blob: 401e50f0767a31b5ac91721c162f42411cc95ff9 [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
Emil Keyder01770b32017-01-20 18:03:11 -0500298 { TM_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 Joshi93b543a2017-06-01 17:32:41 -0700490 DC_PRED, H_PRED, V_PRED, SMOOTH_PRED, TM_PRED,
491#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
494 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,
500 UV_V_PRED, UV_SMOOTH_PRED, UV_TM_PRED,
501#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,
1846#if CONFIG_LGT
1847 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 Joshi9752a2e2017-10-02 17:32:27 -07002215static TX_SIZE tx_size_cost(const AV1_COMP *const cpi,
2216 const MACROBLOCK *const x, BLOCK_SIZE bsize,
2217 TX_SIZE tx_size) {
Urvang Joshifeb925f2016-12-05 10:37:29 -08002218 const AV1_COMMON *const cm = &cpi->common;
Urvang Joshi0d1e4ff2017-04-27 16:17:25 -07002219 const MACROBLOCKD *const xd = &x->e_mbd;
2220 const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Urvang Joshifeb925f2016-12-05 10:37:29 -08002221
Rupert Swarbrick93c39e92017-07-12 11:11:02 +01002222 const int tx_select = cm->tx_mode == TX_MODE_SELECT &&
2223#if CONFIG_EXT_PARTITION_TYPES
2224 // Currently these block shapes can only use 4x4
2225 // transforms
2226 mbmi->sb_type != BLOCK_4X16 &&
2227 mbmi->sb_type != BLOCK_16X4 &&
2228#endif
2229 mbmi->sb_type >= BLOCK_8X8;
Urvang Joshifeb925f2016-12-05 10:37:29 -08002230
2231 if (tx_select) {
2232 const int is_inter = is_inter_block(mbmi);
Urvang Joshi9752a2e2017-10-02 17:32:27 -07002233 const TX_SIZE tx_size_cat = is_inter ? inter_tx_size_cat_lookup[bsize]
2234 : intra_tx_size_cat_lookup[bsize];
Urvang Joshifeb925f2016-12-05 10:37:29 -08002235 const TX_SIZE coded_tx_size = txsize_sqr_up_map[tx_size];
2236 const int depth = tx_size_to_depth(coded_tx_size);
Urvang Joshi9752a2e2017-10-02 17:32:27 -07002237 const TX_SIZE tx_size_ctx = get_tx_size_context(xd);
Yue Chenb23d00a2017-07-28 17:01:21 -07002238 int r_tx_size = x->tx_size_cost[tx_size_cat][tx_size_ctx][depth];
Yue Chend6bdd462017-07-19 16:05:43 -07002239#if CONFIG_RECT_TX_EXT && (CONFIG_EXT_TX || CONFIG_VAR_TX)
Yue Chen56e226e2017-05-02 16:21:40 -07002240 if (is_quarter_tx_allowed(xd, mbmi, is_inter) && tx_size != coded_tx_size)
2241 r_tx_size += av1_cost_bit(cm->fc->quarter_tx_size_prob,
2242 tx_size == quarter_txsize_lookup[bsize]);
Yue Chend6bdd462017-07-19 16:05:43 -07002243#endif
Urvang Joshifeb925f2016-12-05 10:37:29 -08002244 return r_tx_size;
2245 } else {
2246 return 0;
2247 }
2248}
2249
Hui Suddbcde22017-09-18 17:22:02 -07002250// TODO(angiebird): use this function whenever it's possible
Yue Chenb23d00a2017-07-28 17:01:21 -07002251int av1_tx_type_cost(const AV1_COMMON *cm, const MACROBLOCK *x,
2252 const MACROBLOCKD *xd, BLOCK_SIZE bsize, int plane,
2253 TX_SIZE tx_size, TX_TYPE tx_type) {
Angie Chiang05917872017-04-15 12:28:56 -07002254 if (plane > 0) return 0;
2255
Jingning Han243b66b2017-06-23 12:11:47 -07002256#if CONFIG_VAR_TX
2257 tx_size = get_min_tx_size(tx_size);
2258#endif
2259
Angie Chiang65201562017-04-10 15:23:28 -07002260 const MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
2261 const int is_inter = is_inter_block(mbmi);
2262#if CONFIG_EXT_TX
Angie Chiang65201562017-04-10 15:23:28 -07002263 if (get_ext_tx_types(tx_size, bsize, is_inter, cm->reduced_tx_set_used) > 1 &&
2264 !xd->lossless[xd->mi[0]->mbmi.segment_id]) {
2265 const int ext_tx_set =
2266 get_ext_tx_set(tx_size, bsize, is_inter, cm->reduced_tx_set_used);
2267 if (is_inter) {
2268 if (ext_tx_set > 0)
Yue Chenb23d00a2017-07-28 17:01:21 -07002269 return x
Angie Chiang65201562017-04-10 15:23:28 -07002270 ->inter_tx_type_costs[ext_tx_set][txsize_sqr_map[tx_size]][tx_type];
2271 } else {
2272 if (ext_tx_set > 0 && ALLOW_INTRA_EXT_TX)
Yue Chenb23d00a2017-07-28 17:01:21 -07002273 return x->intra_tx_type_costs[ext_tx_set][txsize_sqr_map[tx_size]]
2274 [mbmi->mode][tx_type];
Angie Chiang65201562017-04-10 15:23:28 -07002275 }
2276 }
2277#else
2278 (void)bsize;
Yue Chenb23d00a2017-07-28 17:01:21 -07002279 (void)cm;
Angie Chiang65201562017-04-10 15:23:28 -07002280 if (tx_size < TX_32X32 && !xd->lossless[xd->mi[0]->mbmi.segment_id] &&
2281 !FIXED_TX_TYPE) {
2282 if (is_inter) {
Yue Chenb23d00a2017-07-28 17:01:21 -07002283 return x->inter_tx_type_costs[tx_size][tx_type];
Angie Chiang65201562017-04-10 15:23:28 -07002284 } else {
Yue Chenb23d00a2017-07-28 17:01:21 -07002285 return x->intra_tx_type_costs[tx_size]
2286 [intra_mode_to_tx_type_context[mbmi->mode]]
2287 [tx_type];
Angie Chiang65201562017-04-10 15:23:28 -07002288 }
2289 }
2290#endif // CONFIG_EXT_TX
2291 return 0;
2292}
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002293static int64_t txfm_yrd(const AV1_COMP *const cpi, MACROBLOCK *x,
2294 RD_STATS *rd_stats, int64_t ref_best_rd, BLOCK_SIZE bs,
Urvang Joshi9752a2e2017-10-02 17:32:27 -07002295 TX_TYPE tx_type, TX_SIZE tx_size) {
Urvang Joshi52648442016-10-13 17:27:51 -07002296 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002297 MACROBLOCKD *const xd = &x->e_mbd;
2298 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
2299 int64_t rd = INT64_MAX;
Yaowu Xuf883b422016-08-30 14:01:10 -07002300 aom_prob skip_prob = av1_get_skip_prob(cm, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002301 int s0, s1;
2302 const int is_inter = is_inter_block(mbmi);
Jingning Hanbf9c6b72016-12-14 14:50:45 -08002303 const int tx_select =
2304 cm->tx_mode == TX_MODE_SELECT && mbmi->sb_type >= BLOCK_8X8;
Urvang Joshifeb925f2016-12-05 10:37:29 -08002305
2306 const int r_tx_size = tx_size_cost(cpi, x, bs, tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002307
Yushin Chocd4f4a22017-07-10 18:19:05 -07002308#if CONFIG_PVQ
2309 assert(tx_size >= TX_4X4);
2310#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -07002311 assert(skip_prob > 0);
2312#if CONFIG_EXT_TX && CONFIG_RECT_TX
2313 assert(IMPLIES(is_rect_tx(tx_size), is_rect_tx_allowed_bsize(bs)));
2314#endif // CONFIG_EXT_TX && CONFIG_RECT_TX
2315
Yaowu Xuf883b422016-08-30 14:01:10 -07002316 s0 = av1_cost_bit(skip_prob, 0);
2317 s1 = av1_cost_bit(skip_prob, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002318
2319 mbmi->tx_type = tx_type;
2320 mbmi->tx_size = tx_size;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002321 txfm_rd_in_plane(x, cpi, rd_stats, ref_best_rd, 0, bs, tx_size,
Yaowu Xuc27fc142016-08-22 16:08:15 -07002322 cpi->sf.use_fast_coef_costing);
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002323 if (rd_stats->rate == INT_MAX) return INT64_MAX;
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002324#if !CONFIG_TXK_SEL
Angie Chiang05917872017-04-15 12:28:56 -07002325 int plane = 0;
Yue Chenb23d00a2017-07-28 17:01:21 -07002326 rd_stats->rate += av1_tx_type_cost(cm, x, xd, bs, plane, tx_size, tx_type);
Angie Chiang05917872017-04-15 12:28:56 -07002327#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07002328
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002329 if (rd_stats->skip) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07002330 if (is_inter) {
Urvang Joshi70006e42017-06-14 16:08:55 -07002331 rd = RDCOST(x->rdmult, s1, rd_stats->sse);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002332 } else {
Urvang Joshi70006e42017-06-14 16:08:55 -07002333 rd = RDCOST(x->rdmult, s1 + r_tx_size * tx_select, rd_stats->sse);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002334 }
2335 } else {
Urvang Joshi70006e42017-06-14 16:08:55 -07002336 rd = RDCOST(x->rdmult, rd_stats->rate + s0 + r_tx_size * tx_select,
2337 rd_stats->dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002338 }
2339
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002340 if (tx_select) rd_stats->rate += r_tx_size;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002341
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002342 if (is_inter && !xd->lossless[xd->mi[0]->mbmi.segment_id] &&
2343 !(rd_stats->skip))
Urvang Joshi70006e42017-06-14 16:08:55 -07002344 rd = AOMMIN(rd, RDCOST(x->rdmult, s1, rd_stats->sse));
Yaowu Xuc27fc142016-08-22 16:08:15 -07002345
2346 return rd;
2347}
2348
Angie Chiang2d147c12017-04-05 11:23:59 -07002349static int skip_txfm_search(const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs,
2350 TX_TYPE tx_type, TX_SIZE tx_size) {
Urvang Joshi0d1e4ff2017-04-27 16:17:25 -07002351 const MACROBLOCKD *const xd = &x->e_mbd;
2352 const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Angie Chiang2d147c12017-04-05 11:23:59 -07002353 const TX_SIZE max_tx_size = max_txsize_lookup[bs];
2354 const int is_inter = is_inter_block(mbmi);
2355 int prune = 0;
2356 if (is_inter && cpi->sf.tx_type_search.prune_mode > NO_PRUNE)
2357 // passing -1 in for tx_type indicates that all 1D
2358 // transforms should be considered for pruning
2359 prune = prune_tx_types(cpi, bs, x, xd, -1);
2360
Sarah Parker53f93db2017-07-11 17:20:04 -07002361#if CONFIG_MRC_TX
2362 // MRC_DCT only implemented for TX_32X32 so only include this tx in
2363 // the search for TX_32X32
Sarah Parker2e08d962017-08-01 19:51:20 -07002364 if (tx_type == MRC_DCT &&
2365 ((is_inter && !USE_MRC_INTER) || (!is_inter && !USE_MRC_INTRA) ||
2366 tx_size != TX_32X32))
2367 return 1;
Sarah Parker53f93db2017-07-11 17:20:04 -07002368#endif // CONFIG_MRC_TX
Angie Chianga4fa1902017-04-05 15:26:09 -07002369 if (mbmi->ref_mv_idx > 0 && tx_type != DCT_DCT) return 1;
Angie Chiang2d147c12017-04-05 11:23:59 -07002370 if (FIXED_TX_TYPE && tx_type != get_default_tx_type(0, xd, 0, tx_size))
2371 return 1;
2372 if (!is_inter && x->use_default_intra_tx_type &&
2373 tx_type != get_default_tx_type(0, xd, 0, tx_size))
2374 return 1;
2375 if (is_inter && x->use_default_inter_tx_type &&
2376 tx_type != get_default_tx_type(0, xd, 0, tx_size))
2377 return 1;
2378 if (max_tx_size >= TX_32X32 && tx_size == TX_4X4) return 1;
2379#if CONFIG_EXT_TX
2380 const AV1_COMMON *const cm = &cpi->common;
Hui Suddbcde22017-09-18 17:22:02 -07002381 const TxSetType tx_set_type =
2382 get_ext_tx_set_type(tx_size, bs, is_inter, cm->reduced_tx_set_used);
2383 if (!av1_ext_tx_used[tx_set_type][tx_type]) return 1;
Angie Chiang2d147c12017-04-05 11:23:59 -07002384 if (is_inter) {
Angie Chiang2d147c12017-04-05 11:23:59 -07002385 if (cpi->sf.tx_type_search.prune_mode > NO_PRUNE) {
2386 if (!do_tx_type_search(tx_type, prune)) return 1;
2387 }
2388 } else {
2389 if (!ALLOW_INTRA_EXT_TX && bs >= BLOCK_8X8) {
2390 if (tx_type != intra_mode_to_tx_type_context[mbmi->mode]) return 1;
2391 }
Angie Chiang2d147c12017-04-05 11:23:59 -07002392 }
2393#else // CONFIG_EXT_TX
2394 if (tx_size >= TX_32X32 && tx_type != DCT_DCT) return 1;
2395 if (is_inter && cpi->sf.tx_type_search.prune_mode > NO_PRUNE &&
2396 !do_tx_type_search(tx_type, prune))
2397 return 1;
2398#endif // CONFIG_EXT_TX
2399 return 0;
2400}
2401
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02002402#if (CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT || CONFIG_INTERINTRA)
Urvang Joshi52648442016-10-13 17:27:51 -07002403static int64_t estimate_yrd_for_sb(const AV1_COMP *const cpi, BLOCK_SIZE bs,
2404 MACROBLOCK *x, int *r, int64_t *d, int *s,
2405 int64_t *sse, int64_t ref_best_rd) {
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002406 RD_STATS rd_stats;
2407 int64_t rd = txfm_yrd(cpi, x, &rd_stats, ref_best_rd, bs, DCT_DCT,
2408 max_txsize_lookup[bs]);
2409 *r = rd_stats.rate;
2410 *d = rd_stats.dist;
2411 *s = rd_stats.skip;
2412 *sse = rd_stats.sse;
2413 return rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002414}
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02002415#endif // (CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT)
Yaowu Xuc27fc142016-08-22 16:08:15 -07002416
Urvang Joshi52648442016-10-13 17:27:51 -07002417static void choose_largest_tx_size(const AV1_COMP *const cpi, MACROBLOCK *x,
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002418 RD_STATS *rd_stats, int64_t ref_best_rd,
Urvang Joshi52648442016-10-13 17:27:51 -07002419 BLOCK_SIZE bs) {
2420 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002421 MACROBLOCKD *const xd = &x->e_mbd;
2422 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
2423 TX_TYPE tx_type, best_tx_type = DCT_DCT;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002424 int64_t this_rd, best_rd = INT64_MAX;
Yaowu Xuf883b422016-08-30 14:01:10 -07002425 aom_prob skip_prob = av1_get_skip_prob(cm, xd);
2426 int s0 = av1_cost_bit(skip_prob, 0);
2427 int s1 = av1_cost_bit(skip_prob, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002428 const int is_inter = is_inter_block(mbmi);
2429 int prune = 0;
Angie Chiangaa0c34b2017-04-25 12:25:38 -07002430 const int plane = 0;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002431 av1_invalid_rd_stats(rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002432
2433 mbmi->tx_size = tx_size_from_tx_mode(bs, cm->tx_mode, is_inter);
Jingning Hane67b38a2016-11-04 10:30:00 -07002434#if CONFIG_VAR_TX
2435 mbmi->min_tx_size = get_min_tx_size(mbmi->tx_size);
Fergus Simpson4063a682017-02-28 16:52:22 -08002436#endif // CONFIG_VAR_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07002437#if CONFIG_EXT_TX
Hui Suddbcde22017-09-18 17:22:02 -07002438 int ext_tx_set =
Sarah Parkere68a3e42017-02-16 14:03:24 -08002439 get_ext_tx_set(mbmi->tx_size, bs, is_inter, cm->reduced_tx_set_used);
Hui Suddbcde22017-09-18 17:22:02 -07002440 const TxSetType tx_set_type =
2441 get_ext_tx_set_type(mbmi->tx_size, bs, is_inter, cm->reduced_tx_set_used);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002442#endif // CONFIG_EXT_TX
2443
2444 if (is_inter && cpi->sf.tx_type_search.prune_mode > NO_PRUNE)
2445#if CONFIG_EXT_TX
2446 prune = prune_tx_types(cpi, bs, x, xd, ext_tx_set);
2447#else
2448 prune = prune_tx_types(cpi, bs, x, xd, 0);
Fergus Simpson4063a682017-02-28 16:52:22 -08002449#endif // CONFIG_EXT_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07002450#if CONFIG_EXT_TX
Sarah Parkere68a3e42017-02-16 14:03:24 -08002451 if (get_ext_tx_types(mbmi->tx_size, bs, is_inter, cm->reduced_tx_set_used) >
2452 1 &&
Yaowu Xuc27fc142016-08-22 16:08:15 -07002453 !xd->lossless[mbmi->segment_id]) {
Yushin Cho77bba8d2016-11-04 16:36:56 -07002454#if CONFIG_PVQ
2455 od_rollback_buffer pre_buf, post_buf;
2456
2457 od_encode_checkpoint(&x->daala_enc, &pre_buf);
2458 od_encode_checkpoint(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08002459#endif // CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -07002460
2461 for (tx_type = DCT_DCT; tx_type < TX_TYPES; ++tx_type) {
Hui Suddbcde22017-09-18 17:22:02 -07002462 if (!av1_ext_tx_used[tx_set_type][tx_type]) continue;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002463 RD_STATS this_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002464 if (is_inter) {
2465 if (x->use_default_inter_tx_type &&
2466 tx_type != get_default_tx_type(0, xd, 0, mbmi->tx_size))
2467 continue;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002468 if (cpi->sf.tx_type_search.prune_mode > NO_PRUNE) {
2469 if (!do_tx_type_search(tx_type, prune)) continue;
2470 }
2471 } else {
2472 if (x->use_default_intra_tx_type &&
2473 tx_type != get_default_tx_type(0, xd, 0, mbmi->tx_size))
2474 continue;
2475 if (!ALLOW_INTRA_EXT_TX && bs >= BLOCK_8X8) {
2476 if (tx_type != intra_mode_to_tx_type_context[mbmi->mode]) continue;
2477 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07002478 }
2479
2480 mbmi->tx_type = tx_type;
2481
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002482 txfm_rd_in_plane(x, cpi, &this_rd_stats, ref_best_rd, 0, bs,
Yaowu Xuc27fc142016-08-22 16:08:15 -07002483 mbmi->tx_size, cpi->sf.use_fast_coef_costing);
Yushin Cho77bba8d2016-11-04 16:36:56 -07002484#if CONFIG_PVQ
2485 od_encode_rollback(&x->daala_enc, &pre_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08002486#endif // CONFIG_PVQ
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002487 if (this_rd_stats.rate == INT_MAX) continue;
Yue Chenb23d00a2017-07-28 17:01:21 -07002488 av1_tx_type_cost(cm, x, xd, bs, plane, mbmi->tx_size, tx_type);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002489
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002490 if (this_rd_stats.skip)
Urvang Joshi70006e42017-06-14 16:08:55 -07002491 this_rd = RDCOST(x->rdmult, s1, this_rd_stats.sse);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002492 else
Urvang Joshi70006e42017-06-14 16:08:55 -07002493 this_rd =
2494 RDCOST(x->rdmult, this_rd_stats.rate + s0, this_rd_stats.dist);
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002495 if (is_inter_block(mbmi) && !xd->lossless[mbmi->segment_id] &&
2496 !this_rd_stats.skip)
Urvang Joshi70006e42017-06-14 16:08:55 -07002497 this_rd = AOMMIN(this_rd, RDCOST(x->rdmult, s1, this_rd_stats.sse));
Yaowu Xuc27fc142016-08-22 16:08:15 -07002498
2499 if (this_rd < best_rd) {
2500 best_rd = this_rd;
2501 best_tx_type = mbmi->tx_type;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002502 *rd_stats = this_rd_stats;
Yushin Cho77bba8d2016-11-04 16:36:56 -07002503#if CONFIG_PVQ
2504 od_encode_checkpoint(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08002505#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -07002506 }
2507 }
Yushin Cho77bba8d2016-11-04 16:36:56 -07002508#if CONFIG_PVQ
2509 od_encode_rollback(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08002510#endif // CONFIG_PVQ
Guillaume Martres4e4d3a02016-08-21 19:02:33 -07002511 } else {
2512 mbmi->tx_type = DCT_DCT;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002513 txfm_rd_in_plane(x, cpi, rd_stats, ref_best_rd, 0, bs, mbmi->tx_size,
2514 cpi->sf.use_fast_coef_costing);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002515 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07002516#else // CONFIG_EXT_TX
2517 if (mbmi->tx_size < TX_32X32 && !xd->lossless[mbmi->segment_id]) {
2518 for (tx_type = 0; tx_type < TX_TYPES; ++tx_type) {
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002519 RD_STATS this_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002520 if (!is_inter && x->use_default_intra_tx_type &&
2521 tx_type != get_default_tx_type(0, xd, 0, mbmi->tx_size))
2522 continue;
2523 if (is_inter && x->use_default_inter_tx_type &&
2524 tx_type != get_default_tx_type(0, xd, 0, mbmi->tx_size))
2525 continue;
2526 mbmi->tx_type = tx_type;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002527 txfm_rd_in_plane(x, cpi, &this_rd_stats, ref_best_rd, 0, bs,
Yaowu Xuc27fc142016-08-22 16:08:15 -07002528 mbmi->tx_size, cpi->sf.use_fast_coef_costing);
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002529 if (this_rd_stats.rate == INT_MAX) continue;
Angie Chiangaa0c34b2017-04-25 12:25:38 -07002530
Yue Chenb23d00a2017-07-28 17:01:21 -07002531 av1_tx_type_cost(cm, x, xd, bs, plane, mbmi->tx_size, tx_type);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002532 if (is_inter) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07002533 if (cpi->sf.tx_type_search.prune_mode > NO_PRUNE &&
2534 !do_tx_type_search(tx_type, prune))
2535 continue;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002536 }
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002537 if (this_rd_stats.skip)
Urvang Joshi70006e42017-06-14 16:08:55 -07002538 this_rd = RDCOST(x->rdmult, s1, this_rd_stats.sse);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002539 else
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002540 this_rd =
Urvang Joshi70006e42017-06-14 16:08:55 -07002541 RDCOST(x->rdmult, this_rd_stats.rate + s0, this_rd_stats.dist);
2542 if (is_inter && !xd->lossless[mbmi->segment_id] && !this_rd_stats.skip)
2543 this_rd = AOMMIN(this_rd, RDCOST(x->rdmult, s1, this_rd_stats.sse));
Yaowu Xuc27fc142016-08-22 16:08:15 -07002544
2545 if (this_rd < best_rd) {
2546 best_rd = this_rd;
2547 best_tx_type = mbmi->tx_type;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002548 *rd_stats = this_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002549 }
2550 }
Guillaume Martres4e4d3a02016-08-21 19:02:33 -07002551 } else {
2552 mbmi->tx_type = DCT_DCT;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002553 txfm_rd_in_plane(x, cpi, rd_stats, ref_best_rd, 0, bs, mbmi->tx_size,
2554 cpi->sf.use_fast_coef_costing);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002555 }
2556#endif // CONFIG_EXT_TX
2557 mbmi->tx_type = best_tx_type;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002558}
2559
Urvang Joshi52648442016-10-13 17:27:51 -07002560static void choose_smallest_tx_size(const AV1_COMP *const cpi, MACROBLOCK *x,
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002561 RD_STATS *rd_stats, int64_t ref_best_rd,
Yaowu Xuc27fc142016-08-22 16:08:15 -07002562 BLOCK_SIZE bs) {
2563 MACROBLOCKD *const xd = &x->e_mbd;
2564 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
2565
2566 mbmi->tx_size = TX_4X4;
2567 mbmi->tx_type = DCT_DCT;
Jingning Hane67b38a2016-11-04 10:30:00 -07002568#if CONFIG_VAR_TX
2569 mbmi->min_tx_size = get_min_tx_size(TX_4X4);
Fergus Simpson4063a682017-02-28 16:52:22 -08002570#endif // CONFIG_VAR_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07002571
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002572 txfm_rd_in_plane(x, cpi, rd_stats, ref_best_rd, 0, bs, mbmi->tx_size,
2573 cpi->sf.use_fast_coef_costing);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002574}
2575
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002576#if CONFIG_TXK_SEL || CONFIG_VAR_TX
Angie Chiangf1cb0752017-04-10 16:01:20 -07002577static INLINE int bsize_to_num_blk(BLOCK_SIZE bsize) {
2578 int num_blk = 1 << (num_pels_log2_lookup[bsize] - 2 * tx_size_wide_log2[0]);
2579 return num_blk;
2580}
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002581#endif // CONFIG_TXK_SEL || CONFIG_VAR_TX
Angie Chiangf1cb0752017-04-10 16:01:20 -07002582
Urvang Joshi52648442016-10-13 17:27:51 -07002583static void choose_tx_size_type_from_rd(const AV1_COMP *const cpi,
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002584 MACROBLOCK *x, RD_STATS *rd_stats,
2585 int64_t ref_best_rd, BLOCK_SIZE bs) {
Angie Chianga4fa1902017-04-05 15:26:09 -07002586 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002587 MACROBLOCKD *const xd = &x->e_mbd;
2588 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002589 int64_t rd = INT64_MAX;
Angie Chianga4fa1902017-04-05 15:26:09 -07002590 int n;
2591 int start_tx, end_tx;
2592 int64_t best_rd = INT64_MAX, last_rd = INT64_MAX;
2593 const TX_SIZE max_tx_size = max_txsize_lookup[bs];
2594 TX_SIZE best_tx_size = max_tx_size;
2595 TX_TYPE best_tx_type = DCT_DCT;
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002596#if CONFIG_TXK_SEL
Angie Chiangf1cb0752017-04-10 16:01:20 -07002597 TX_TYPE best_txk_type[MAX_SB_SQUARE / (TX_SIZE_W_MIN * TX_SIZE_H_MIN)];
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002598#endif // CONFIG_TXK_SEL
Angie Chianga4fa1902017-04-05 15:26:09 -07002599 const int tx_select = cm->tx_mode == TX_MODE_SELECT;
2600 const int is_inter = is_inter_block(mbmi);
Yushin Cho77bba8d2016-11-04 16:36:56 -07002601#if CONFIG_PVQ
2602 od_rollback_buffer buf;
Yushin Cho77bba8d2016-11-04 16:36:56 -07002603 od_encode_checkpoint(&x->daala_enc, &buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08002604#endif // CONFIG_PVQ
Angie Chianga4fa1902017-04-05 15:26:09 -07002605
2606 av1_invalid_rd_stats(rd_stats);
2607
2608#if CONFIG_EXT_TX && CONFIG_RECT_TX
2609 int evaluate_rect_tx = 0;
2610 if (tx_select) {
2611 evaluate_rect_tx = is_rect_tx_allowed(xd, mbmi);
2612 } else {
2613 const TX_SIZE chosen_tx_size =
2614 tx_size_from_tx_mode(bs, cm->tx_mode, is_inter);
2615 evaluate_rect_tx = is_rect_tx(chosen_tx_size);
2616 assert(IMPLIES(evaluate_rect_tx, is_rect_tx_allowed(xd, mbmi)));
2617 }
2618 if (evaluate_rect_tx) {
Angie Chiangf1cb0752017-04-10 16:01:20 -07002619 TX_TYPE tx_start = DCT_DCT;
2620 TX_TYPE tx_end = TX_TYPES;
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002621#if CONFIG_TXK_SEL
Angie Chiangf1cb0752017-04-10 16:01:20 -07002622 // The tx_type becomes dummy when lv_map is on. The tx_type search will be
2623 // performed in av1_search_txk_type()
2624 tx_end = DCT_DCT + 1;
2625#endif
Angie Chianga4fa1902017-04-05 15:26:09 -07002626 TX_TYPE tx_type;
Angie Chiangf1cb0752017-04-10 16:01:20 -07002627 for (tx_type = tx_start; tx_type < tx_end; ++tx_type) {
Angie Chianga4fa1902017-04-05 15:26:09 -07002628 if (mbmi->ref_mv_idx > 0 && tx_type != DCT_DCT) continue;
Angie Chianga4fa1902017-04-05 15:26:09 -07002629 const TX_SIZE rect_tx_size = max_txsize_rect_lookup[bs];
2630 RD_STATS this_rd_stats;
Hui Suddbcde22017-09-18 17:22:02 -07002631 const TxSetType tx_set_type = get_ext_tx_set_type(
2632 rect_tx_size, bs, is_inter, cm->reduced_tx_set_used);
2633 if (av1_ext_tx_used[tx_set_type][tx_type]) {
Angie Chianga4fa1902017-04-05 15:26:09 -07002634 rd = txfm_yrd(cpi, x, &this_rd_stats, ref_best_rd, bs, tx_type,
2635 rect_tx_size);
Hui Suda816a12017-08-18 14:46:02 -07002636 ref_best_rd = AOMMIN(rd, ref_best_rd);
Angie Chianga4fa1902017-04-05 15:26:09 -07002637 if (rd < best_rd) {
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002638#if CONFIG_TXK_SEL
Jingning Han19b5c8f2017-07-06 15:10:12 -07002639 memcpy(best_txk_type, mbmi->txk_type, sizeof(best_txk_type[0]) * 256);
Angie Chiangf1cb0752017-04-10 16:01:20 -07002640#endif
Angie Chianga4fa1902017-04-05 15:26:09 -07002641 best_tx_type = tx_type;
2642 best_tx_size = rect_tx_size;
2643 best_rd = rd;
2644 *rd_stats = this_rd_stats;
2645 }
2646 }
Debargha Mukherjee094c9432017-02-22 10:31:25 -08002647#if CONFIG_CB4X4 && !USE_TXTYPE_SEARCH_FOR_SUB8X8_IN_CB4X4
Angie Chianga4fa1902017-04-05 15:26:09 -07002648 const int is_inter = is_inter_block(mbmi);
2649 if (mbmi->sb_type < BLOCK_8X8 && is_inter) break;
Fergus Simpson4063a682017-02-28 16:52:22 -08002650#endif // CONFIG_CB4X4 && !USE_TXTYPE_SEARCH_FOR_SUB8X8_IN_CB4X4
Angie Chianga4fa1902017-04-05 15:26:09 -07002651 }
2652 }
Yue Chen56e226e2017-05-02 16:21:40 -07002653
2654#if CONFIG_RECT_TX_EXT
2655 // test 1:4/4:1 tx
2656 int evaluate_quarter_tx = 0;
2657 if (is_quarter_tx_allowed(xd, mbmi, is_inter)) {
2658 if (tx_select) {
2659 evaluate_quarter_tx = 1;
2660 } else {
2661 const TX_SIZE chosen_tx_size =
2662 tx_size_from_tx_mode(bs, cm->tx_mode, is_inter);
2663 evaluate_quarter_tx = chosen_tx_size == quarter_txsize_lookup[bs];
2664 }
2665 }
2666 if (evaluate_quarter_tx) {
2667 TX_TYPE tx_start = DCT_DCT;
2668 TX_TYPE tx_end = TX_TYPES;
2669#if CONFIG_TXK_SEL
2670 // The tx_type becomes dummy when lv_map is on. The tx_type search will be
2671 // performed in av1_search_txk_type()
2672 tx_end = DCT_DCT + 1;
2673#endif
2674 TX_TYPE tx_type;
2675 for (tx_type = tx_start; tx_type < tx_end; ++tx_type) {
2676 if (mbmi->ref_mv_idx > 0 && tx_type != DCT_DCT) continue;
2677 const TX_SIZE tx_size = quarter_txsize_lookup[bs];
2678 RD_STATS this_rd_stats;
Hui Suddbcde22017-09-18 17:22:02 -07002679 const TxSetType tx_set_type =
2680 get_ext_tx_set_type(tx_size, bs, is_inter, cm->reduced_tx_set_used);
2681 if (av1_ext_tx_used[tx_set_type][tx_type]) {
Yue Chen56e226e2017-05-02 16:21:40 -07002682 rd =
2683 txfm_yrd(cpi, x, &this_rd_stats, ref_best_rd, bs, tx_type, tx_size);
2684 if (rd < best_rd) {
2685#if CONFIG_TXK_SEL
2686 memcpy(best_txk_type, mbmi->txk_type,
2687 sizeof(best_txk_type[0]) * num_blk);
2688#endif
2689 best_tx_type = tx_type;
2690 best_tx_size = tx_size;
2691 best_rd = rd;
2692 *rd_stats = this_rd_stats;
2693 }
2694 }
2695#if CONFIG_CB4X4 && !USE_TXTYPE_SEARCH_FOR_SUB8X8_IN_CB4X4
2696 const int is_inter = is_inter_block(mbmi);
2697 if (mbmi->sb_type < BLOCK_8X8 && is_inter) break;
2698#endif // CONFIG_CB4X4 && !USE_TXTYPE_SEARCH_FOR_SUB8X8_IN_CB4X4
2699 }
2700 }
2701#endif // CONFIG_RECT_TX_EXT
Angie Chianga4fa1902017-04-05 15:26:09 -07002702#endif // CONFIG_EXT_TX && CONFIG_RECT_TX
2703
2704 if (tx_select) {
2705 start_tx = max_tx_size;
2706 end_tx = (max_tx_size >= TX_32X32) ? TX_8X8 : TX_4X4;
2707 } else {
2708 const TX_SIZE chosen_tx_size =
2709 tx_size_from_tx_mode(bs, cm->tx_mode, is_inter);
2710 start_tx = chosen_tx_size;
2711 end_tx = chosen_tx_size;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002712 }
2713
Angie Chianga4fa1902017-04-05 15:26:09 -07002714 last_rd = INT64_MAX;
2715 for (n = start_tx; n >= end_tx; --n) {
Sarah Parker36661922017-04-13 14:26:49 -07002716#if CONFIG_EXT_TX && CONFIG_RECT_TX
2717 if (is_rect_tx(n)) break;
2718#endif // CONFIG_EXT_TX && CONFIG_RECT_TX
Angie Chiangf1cb0752017-04-10 16:01:20 -07002719 TX_TYPE tx_start = DCT_DCT;
2720 TX_TYPE tx_end = TX_TYPES;
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002721#if CONFIG_TXK_SEL
Angie Chiangf1cb0752017-04-10 16:01:20 -07002722 // The tx_type becomes dummy when lv_map is on. The tx_type search will be
2723 // performed in av1_search_txk_type()
2724 tx_end = DCT_DCT + 1;
2725#endif
Angie Chianga4fa1902017-04-05 15:26:09 -07002726 TX_TYPE tx_type;
Angie Chiangf1cb0752017-04-10 16:01:20 -07002727 for (tx_type = tx_start; tx_type < tx_end; ++tx_type) {
Angie Chianga4fa1902017-04-05 15:26:09 -07002728 RD_STATS this_rd_stats;
2729 if (skip_txfm_search(cpi, x, bs, tx_type, n)) continue;
2730 rd = txfm_yrd(cpi, x, &this_rd_stats, ref_best_rd, bs, tx_type, n);
2731#if CONFIG_PVQ
2732 od_encode_rollback(&x->daala_enc, &buf);
2733#endif // CONFIG_PVQ
2734 // Early termination in transform size search.
2735 if (cpi->sf.tx_size_search_breakout &&
2736 (rd == INT64_MAX ||
2737 (this_rd_stats.skip == 1 && tx_type != DCT_DCT && n < start_tx) ||
2738 (n < (int)max_tx_size && rd > last_rd)))
2739 break;
2740
2741 last_rd = rd;
Hui Suda816a12017-08-18 14:46:02 -07002742 ref_best_rd = AOMMIN(rd, ref_best_rd);
Angie Chianga4fa1902017-04-05 15:26:09 -07002743 if (rd < best_rd) {
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002744#if CONFIG_TXK_SEL
Jingning Han19b5c8f2017-07-06 15:10:12 -07002745 memcpy(best_txk_type, mbmi->txk_type, sizeof(best_txk_type[0]) * 256);
Angie Chiangf1cb0752017-04-10 16:01:20 -07002746#endif
Angie Chianga4fa1902017-04-05 15:26:09 -07002747 best_tx_type = tx_type;
2748 best_tx_size = n;
2749 best_rd = rd;
2750 *rd_stats = this_rd_stats;
2751 }
2752#if CONFIG_CB4X4 && !USE_TXTYPE_SEARCH_FOR_SUB8X8_IN_CB4X4
2753 const int is_inter = is_inter_block(mbmi);
2754 if (mbmi->sb_type < BLOCK_8X8 && is_inter) break;
2755#endif // CONFIG_CB4X4 && !USE_TXTYPE_SEARCH_FOR_SUB8X8_IN_CB4X4
2756 }
2757 }
2758 mbmi->tx_size = best_tx_size;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002759 mbmi->tx_type = best_tx_type;
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002760#if CONFIG_TXK_SEL
Jingning Han19b5c8f2017-07-06 15:10:12 -07002761 memcpy(mbmi->txk_type, best_txk_type, sizeof(best_txk_type[0]) * 256);
Angie Chiangf1cb0752017-04-10 16:01:20 -07002762#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07002763
Jingning Hane67b38a2016-11-04 10:30:00 -07002764#if CONFIG_VAR_TX
2765 mbmi->min_tx_size = get_min_tx_size(mbmi->tx_size);
Fergus Simpson4063a682017-02-28 16:52:22 -08002766#endif // CONFIG_VAR_TX
Jingning Hane67b38a2016-11-04 10:30:00 -07002767
Yaowu Xuc27fc142016-08-22 16:08:15 -07002768#if !CONFIG_EXT_TX
2769 if (mbmi->tx_size >= TX_32X32) assert(mbmi->tx_type == DCT_DCT);
Fergus Simpson4063a682017-02-28 16:52:22 -08002770#endif // !CONFIG_EXT_TX
Yushin Cho77bba8d2016-11-04 16:36:56 -07002771#if CONFIG_PVQ
Yushin Cho403618e2016-11-09 10:45:32 -08002772 if (best_rd != INT64_MAX) {
Angie Chianga4fa1902017-04-05 15:26:09 -07002773 txfm_yrd(cpi, x, rd_stats, ref_best_rd, bs, best_tx_type, best_tx_size);
Yushin Cho05f540a2016-11-08 22:12:51 -08002774 }
Fergus Simpson4063a682017-02-28 16:52:22 -08002775#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -07002776}
2777
Angie Chiang0e9a2e92016-11-08 09:45:40 -08002778static void super_block_yrd(const AV1_COMP *const cpi, MACROBLOCK *x,
2779 RD_STATS *rd_stats, BLOCK_SIZE bs,
2780 int64_t ref_best_rd) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07002781 MACROBLOCKD *xd = &x->e_mbd;
Angie Chiang0e9a2e92016-11-08 09:45:40 -08002782 av1_init_rd_stats(rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002783
2784 assert(bs == xd->mi[0]->mbmi.sb_type);
2785
Yaowu Xu1e2aae12017-02-27 16:33:14 -08002786 if (xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Angie Chiang0e9a2e92016-11-08 09:45:40 -08002787 choose_smallest_tx_size(cpi, x, rd_stats, ref_best_rd, bs);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002788 } else if (cpi->sf.tx_size_search_method == USE_LARGESTALL) {
Angie Chiang0e9a2e92016-11-08 09:45:40 -08002789 choose_largest_tx_size(cpi, x, rd_stats, ref_best_rd, bs);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002790 } else {
Angie Chiang0e9a2e92016-11-08 09:45:40 -08002791 choose_tx_size_type_from_rd(cpi, x, rd_stats, ref_best_rd, bs);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002792 }
2793}
2794
2795static int conditional_skipintra(PREDICTION_MODE mode,
2796 PREDICTION_MODE best_intra_mode) {
2797 if (mode == D117_PRED && best_intra_mode != V_PRED &&
2798 best_intra_mode != D135_PRED)
2799 return 1;
2800 if (mode == D63_PRED && best_intra_mode != V_PRED &&
2801 best_intra_mode != D45_PRED)
2802 return 1;
2803 if (mode == D207_PRED && best_intra_mode != H_PRED &&
2804 best_intra_mode != D45_PRED)
2805 return 1;
2806 if (mode == D153_PRED && best_intra_mode != H_PRED &&
2807 best_intra_mode != D135_PRED)
2808 return 1;
2809 return 0;
2810}
2811
hui su308a6392017-01-12 14:49:57 -08002812// Model based RD estimation for luma intra blocks.
2813static int64_t intra_model_yrd(const AV1_COMP *const cpi, MACROBLOCK *const x,
hui su9a416f52017-01-13 11:37:53 -08002814 BLOCK_SIZE bsize, int mode_cost) {
David Barker761b1ac2017-09-25 11:23:03 +01002815 const AV1_COMMON *cm = &cpi->common;
hui su308a6392017-01-12 14:49:57 -08002816 MACROBLOCKD *const xd = &x->e_mbd;
2817 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07002818 assert(!is_inter_block(mbmi));
hui su308a6392017-01-12 14:49:57 -08002819 RD_STATS this_rd_stats;
2820 int row, col;
2821 int64_t temp_sse, this_rd;
2822 const TX_SIZE tx_size = tx_size_from_tx_mode(bsize, cpi->common.tx_mode, 0);
2823 const int stepr = tx_size_high_unit[tx_size];
2824 const int stepc = tx_size_wide_unit[tx_size];
2825 const int max_blocks_wide = max_block_wide(xd, bsize, 0);
2826 const int max_blocks_high = max_block_high(xd, bsize, 0);
2827 mbmi->tx_size = tx_size;
2828 // Prediction.
Angie Chiang3d005e42017-04-02 16:31:35 -07002829 const int step = stepr * stepc;
2830 int block = 0;
hui su308a6392017-01-12 14:49:57 -08002831 for (row = 0; row < max_blocks_high; row += stepr) {
2832 for (col = 0; col < max_blocks_wide; col += stepc) {
David Barker761b1ac2017-09-25 11:23:03 +01002833 av1_predict_intra_block_facade(cm, xd, 0, block, col, row, tx_size);
Angie Chiang3d005e42017-04-02 16:31:35 -07002834 block += step;
hui su308a6392017-01-12 14:49:57 -08002835 }
2836 }
2837 // RD estimation.
2838 model_rd_for_sb(cpi, bsize, x, xd, 0, 0, &this_rd_stats.rate,
2839 &this_rd_stats.dist, &this_rd_stats.skip, &temp_sse);
hui su9a416f52017-01-13 11:37:53 -08002840#if CONFIG_EXT_INTRA
Joe Young830d4ce2017-05-30 17:48:13 -07002841 if (av1_is_directional_mode(mbmi->mode, bsize) &&
2842 av1_use_angle_delta(bsize)) {
hui su0a6731f2017-04-26 15:23:47 -07002843 mode_cost += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
2844 MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
hui su9a416f52017-01-13 11:37:53 -08002845 }
2846#endif // CONFIG_EXT_INTRA
hui su8f4cc0a2017-01-13 15:14:49 -08002847#if CONFIG_FILTER_INTRA
2848 if (mbmi->mode == DC_PRED) {
2849 const aom_prob prob = cpi->common.fc->filter_intra_probs[0];
2850 if (mbmi->filter_intra_mode_info.use_filter_intra_mode[0]) {
2851 const int mode = mbmi->filter_intra_mode_info.filter_intra_mode[0];
2852 mode_cost += (av1_cost_bit(prob, 1) +
2853 write_uniform_cost(FILTER_INTRA_MODES, mode));
2854 } else {
2855 mode_cost += av1_cost_bit(prob, 0);
2856 }
2857 }
2858#endif // CONFIG_FILTER_INTRA
Urvang Joshi70006e42017-06-14 16:08:55 -07002859 this_rd =
2860 RDCOST(x->rdmult, this_rd_stats.rate + mode_cost, this_rd_stats.dist);
hui su308a6392017-01-12 14:49:57 -08002861 return this_rd;
2862}
2863
Urvang Joshi56ba91b2017-01-10 13:22:09 -08002864// Extends 'color_map' array from 'orig_width x orig_height' to 'new_width x
2865// new_height'. Extra rows and columns are filled in by copying last valid
2866// row/column.
2867static void extend_palette_color_map(uint8_t *const color_map, int orig_width,
2868 int orig_height, int new_width,
2869 int new_height) {
2870 int j;
2871 assert(new_width >= orig_width);
2872 assert(new_height >= orig_height);
2873 if (new_width == orig_width && new_height == orig_height) return;
2874
2875 for (j = orig_height - 1; j >= 0; --j) {
2876 memmove(color_map + j * new_width, color_map + j * orig_width, orig_width);
2877 // Copy last column to extra columns.
2878 memset(color_map + j * new_width + orig_width,
2879 color_map[j * new_width + orig_width - 1], new_width - orig_width);
2880 }
2881 // Copy last row to extra rows.
2882 for (j = orig_height; j < new_height; ++j) {
2883 memcpy(color_map + j * new_width, color_map + (orig_height - 1) * new_width,
2884 new_width);
2885 }
2886}
2887
hui su33567b22017-04-30 16:40:19 -07002888#if CONFIG_PALETTE_DELTA_ENCODING
2889// Bias toward using colors in the cache.
2890// TODO(huisu): Try other schemes to improve compression.
2891static void optimize_palette_colors(uint16_t *color_cache, int n_cache,
2892 int n_colors, int stride,
2893 float *centroids) {
2894 if (n_cache <= 0) return;
2895 for (int i = 0; i < n_colors * stride; i += stride) {
2896 float min_diff = fabsf(centroids[i] - color_cache[0]);
2897 int idx = 0;
2898 for (int j = 1; j < n_cache; ++j) {
2899 float this_diff = fabsf(centroids[i] - color_cache[j]);
2900 if (this_diff < min_diff) {
2901 min_diff = this_diff;
2902 idx = j;
2903 }
2904 }
2905 if (min_diff < 1.5) centroids[i] = color_cache[idx];
2906 }
2907}
2908#endif // CONFIG_PALETTE_DELTA_ENCODING
2909
hui sude0c70a2017-01-09 17:12:17 -08002910static int rd_pick_palette_intra_sby(const AV1_COMP *const cpi, MACROBLOCK *x,
2911 BLOCK_SIZE bsize, int palette_ctx,
2912 int dc_mode_cost, MB_MODE_INFO *best_mbmi,
2913 uint8_t *best_palette_color_map,
hui su78c611a2017-01-13 17:06:04 -08002914 int64_t *best_rd, int64_t *best_model_rd,
2915 int *rate, int *rate_tokenonly,
2916 int64_t *distortion, int *skippable) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07002917 int rate_overhead = 0;
2918 MACROBLOCKD *const xd = &x->e_mbd;
2919 MODE_INFO *const mic = xd->mi[0];
hui sude0c70a2017-01-09 17:12:17 -08002920 MB_MODE_INFO *const mbmi = &mic->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07002921 assert(!is_inter_block(mbmi));
Urvang Joshic9e71d42017-08-09 18:58:33 -07002922 assert(bsize >= BLOCK_8X8);
Angie Chiang0e9a2e92016-11-08 09:45:40 -08002923 int this_rate, colors, n;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002924 const int src_stride = x->plane[0].src.stride;
2925 const uint8_t *const src = x->plane[0].src.buf;
hui sude0c70a2017-01-09 17:12:17 -08002926 uint8_t *const color_map = xd->plane[0].color_index_map;
Urvang Joshi56ba91b2017-01-10 13:22:09 -08002927 int block_width, block_height, rows, cols;
2928 av1_get_block_dimensions(bsize, 0, xd, &block_width, &block_height, &rows,
2929 &cols);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002930
2931 assert(cpi->common.allow_screen_content_tools);
2932
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02002933#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07002934 if (cpi->common.use_highbitdepth)
Yaowu Xuf883b422016-08-30 14:01:10 -07002935 colors = av1_count_colors_highbd(src, src_stride, rows, cols,
2936 cpi->common.bit_depth);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002937 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02002938#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuf883b422016-08-30 14:01:10 -07002939 colors = av1_count_colors(src, src_stride, rows, cols);
hui su5db97432016-10-14 16:10:14 -07002940#if CONFIG_FILTER_INTRA
hui sude0c70a2017-01-09 17:12:17 -08002941 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] = 0;
hui su5db97432016-10-14 16:10:14 -07002942#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07002943
2944 if (colors > 1 && colors <= 64) {
Sarah Parker9c0e4512017-08-15 16:23:53 -07002945 int r, c, i, k, palette_mode_cost;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002946 const int max_itr = 50;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002947 float *const data = x->palette_buffer->kmeans_data_buf;
2948 float centroids[PALETTE_MAX_SIZE];
Yaowu Xuc27fc142016-08-22 16:08:15 -07002949 float lb, ub, val;
hui su78c611a2017-01-13 17:06:04 -08002950 RD_STATS tokenonly_rd_stats;
2951 int64_t this_rd, this_model_rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002952 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02002953#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07002954 uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
2955 if (cpi->common.use_highbitdepth)
2956 lb = ub = src16[0];
2957 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02002958#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07002959 lb = ub = src[0];
2960
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02002961#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07002962 if (cpi->common.use_highbitdepth) {
2963 for (r = 0; r < rows; ++r) {
2964 for (c = 0; c < cols; ++c) {
2965 val = src16[r * src_stride + c];
2966 data[r * cols + c] = val;
2967 if (val < lb)
2968 lb = val;
2969 else if (val > ub)
2970 ub = val;
2971 }
2972 }
2973 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02002974#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07002975 for (r = 0; r < rows; ++r) {
2976 for (c = 0; c < cols; ++c) {
2977 val = src[r * src_stride + c];
2978 data[r * cols + c] = val;
2979 if (val < lb)
2980 lb = val;
2981 else if (val > ub)
2982 ub = val;
2983 }
2984 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02002985#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07002986 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02002987#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07002988
2989 mbmi->mode = DC_PRED;
hui su5db97432016-10-14 16:10:14 -07002990#if CONFIG_FILTER_INTRA
2991 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] = 0;
2992#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07002993
2994 if (rows * cols > PALETTE_MAX_BLOCK_SIZE) return 0;
2995
hui su33567b22017-04-30 16:40:19 -07002996#if CONFIG_PALETTE_DELTA_ENCODING
hui su33567b22017-04-30 16:40:19 -07002997 uint16_t color_cache[2 * PALETTE_MAX_SIZE];
Hui Su3748bc22017-08-23 11:30:41 -07002998 const int n_cache = av1_get_palette_cache(xd, 0, color_cache);
hui su33567b22017-04-30 16:40:19 -07002999#endif // CONFIG_PALETTE_DELTA_ENCODING
3000
Yaowu Xuc27fc142016-08-22 16:08:15 -07003001 for (n = colors > PALETTE_MAX_SIZE ? PALETTE_MAX_SIZE : colors; n >= 2;
3002 --n) {
Urvang Joshi773e3542017-05-05 18:09:42 -07003003 if (colors == PALETTE_MIN_SIZE) {
3004 // Special case: These colors automatically become the centroids.
3005 assert(colors == n);
3006 assert(colors == 2);
3007 centroids[0] = lb;
3008 centroids[1] = ub;
3009 k = 2;
3010 } else {
3011 for (i = 0; i < n; ++i) {
3012 centroids[i] = lb + (2 * i + 1) * (ub - lb) / n / 2;
3013 }
3014 av1_k_means(data, centroids, color_map, rows * cols, n, 1, max_itr);
hui su33567b22017-04-30 16:40:19 -07003015#if CONFIG_PALETTE_DELTA_ENCODING
3016 optimize_palette_colors(color_cache, n_cache, n, 1, centroids);
3017#endif // CONFIG_PALETTE_DELTA_ENCODING
Urvang Joshi773e3542017-05-05 18:09:42 -07003018 k = av1_remove_duplicates(centroids, n);
3019 if (k < PALETTE_MIN_SIZE) {
3020 // Too few unique colors to create a palette. And DC_PRED will work
3021 // well for that case anyway. So skip.
3022 continue;
3023 }
Urvang Joshi5fb95f72017-05-05 17:36:16 -07003024 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07003025
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003026#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07003027 if (cpi->common.use_highbitdepth)
3028 for (i = 0; i < k; ++i)
3029 pmi->palette_colors[i] =
3030 clip_pixel_highbd((int)centroids[i], cpi->common.bit_depth);
3031 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003032#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07003033 for (i = 0; i < k; ++i)
3034 pmi->palette_colors[i] = clip_pixel((int)centroids[i]);
3035 pmi->palette_size[0] = k;
3036
Yaowu Xuf883b422016-08-30 14:01:10 -07003037 av1_calc_indices(data, centroids, color_map, rows * cols, k, 1);
Urvang Joshi56ba91b2017-01-10 13:22:09 -08003038 extend_palette_color_map(color_map, cols, rows, block_width,
3039 block_height);
hui su78c611a2017-01-13 17:06:04 -08003040 palette_mode_cost =
hui sud13c24a2017-04-07 16:13:07 -07003041 dc_mode_cost +
Yue Chenb23d00a2017-07-28 17:01:21 -07003042 x->palette_y_size_cost[bsize - BLOCK_8X8][k - PALETTE_MIN_SIZE] +
Yaowu Xuc27fc142016-08-22 16:08:15 -07003043 write_uniform_cost(k, color_map[0]) +
Yaowu Xuf883b422016-08-30 14:01:10 -07003044 av1_cost_bit(
3045 av1_default_palette_y_mode_prob[bsize - BLOCK_8X8][palette_ctx],
Yaowu Xuc27fc142016-08-22 16:08:15 -07003046 1);
hui su33567b22017-04-30 16:40:19 -07003047 palette_mode_cost += av1_palette_color_cost_y(pmi,
3048#if CONFIG_PALETTE_DELTA_ENCODING
3049 color_cache, n_cache,
3050#endif // CONFIG_PALETTE_DELTA_ENCODING
3051 cpi->common.bit_depth);
Sarah Parker99e7daa2017-08-29 10:30:13 -07003052 palette_mode_cost +=
3053 av1_cost_color_map(x, 0, 0, bsize, mbmi->tx_size, PALETTE_MAP);
hui su78c611a2017-01-13 17:06:04 -08003054 this_model_rd = intra_model_yrd(cpi, x, bsize, palette_mode_cost);
3055 if (*best_model_rd != INT64_MAX &&
3056 this_model_rd > *best_model_rd + (*best_model_rd >> 1))
3057 continue;
3058 if (this_model_rd < *best_model_rd) *best_model_rd = this_model_rd;
3059 super_block_yrd(cpi, x, &tokenonly_rd_stats, bsize, *best_rd);
3060 if (tokenonly_rd_stats.rate == INT_MAX) continue;
3061 this_rate = tokenonly_rd_stats.rate + palette_mode_cost;
Urvang Joshi70006e42017-06-14 16:08:55 -07003062 this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
hui su8a630492017-01-10 18:22:41 -08003063 if (!xd->lossless[mbmi->segment_id] && mbmi->sb_type >= BLOCK_8X8) {
Urvang Joshifeb925f2016-12-05 10:37:29 -08003064 tokenonly_rd_stats.rate -= tx_size_cost(cpi, x, bsize, mbmi->tx_size);
hui su8a630492017-01-10 18:22:41 -08003065 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07003066 if (this_rd < *best_rd) {
3067 *best_rd = this_rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003068 memcpy(best_palette_color_map, color_map,
Urvang Joshi56ba91b2017-01-10 13:22:09 -08003069 block_width * block_height * sizeof(color_map[0]));
hui sude0c70a2017-01-09 17:12:17 -08003070 *best_mbmi = *mbmi;
Angie Chiang0e9a2e92016-11-08 09:45:40 -08003071 rate_overhead = this_rate - tokenonly_rd_stats.rate;
hui su8a630492017-01-10 18:22:41 -08003072 if (rate) *rate = this_rate;
3073 if (rate_tokenonly) *rate_tokenonly = tokenonly_rd_stats.rate;
3074 if (distortion) *distortion = tokenonly_rd_stats.dist;
3075 if (skippable) *skippable = tokenonly_rd_stats.skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003076 }
3077 }
3078 }
hui sude0c70a2017-01-09 17:12:17 -08003079
3080 if (best_mbmi->palette_mode_info.palette_size[0] > 0) {
3081 memcpy(color_map, best_palette_color_map,
Luc Trudeau0401e892017-08-31 00:37:11 -04003082 block_width * block_height * sizeof(best_palette_color_map[0]));
hui sude0c70a2017-01-09 17:12:17 -08003083 }
3084 *mbmi = *best_mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003085 return rate_overhead;
3086}
3087
Urvang Joshifeb925f2016-12-05 10:37:29 -08003088static int64_t rd_pick_intra_sub_8x8_y_subblock_mode(
Urvang Joshi52648442016-10-13 17:27:51 -07003089 const AV1_COMP *const cpi, MACROBLOCK *x, int row, int col,
3090 PREDICTION_MODE *best_mode, const int *bmode_costs, ENTROPY_CONTEXT *a,
3091 ENTROPY_CONTEXT *l, int *bestrate, int *bestratey, int64_t *bestdistortion,
Urvang Joshifeb925f2016-12-05 10:37:29 -08003092 BLOCK_SIZE bsize, TX_SIZE tx_size, int *y_skip, int64_t rd_thresh) {
Angie Chiang22ba7512016-10-20 17:10:33 -07003093 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003094 PREDICTION_MODE mode;
3095 MACROBLOCKD *const xd = &x->e_mbd;
Urvang Joshi330aec82017-05-08 15:37:42 -07003096 assert(!is_inter_block(&xd->mi[0]->mbmi));
Yaowu Xuc27fc142016-08-22 16:08:15 -07003097 int64_t best_rd = rd_thresh;
3098 struct macroblock_plane *p = &x->plane[0];
3099 struct macroblockd_plane *pd = &xd->plane[0];
3100 const int src_stride = p->src.stride;
3101 const int dst_stride = pd->dst.stride;
3102 const uint8_t *src_init = &p->src.buf[row * 4 * src_stride + col * 4];
Yushin Cho1a2df5e2017-01-09 13:36:13 -08003103 uint8_t *dst_init = &pd->dst.buf[row * 4 * dst_stride + col * 4];
Timothy B. Terriberryfe67ed62017-04-26 16:53:47 -07003104#if CONFIG_CHROMA_2X2
Jingning Han276c2942016-12-05 12:37:02 -08003105 // TODO(jingning): This is a temporal change. The whole function should be
3106 // out when cb4x4 is enabled.
3107 ENTROPY_CONTEXT ta[4], tempa[4];
3108 ENTROPY_CONTEXT tl[4], templ[4];
3109#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07003110 ENTROPY_CONTEXT ta[2], tempa[2];
3111 ENTROPY_CONTEXT tl[2], templ[2];
Timothy B. Terriberryfe67ed62017-04-26 16:53:47 -07003112#endif // CONFIG_CHROMA_2X2
Urvang Joshifeb925f2016-12-05 10:37:29 -08003113
3114 const int pred_width_in_4x4_blocks = num_4x4_blocks_wide_lookup[bsize];
3115 const int pred_height_in_4x4_blocks = num_4x4_blocks_high_lookup[bsize];
3116 const int tx_width_unit = tx_size_wide_unit[tx_size];
3117 const int tx_height_unit = tx_size_high_unit[tx_size];
3118 const int pred_block_width = block_size_wide[bsize];
3119 const int pred_block_height = block_size_high[bsize];
3120 const int tx_width = tx_size_wide[tx_size];
3121 const int tx_height = tx_size_high[tx_size];
3122 const int pred_width_in_transform_blocks = pred_block_width / tx_width;
3123 const int pred_height_in_transform_blocks = pred_block_height / tx_height;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003124 int idx, idy;
Debargha Mukherjee096ae4c2016-09-07 10:08:13 -07003125 int best_can_skip = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003126 uint8_t best_dst[8 * 8];
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003127#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07003128 uint16_t best_dst16[8 * 8];
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003129#endif // CONFIG_HIGHBITDEPTH
Urvang Joshifeb925f2016-12-05 10:37:29 -08003130 const int is_lossless = xd->lossless[xd->mi[0]->mbmi.segment_id];
3131#if CONFIG_EXT_TX && CONFIG_RECT_TX
3132 const int sub_bsize = bsize;
3133#else
3134 const int sub_bsize = BLOCK_4X4;
3135#endif // CONFIG_EXT_TX && CONFIG_RECT_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07003136
Yushin Cho77bba8d2016-11-04 16:36:56 -07003137#if CONFIG_PVQ
3138 od_rollback_buffer pre_buf, post_buf;
3139 od_encode_checkpoint(&x->daala_enc, &pre_buf);
3140 od_encode_checkpoint(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08003141#endif // CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -07003142
Urvang Joshifeb925f2016-12-05 10:37:29 -08003143 assert(bsize < BLOCK_8X8);
3144 assert(tx_width < 8 || tx_height < 8);
3145#if CONFIG_EXT_TX && CONFIG_RECT_TX
hui suff5e2092017-03-27 10:07:59 -07003146 if (is_lossless)
3147 assert(tx_width == 4 && tx_height == 4);
3148 else
3149 assert(tx_width == pred_block_width && tx_height == pred_block_height);
Urvang Joshifeb925f2016-12-05 10:37:29 -08003150#else
3151 assert(tx_width == 4 && tx_height == 4);
3152#endif // CONFIG_EXT_TX && CONFIG_RECT_TX
3153
3154 memcpy(ta, a, pred_width_in_transform_blocks * sizeof(a[0]));
3155 memcpy(tl, l, pred_height_in_transform_blocks * sizeof(l[0]));
3156
3157 xd->mi[0]->mbmi.tx_size = tx_size;
3158
Yaowu Xuc27fc142016-08-22 16:08:15 -07003159 xd->mi[0]->mbmi.palette_mode_info.palette_size[0] = 0;
3160
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003161#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07003162 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Thomas Daede6ff6af62017-02-03 16:29:24 -08003163#if CONFIG_PVQ
3164 od_encode_checkpoint(&x->daala_enc, &pre_buf);
3165#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07003166 for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
3167 int64_t this_rd;
3168 int ratey = 0;
3169 int64_t distortion = 0;
3170 int rate = bmode_costs[mode];
Debargha Mukherjee096ae4c2016-09-07 10:08:13 -07003171 int can_skip = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003172
Urvang Joshifeb925f2016-12-05 10:37:29 -08003173 if (!(cpi->sf.intra_y_mode_mask[txsize_sqr_up_map[tx_size]] &
3174 (1 << mode)))
3175 continue;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003176
3177 // Only do the oblique modes if the best so far is
3178 // one of the neighboring directional modes
3179 if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
3180 if (conditional_skipintra(mode, *best_mode)) continue;
3181 }
3182
Urvang Joshifeb925f2016-12-05 10:37:29 -08003183 memcpy(tempa, ta, pred_width_in_transform_blocks * sizeof(ta[0]));
3184 memcpy(templ, tl, pred_height_in_transform_blocks * sizeof(tl[0]));
Yaowu Xuc27fc142016-08-22 16:08:15 -07003185
Urvang Joshifeb925f2016-12-05 10:37:29 -08003186 for (idy = 0; idy < pred_height_in_transform_blocks; ++idy) {
3187 for (idx = 0; idx < pred_width_in_transform_blocks; ++idx) {
3188 const int block_raster_idx = (row + idy) * 2 + (col + idx);
3189 const int block =
3190 av1_raster_order_to_block_index(tx_size, block_raster_idx);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003191 const uint8_t *const src = &src_init[idx * 4 + idy * 4 * src_stride];
3192 uint8_t *const dst = &dst_init[idx * 4 + idy * 4 * dst_stride];
Thomas Daede6ff6af62017-02-03 16:29:24 -08003193#if !CONFIG_PVQ
Urvang Joshifeb925f2016-12-05 10:37:29 -08003194 int16_t *const src_diff = av1_raster_block_offset_int16(
3195 BLOCK_8X8, block_raster_idx, p->src_diff);
Thomas Daede6ff6af62017-02-03 16:29:24 -08003196#endif
Urvang Joshifeb925f2016-12-05 10:37:29 -08003197 int skip;
3198 assert(block < 4);
3199 assert(IMPLIES(tx_size == TX_4X8 || tx_size == TX_8X4,
3200 idx == 0 && idy == 0));
3201 assert(IMPLIES(tx_size == TX_4X8 || tx_size == TX_8X4,
3202 block == 0 || block == 2));
3203 xd->mi[0]->bmi[block_raster_idx].as_mode = mode;
David Barker839467f2017-01-19 11:06:15 +00003204 av1_predict_intra_block(
David Barker761b1ac2017-09-25 11:23:03 +01003205 cm, xd, pd->width, pd->height, txsize_to_bsize[tx_size], mode,
3206 dst, dst_stride, dst, dst_stride, col + idx, row + idy, 0);
Thomas Daede6ff6af62017-02-03 16:29:24 -08003207#if !CONFIG_PVQ
Urvang Joshifeb925f2016-12-05 10:37:29 -08003208 aom_highbd_subtract_block(tx_height, tx_width, src_diff, 8, src,
3209 src_stride, dst, dst_stride, xd->bd);
Thomas Daede6ff6af62017-02-03 16:29:24 -08003210#endif
Urvang Joshifeb925f2016-12-05 10:37:29 -08003211 if (is_lossless) {
Jingning Han19b5c8f2017-07-06 15:10:12 -07003212 TX_TYPE tx_type =
3213 av1_get_tx_type(PLANE_TYPE_Y, xd, 0, 0, block, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -07003214 const SCAN_ORDER *scan_order =
3215 get_scan(cm, tx_size, tx_type, &xd->mi[0]->mbmi);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003216 const int coeff_ctx =
Urvang Joshifeb925f2016-12-05 10:37:29 -08003217 combine_entropy_contexts(tempa[idx], templ[idy]);
Thomas Daede6ff6af62017-02-03 16:29:24 -08003218#if !CONFIG_PVQ
Angie Chiangff6d8902016-10-21 11:02:09 -07003219 av1_xform_quant(cm, x, 0, block, row + idy, col + idx, BLOCK_8X8,
Urvang Joshifeb925f2016-12-05 10:37:29 -08003220 tx_size, coeff_ctx, AV1_XFORM_QUANT_FP);
Jingning Han7eab9ff2017-07-06 10:12:54 -07003221 ratey += av1_cost_coeffs(cpi, x, 0, 0, 0, block, tx_size,
3222 scan_order, tempa + idx, templ + idy,
Urvang Joshi03f6fdc2016-10-14 15:53:39 -07003223 cpi->sf.use_fast_coef_costing);
Urvang Joshifeb925f2016-12-05 10:37:29 -08003224 skip = (p->eobs[block] == 0);
3225 can_skip &= skip;
3226 tempa[idx] = !skip;
3227 templ[idy] = !skip;
3228#if CONFIG_EXT_TX
3229 if (tx_size == TX_8X4) {
3230 tempa[idx + 1] = tempa[idx];
3231 } else if (tx_size == TX_4X8) {
3232 templ[idy + 1] = templ[idy];
3233 }
3234#endif // CONFIG_EXT_TX
Thomas Daede6ff6af62017-02-03 16:29:24 -08003235#else
3236 (void)scan_order;
Urvang Joshifeb925f2016-12-05 10:37:29 -08003237
Thomas Daede6ff6af62017-02-03 16:29:24 -08003238 av1_xform_quant(cm, x, 0, block, row + idy, col + idx, BLOCK_8X8,
3239 tx_size, coeff_ctx, AV1_XFORM_QUANT_B);
3240
3241 ratey += x->rate;
3242 skip = x->pvq_skip[0];
3243 tempa[idx] = !skip;
3244 templ[idy] = !skip;
3245 can_skip &= skip;
3246#endif
Urvang Joshi70006e42017-06-14 16:08:55 -07003247 if (RDCOST(x->rdmult, ratey, distortion) >= best_rd)
Yaowu Xuc27fc142016-08-22 16:08:15 -07003248 goto next_highbd;
Thomas Daede6ff6af62017-02-03 16:29:24 -08003249#if CONFIG_PVQ
Yushin Cho08195cc2017-04-05 16:37:01 -07003250 if (!skip)
Thomas Daede6ff6af62017-02-03 16:29:24 -08003251#endif
Yushin Cho08195cc2017-04-05 16:37:01 -07003252 av1_inverse_transform_block(xd, BLOCK_OFFSET(pd->dqcoeff, block),
Lester Lu708c1ec2017-06-14 14:54:49 -07003253#if CONFIG_LGT
3254 mode,
3255#endif
Sarah Parker99e7daa2017-08-29 10:30:13 -07003256#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
3257 BLOCK_OFFSET(xd->mrc_mask, block),
3258#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
Yushin Cho08195cc2017-04-05 16:37:01 -07003259 DCT_DCT, tx_size, dst, dst_stride,
3260 p->eobs[block]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003261 } else {
3262 int64_t dist;
3263 unsigned int tmp;
Jingning Han19b5c8f2017-07-06 15:10:12 -07003264 TX_TYPE tx_type =
3265 av1_get_tx_type(PLANE_TYPE_Y, xd, 0, 0, block, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -07003266 const SCAN_ORDER *scan_order =
3267 get_scan(cm, tx_size, tx_type, &xd->mi[0]->mbmi);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003268 const int coeff_ctx =
Urvang Joshifeb925f2016-12-05 10:37:29 -08003269 combine_entropy_contexts(tempa[idx], templ[idy]);
Thomas Daede6ff6af62017-02-03 16:29:24 -08003270#if !CONFIG_PVQ
Sarah Parker345366a2017-06-15 12:13:01 -07003271#if DISABLE_TRELLISQ_SEARCH
3272 av1_xform_quant(cm, x, 0, block, row + idy, col + idx, BLOCK_8X8,
3273 tx_size, coeff_ctx, AV1_XFORM_QUANT_B);
3274#else
Angie Chiangff6d8902016-10-21 11:02:09 -07003275 av1_xform_quant(cm, x, 0, block, row + idy, col + idx, BLOCK_8X8,
Urvang Joshifeb925f2016-12-05 10:37:29 -08003276 tx_size, coeff_ctx, AV1_XFORM_QUANT_FP);
Jingning Han7eab9ff2017-07-06 10:12:54 -07003277 av1_optimize_b(cm, x, 0, 0, 0, block, BLOCK_8X8, tx_size,
Angie Chiang25645b72017-09-24 14:28:49 -07003278 tempa + idx, templ + idy, 1);
Sarah Parker345366a2017-06-15 12:13:01 -07003279#endif // DISABLE_TRELLISQ_SEARCH
Jingning Han7eab9ff2017-07-06 10:12:54 -07003280 ratey += av1_cost_coeffs(cpi, x, 0, 0, 0, block, tx_size,
3281 scan_order, tempa + idx, templ + idy,
Urvang Joshi03f6fdc2016-10-14 15:53:39 -07003282 cpi->sf.use_fast_coef_costing);
Urvang Joshifeb925f2016-12-05 10:37:29 -08003283 skip = (p->eobs[block] == 0);
3284 can_skip &= skip;
3285 tempa[idx] = !skip;
3286 templ[idy] = !skip;
3287#if CONFIG_EXT_TX
3288 if (tx_size == TX_8X4) {
3289 tempa[idx + 1] = tempa[idx];
3290 } else if (tx_size == TX_4X8) {
3291 templ[idy + 1] = templ[idy];
3292 }
3293#endif // CONFIG_EXT_TX
Thomas Daede6ff6af62017-02-03 16:29:24 -08003294#else
3295 (void)scan_order;
3296
3297 av1_xform_quant(cm, x, 0, block, row + idy, col + idx, BLOCK_8X8,
3298 tx_size, coeff_ctx, AV1_XFORM_QUANT_FP);
3299 ratey += x->rate;
3300 skip = x->pvq_skip[0];
3301 tempa[idx] = !skip;
3302 templ[idy] = !skip;
3303 can_skip &= skip;
3304#endif
3305#if CONFIG_PVQ
Yushin Cho08195cc2017-04-05 16:37:01 -07003306 if (!skip)
Thomas Daede6ff6af62017-02-03 16:29:24 -08003307#endif
Yushin Cho08195cc2017-04-05 16:37:01 -07003308 av1_inverse_transform_block(xd, BLOCK_OFFSET(pd->dqcoeff, block),
Lester Lu708c1ec2017-06-14 14:54:49 -07003309#if CONFIG_LGT
3310 mode,
3311#endif
Sarah Parker99e7daa2017-08-29 10:30:13 -07003312#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
3313 BLOCK_OFFSET(xd->mrc_mask, block),
3314#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
Yushin Cho08195cc2017-04-05 16:37:01 -07003315 tx_type, tx_size, dst, dst_stride,
3316 p->eobs[block]);
Urvang Joshifeb925f2016-12-05 10:37:29 -08003317 cpi->fn_ptr[sub_bsize].vf(src, src_stride, dst, dst_stride, &tmp);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003318 dist = (int64_t)tmp << 4;
3319 distortion += dist;
Urvang Joshi70006e42017-06-14 16:08:55 -07003320 if (RDCOST(x->rdmult, ratey, distortion) >= best_rd)
Yaowu Xuc27fc142016-08-22 16:08:15 -07003321 goto next_highbd;
3322 }
3323 }
3324 }
3325
3326 rate += ratey;
Urvang Joshi70006e42017-06-14 16:08:55 -07003327 this_rd = RDCOST(x->rdmult, rate, distortion);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003328
3329 if (this_rd < best_rd) {
3330 *bestrate = rate;
3331 *bestratey = ratey;
3332 *bestdistortion = distortion;
3333 best_rd = this_rd;
Debargha Mukherjee096ae4c2016-09-07 10:08:13 -07003334 best_can_skip = can_skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003335 *best_mode = mode;
Urvang Joshifeb925f2016-12-05 10:37:29 -08003336 memcpy(a, tempa, pred_width_in_transform_blocks * sizeof(tempa[0]));
3337 memcpy(l, templ, pred_height_in_transform_blocks * sizeof(templ[0]));
Thomas Daede6ff6af62017-02-03 16:29:24 -08003338#if CONFIG_PVQ
3339 od_encode_checkpoint(&x->daala_enc, &post_buf);
3340#endif
Urvang Joshifeb925f2016-12-05 10:37:29 -08003341 for (idy = 0; idy < pred_height_in_transform_blocks * 4; ++idy) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003342 memcpy(best_dst16 + idy * 8,
3343 CONVERT_TO_SHORTPTR(dst_init + idy * dst_stride),
Urvang Joshifeb925f2016-12-05 10:37:29 -08003344 pred_width_in_transform_blocks * 4 * sizeof(uint16_t));
Yaowu Xuc27fc142016-08-22 16:08:15 -07003345 }
3346 }
3347 next_highbd : {}
Thomas Daede6ff6af62017-02-03 16:29:24 -08003348#if CONFIG_PVQ
3349 od_encode_rollback(&x->daala_enc, &pre_buf);
3350#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07003351 }
3352
3353 if (best_rd >= rd_thresh) return best_rd;
3354
Thomas Daede6ff6af62017-02-03 16:29:24 -08003355#if CONFIG_PVQ
3356 od_encode_rollback(&x->daala_enc, &post_buf);
3357#endif
3358
Debargha Mukherjee096ae4c2016-09-07 10:08:13 -07003359 if (y_skip) *y_skip &= best_can_skip;
3360
Urvang Joshifeb925f2016-12-05 10:37:29 -08003361 for (idy = 0; idy < pred_height_in_transform_blocks * 4; ++idy) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003362 memcpy(CONVERT_TO_SHORTPTR(dst_init + idy * dst_stride),
Urvang Joshifeb925f2016-12-05 10:37:29 -08003363 best_dst16 + idy * 8,
3364 pred_width_in_transform_blocks * 4 * sizeof(uint16_t));
Yaowu Xuc27fc142016-08-22 16:08:15 -07003365 }
3366
3367 return best_rd;
3368 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003369#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07003370
Yushin Cho77bba8d2016-11-04 16:36:56 -07003371#if CONFIG_PVQ
3372 od_encode_checkpoint(&x->daala_enc, &pre_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08003373#endif // CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -07003374
Yaowu Xuc27fc142016-08-22 16:08:15 -07003375 for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
3376 int64_t this_rd;
3377 int ratey = 0;
3378 int64_t distortion = 0;
3379 int rate = bmode_costs[mode];
Debargha Mukherjee096ae4c2016-09-07 10:08:13 -07003380 int can_skip = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003381
Urvang Joshifeb925f2016-12-05 10:37:29 -08003382 if (!(cpi->sf.intra_y_mode_mask[txsize_sqr_up_map[tx_size]] &
3383 (1 << mode))) {
3384 continue;
3385 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07003386
3387 // Only do the oblique modes if the best so far is
3388 // one of the neighboring directional modes
3389 if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
3390 if (conditional_skipintra(mode, *best_mode)) continue;
3391 }
3392
Urvang Joshifeb925f2016-12-05 10:37:29 -08003393 memcpy(tempa, ta, pred_width_in_transform_blocks * sizeof(ta[0]));
3394 memcpy(templ, tl, pred_height_in_transform_blocks * sizeof(tl[0]));
Yaowu Xuc27fc142016-08-22 16:08:15 -07003395
Urvang Joshifeb925f2016-12-05 10:37:29 -08003396 for (idy = 0; idy < pred_height_in_4x4_blocks; idy += tx_height_unit) {
3397 for (idx = 0; idx < pred_width_in_4x4_blocks; idx += tx_width_unit) {
3398 const int block_raster_idx = (row + idy) * 2 + (col + idx);
3399 int block = av1_raster_order_to_block_index(tx_size, block_raster_idx);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003400 const uint8_t *const src = &src_init[idx * 4 + idy * 4 * src_stride];
3401 uint8_t *const dst = &dst_init[idx * 4 + idy * 4 * dst_stride];
Yushin Cho77bba8d2016-11-04 16:36:56 -07003402#if !CONFIG_PVQ
Urvang Joshifeb925f2016-12-05 10:37:29 -08003403 int16_t *const src_diff = av1_raster_block_offset_int16(
3404 BLOCK_8X8, block_raster_idx, p->src_diff);
Fergus Simpson4063a682017-02-28 16:52:22 -08003405#endif // !CONFIG_PVQ
Urvang Joshifeb925f2016-12-05 10:37:29 -08003406 int skip;
3407 assert(block < 4);
3408 assert(IMPLIES(tx_size == TX_4X8 || tx_size == TX_8X4,
3409 idx == 0 && idy == 0));
3410 assert(IMPLIES(tx_size == TX_4X8 || tx_size == TX_8X4,
3411 block == 0 || block == 2));
3412 xd->mi[0]->bmi[block_raster_idx].as_mode = mode;
David Barker761b1ac2017-09-25 11:23:03 +01003413 av1_predict_intra_block(cm, xd, pd->width, pd->height,
David Barker839467f2017-01-19 11:06:15 +00003414 txsize_to_bsize[tx_size], mode, dst, dst_stride,
3415 dst, dst_stride,
Jingning Hand1097fc2016-12-06 10:55:34 -08003416#if CONFIG_CB4X4
3417 2 * (col + idx), 2 * (row + idy),
3418#else
3419 col + idx, row + idy,
Fergus Simpson4063a682017-02-28 16:52:22 -08003420#endif // CONFIG_CB4X4
Jingning Hand1097fc2016-12-06 10:55:34 -08003421 0);
Yushin Cho77bba8d2016-11-04 16:36:56 -07003422#if !CONFIG_PVQ
Urvang Joshifeb925f2016-12-05 10:37:29 -08003423 aom_subtract_block(tx_height, tx_width, src_diff, 8, src, src_stride,
3424 dst, dst_stride);
Fergus Simpson4063a682017-02-28 16:52:22 -08003425#endif // !CONFIG_PVQ
Jingning Han19b5c8f2017-07-06 15:10:12 -07003426 TX_TYPE tx_type =
3427 av1_get_tx_type(PLANE_TYPE_Y, xd, 0, 0, block, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -07003428 const SCAN_ORDER *scan_order =
3429 get_scan(cm, tx_size, tx_type, &xd->mi[0]->mbmi);
Urvang Joshi14731732017-04-27 18:40:49 -07003430 const int coeff_ctx = combine_entropy_contexts(tempa[idx], templ[idy]);
Jingning Hand1097fc2016-12-06 10:55:34 -08003431#if CONFIG_CB4X4
Urvang Joshi14731732017-04-27 18:40:49 -07003432 block = 4 * block;
Fergus Simpson4063a682017-02-28 16:52:22 -08003433#endif // CONFIG_CB4X4
Yushin Cho900243b2017-01-03 11:02:38 -08003434#if !CONFIG_PVQ
Sarah Parker345366a2017-06-15 12:13:01 -07003435#if DISABLE_TRELLISQ_SEARCH
3436 av1_xform_quant(cm, x, 0, block,
3437#if CONFIG_CB4X4
3438 2 * (row + idy), 2 * (col + idx),
3439#else
3440 row + idy, col + idx,
3441#endif // CONFIG_CB4X4
3442 BLOCK_8X8, tx_size, coeff_ctx, AV1_XFORM_QUANT_B);
3443#else
Urvang Joshi14731732017-04-27 18:40:49 -07003444 const AV1_XFORM_QUANT xform_quant =
3445 is_lossless ? AV1_XFORM_QUANT_B : AV1_XFORM_QUANT_FP;
3446 av1_xform_quant(cm, x, 0, block,
Jingning Hand1097fc2016-12-06 10:55:34 -08003447#if CONFIG_CB4X4
Urvang Joshi14731732017-04-27 18:40:49 -07003448 2 * (row + idy), 2 * (col + idx),
Jingning Hand1097fc2016-12-06 10:55:34 -08003449#else
Urvang Joshi14731732017-04-27 18:40:49 -07003450 row + idy, col + idx,
Fergus Simpson4063a682017-02-28 16:52:22 -08003451#endif // CONFIG_CB4X4
Urvang Joshi14731732017-04-27 18:40:49 -07003452 BLOCK_8X8, tx_size, coeff_ctx, xform_quant);
Yushin Cho900243b2017-01-03 11:02:38 -08003453
Jingning Han7eab9ff2017-07-06 10:12:54 -07003454 av1_optimize_b(cm, x, 0, 0, 0, block, BLOCK_8X8, tx_size, tempa + idx,
Angie Chiang25645b72017-09-24 14:28:49 -07003455 templ + idy, 1);
Sarah Parker345366a2017-06-15 12:13:01 -07003456#endif // DISABLE_TRELLISQ_SEARCH
Jingning Han7eab9ff2017-07-06 10:12:54 -07003457 ratey += av1_cost_coeffs(cpi, x, 0, 0, 0, block, tx_size, scan_order,
3458 tempa + idx, templ + idy,
3459 cpi->sf.use_fast_coef_costing);
Urvang Joshi14731732017-04-27 18:40:49 -07003460 skip = (p->eobs[block] == 0);
3461 can_skip &= skip;
3462 tempa[idx] = !skip;
3463 templ[idy] = !skip;
Urvang Joshifeb925f2016-12-05 10:37:29 -08003464#if CONFIG_EXT_TX
Urvang Joshi14731732017-04-27 18:40:49 -07003465 if (tx_size == TX_8X4) {
3466 tempa[idx + 1] = tempa[idx];
3467 } else if (tx_size == TX_4X8) {
3468 templ[idy + 1] = templ[idy];
3469 }
Urvang Joshifeb925f2016-12-05 10:37:29 -08003470#endif // CONFIG_EXT_TX
Yushin Cho77bba8d2016-11-04 16:36:56 -07003471#else
Urvang Joshi14731732017-04-27 18:40:49 -07003472 (void)scan_order;
Yushin Cho900243b2017-01-03 11:02:38 -08003473
Urvang Joshi14731732017-04-27 18:40:49 -07003474 av1_xform_quant(cm, x, 0, block,
Yushin Cho900243b2017-01-03 11:02:38 -08003475#if CONFIG_CB4X4
Urvang Joshi14731732017-04-27 18:40:49 -07003476 2 * (row + idy), 2 * (col + idx),
Yushin Cho900243b2017-01-03 11:02:38 -08003477#else
Urvang Joshi14731732017-04-27 18:40:49 -07003478 row + idy, col + idx,
Fergus Simpson4063a682017-02-28 16:52:22 -08003479#endif // CONFIG_CB4X4
Urvang Joshi14731732017-04-27 18:40:49 -07003480 BLOCK_8X8, tx_size, coeff_ctx, AV1_XFORM_QUANT_FP);
3481
3482 ratey += x->rate;
3483 skip = x->pvq_skip[0];
3484 tempa[idx] = !skip;
3485 templ[idy] = !skip;
3486 can_skip &= skip;
Fergus Simpson4063a682017-02-28 16:52:22 -08003487#endif // !CONFIG_PVQ
Urvang Joshi14731732017-04-27 18:40:49 -07003488
3489 if (!is_lossless) { // To use the pixel domain distortion, we need to
3490 // calculate inverse txfm *before* calculating RD
3491 // cost. Compared to calculating the distortion in
3492 // the frequency domain, the overhead of encoding
3493 // effort is low.
Yushin Chob27a17f2016-12-23 14:33:02 -08003494#if CONFIG_PVQ
Yushin Cho08195cc2017-04-05 16:37:01 -07003495 if (!skip)
Fergus Simpson4063a682017-02-28 16:52:22 -08003496#endif // CONFIG_PVQ
Yushin Cho08195cc2017-04-05 16:37:01 -07003497 av1_inverse_transform_block(xd, BLOCK_OFFSET(pd->dqcoeff, block),
Lester Lu708c1ec2017-06-14 14:54:49 -07003498#if CONFIG_LGT
3499 mode,
3500#endif
Sarah Parker99e7daa2017-08-29 10:30:13 -07003501#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
3502 BLOCK_OFFSET(xd->mrc_mask, block),
3503#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
Yushin Cho08195cc2017-04-05 16:37:01 -07003504 tx_type, tx_size, dst, dst_stride,
3505 p->eobs[block]);
Urvang Joshi14731732017-04-27 18:40:49 -07003506 unsigned int tmp;
Urvang Joshifeb925f2016-12-05 10:37:29 -08003507 cpi->fn_ptr[sub_bsize].vf(src, src_stride, dst, dst_stride, &tmp);
Urvang Joshi14731732017-04-27 18:40:49 -07003508 const int64_t dist = (int64_t)tmp << 4;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003509 distortion += dist;
Urvang Joshi14731732017-04-27 18:40:49 -07003510 }
3511
Urvang Joshi70006e42017-06-14 16:08:55 -07003512 if (RDCOST(x->rdmult, ratey, distortion) >= best_rd) goto next;
Urvang Joshi14731732017-04-27 18:40:49 -07003513
3514 if (is_lossless) { // Calculate inverse txfm *after* RD cost.
3515#if CONFIG_PVQ
3516 if (!skip)
3517#endif // CONFIG_PVQ
3518 av1_inverse_transform_block(xd, BLOCK_OFFSET(pd->dqcoeff, block),
Lester Lu708c1ec2017-06-14 14:54:49 -07003519#if CONFIG_LGT
3520 mode,
3521#endif
Sarah Parker99e7daa2017-08-29 10:30:13 -07003522#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
3523 BLOCK_OFFSET(xd->mrc_mask, block),
3524#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
Urvang Joshi14731732017-04-27 18:40:49 -07003525 DCT_DCT, tx_size, dst, dst_stride,
3526 p->eobs[block]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003527 }
3528 }
3529 }
3530
3531 rate += ratey;
Urvang Joshi70006e42017-06-14 16:08:55 -07003532 this_rd = RDCOST(x->rdmult, rate, distortion);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003533
3534 if (this_rd < best_rd) {
3535 *bestrate = rate;
3536 *bestratey = ratey;
3537 *bestdistortion = distortion;
3538 best_rd = this_rd;
Debargha Mukherjee096ae4c2016-09-07 10:08:13 -07003539 best_can_skip = can_skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003540 *best_mode = mode;
Urvang Joshifeb925f2016-12-05 10:37:29 -08003541 memcpy(a, tempa, pred_width_in_transform_blocks * sizeof(tempa[0]));
3542 memcpy(l, templ, pred_height_in_transform_blocks * sizeof(templ[0]));
Yushin Cho77bba8d2016-11-04 16:36:56 -07003543#if CONFIG_PVQ
3544 od_encode_checkpoint(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08003545#endif // CONFIG_PVQ
Urvang Joshifeb925f2016-12-05 10:37:29 -08003546 for (idy = 0; idy < pred_height_in_transform_blocks * 4; ++idy)
Yaowu Xuc27fc142016-08-22 16:08:15 -07003547 memcpy(best_dst + idy * 8, dst_init + idy * dst_stride,
Urvang Joshifeb925f2016-12-05 10:37:29 -08003548 pred_width_in_transform_blocks * 4);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003549 }
3550 next : {}
Yushin Cho77bba8d2016-11-04 16:36:56 -07003551#if CONFIG_PVQ
3552 od_encode_rollback(&x->daala_enc, &pre_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08003553#endif // CONFIG_PVQ
3554 } // mode decision loop
Yaowu Xuc27fc142016-08-22 16:08:15 -07003555
3556 if (best_rd >= rd_thresh) return best_rd;
3557
Yushin Cho77bba8d2016-11-04 16:36:56 -07003558#if CONFIG_PVQ
3559 od_encode_rollback(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08003560#endif // CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -07003561
Debargha Mukherjee096ae4c2016-09-07 10:08:13 -07003562 if (y_skip) *y_skip &= best_can_skip;
3563
Urvang Joshifeb925f2016-12-05 10:37:29 -08003564 for (idy = 0; idy < pred_height_in_transform_blocks * 4; ++idy)
Yaowu Xuc27fc142016-08-22 16:08:15 -07003565 memcpy(dst_init + idy * dst_stride, best_dst + idy * 8,
Urvang Joshifeb925f2016-12-05 10:37:29 -08003566 pred_width_in_transform_blocks * 4);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003567
3568 return best_rd;
3569}
3570
Urvang Joshi52648442016-10-13 17:27:51 -07003571static int64_t rd_pick_intra_sub_8x8_y_mode(const AV1_COMP *const cpi,
3572 MACROBLOCK *mb, int *rate,
3573 int *rate_y, int64_t *distortion,
3574 int *y_skip, int64_t best_rd) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003575 const MACROBLOCKD *const xd = &mb->e_mbd;
3576 MODE_INFO *const mic = xd->mi[0];
3577 const MODE_INFO *above_mi = xd->above_mi;
3578 const MODE_INFO *left_mi = xd->left_mi;
Urvang Joshifeb925f2016-12-05 10:37:29 -08003579 MB_MODE_INFO *const mbmi = &mic->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07003580 assert(!is_inter_block(mbmi));
Urvang Joshifeb925f2016-12-05 10:37:29 -08003581 const BLOCK_SIZE bsize = mbmi->sb_type;
3582 const int pred_width_in_4x4_blocks = num_4x4_blocks_wide_lookup[bsize];
3583 const int pred_height_in_4x4_blocks = num_4x4_blocks_high_lookup[bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -07003584 int idx, idy;
3585 int cost = 0;
3586 int64_t total_distortion = 0;
3587 int tot_rate_y = 0;
3588 int64_t total_rd = 0;
Yue Chenb23d00a2017-07-28 17:01:21 -07003589 const int *bmode_costs = mb->mbmode_cost[0];
Urvang Joshifeb925f2016-12-05 10:37:29 -08003590 const int is_lossless = xd->lossless[mbmi->segment_id];
3591#if CONFIG_EXT_TX && CONFIG_RECT_TX
3592 const TX_SIZE tx_size = is_lossless ? TX_4X4 : max_txsize_rect_lookup[bsize];
3593#else
3594 const TX_SIZE tx_size = TX_4X4;
3595#endif // CONFIG_EXT_TX && CONFIG_RECT_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07003596
3597#if CONFIG_EXT_INTRA
hui sueda3d762016-12-06 16:58:23 -08003598#if CONFIG_INTRA_INTERP
Urvang Joshifeb925f2016-12-05 10:37:29 -08003599 mbmi->intra_filter = INTRA_FILTER_LINEAR;
hui sueda3d762016-12-06 16:58:23 -08003600#endif // CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -07003601#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -07003602#if CONFIG_FILTER_INTRA
Urvang Joshifeb925f2016-12-05 10:37:29 -08003603 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] = 0;
hui su5db97432016-10-14 16:10:14 -07003604#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07003605
3606 // TODO(any): Add search of the tx_type to improve rd performance at the
3607 // expense of speed.
Urvang Joshifeb925f2016-12-05 10:37:29 -08003608 mbmi->tx_type = DCT_DCT;
3609 mbmi->tx_size = tx_size;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003610
Debargha Mukherjee096ae4c2016-09-07 10:08:13 -07003611 if (y_skip) *y_skip = 1;
3612
Urvang Joshifeb925f2016-12-05 10:37:29 -08003613 // Pick modes for each prediction sub-block (of size 4x4, 4x8, or 8x4) in this
3614 // 8x8 coding block.
3615 for (idy = 0; idy < 2; idy += pred_height_in_4x4_blocks) {
3616 for (idx = 0; idx < 2; idx += pred_width_in_4x4_blocks) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003617 PREDICTION_MODE best_mode = DC_PRED;
3618 int r = INT_MAX, ry = INT_MAX;
3619 int64_t d = INT64_MAX, this_rd = INT64_MAX;
Urvang Joshifeb925f2016-12-05 10:37:29 -08003620 int j;
3621 const int pred_block_idx = idy * 2 + idx;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003622 if (cpi->common.frame_type == KEY_FRAME) {
Urvang Joshifeb925f2016-12-05 10:37:29 -08003623 const PREDICTION_MODE A =
3624 av1_above_block_mode(mic, above_mi, pred_block_idx);
3625 const PREDICTION_MODE L =
3626 av1_left_block_mode(mic, left_mi, pred_block_idx);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003627
Yue Chenb23d00a2017-07-28 17:01:21 -07003628 bmode_costs = mb->y_mode_costs[A][L];
Yaowu Xuc27fc142016-08-22 16:08:15 -07003629 }
Urvang Joshifeb925f2016-12-05 10:37:29 -08003630 this_rd = rd_pick_intra_sub_8x8_y_subblock_mode(
Yaowu Xuc27fc142016-08-22 16:08:15 -07003631 cpi, mb, idy, idx, &best_mode, bmode_costs,
3632 xd->plane[0].above_context + idx, xd->plane[0].left_context + idy, &r,
Urvang Joshifeb925f2016-12-05 10:37:29 -08003633 &ry, &d, bsize, tx_size, y_skip, best_rd - total_rd);
Yushin Cho55104332017-08-14 16:15:43 -07003634#if CONFIG_DIST_8X8
3635 if (!cpi->oxcf.using_dist_8x8)
3636#endif
3637 if (this_rd >= best_rd - total_rd) return INT64_MAX;
3638
Yaowu Xuc27fc142016-08-22 16:08:15 -07003639 total_rd += this_rd;
3640 cost += r;
3641 total_distortion += d;
3642 tot_rate_y += ry;
3643
Urvang Joshifeb925f2016-12-05 10:37:29 -08003644 mic->bmi[pred_block_idx].as_mode = best_mode;
3645 for (j = 1; j < pred_height_in_4x4_blocks; ++j)
3646 mic->bmi[pred_block_idx + j * 2].as_mode = best_mode;
3647 for (j = 1; j < pred_width_in_4x4_blocks; ++j)
3648 mic->bmi[pred_block_idx + j].as_mode = best_mode;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003649
3650 if (total_rd >= best_rd) return INT64_MAX;
3651 }
3652 }
Urvang Joshifeb925f2016-12-05 10:37:29 -08003653 mbmi->mode = mic->bmi[3].as_mode;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003654
Yushin Chob7b60c52017-07-14 16:18:52 -07003655#if CONFIG_DIST_8X8
Yushin Cho55104332017-08-14 16:15:43 -07003656 if (cpi->oxcf.using_dist_8x8) {
Yushin Cho7a428ba2017-01-12 16:28:49 -08003657 const struct macroblock_plane *p = &mb->plane[0];
3658 const struct macroblockd_plane *pd = &xd->plane[0];
3659 const int src_stride = p->src.stride;
3660 const int dst_stride = pd->dst.stride;
3661 uint8_t *src = p->src.buf;
3662 uint8_t *dst = pd->dst.buf;
Yushin Cho7a428ba2017-01-12 16:28:49 -08003663
Yushin Cho7a428ba2017-01-12 16:28:49 -08003664 // Daala-defined distortion computed for the block of 8x8 pixels
Yushin Choe30a47c2017-08-15 13:08:30 -07003665 total_distortion = av1_dist_8x8(cpi, mb, src, src_stride, dst, dst_stride,
Yushin Chob7b60c52017-07-14 16:18:52 -07003666 BLOCK_8X8, 8, 8, 8, 8, mb->qindex)
3667 << 4;
Yushin Cho7a428ba2017-01-12 16:28:49 -08003668 }
Yushin Chob7b60c52017-07-14 16:18:52 -07003669#endif // CONFIG_DIST_8X8
Yaowu Xuc27fc142016-08-22 16:08:15 -07003670 // Add in the cost of the transform type
Urvang Joshifeb925f2016-12-05 10:37:29 -08003671 if (!is_lossless) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003672 int rate_tx_type = 0;
3673#if CONFIG_EXT_TX
Sarah Parkere68a3e42017-02-16 14:03:24 -08003674 if (get_ext_tx_types(tx_size, bsize, 0, cpi->common.reduced_tx_set_used) >
3675 1) {
3676 const int eset =
3677 get_ext_tx_set(tx_size, bsize, 0, cpi->common.reduced_tx_set_used);
Yue Chenb23d00a2017-07-28 17:01:21 -07003678 rate_tx_type = mb->intra_tx_type_costs[eset][txsize_sqr_map[tx_size]]
3679 [mbmi->mode][mbmi->tx_type];
Yaowu Xuc27fc142016-08-22 16:08:15 -07003680 }
3681#else
clang-format67948d32016-09-07 22:40:40 -07003682 rate_tx_type =
Yue Chenb23d00a2017-07-28 17:01:21 -07003683 mb->intra_tx_type_costs[txsize_sqr_map[tx_size]]
3684 [intra_mode_to_tx_type_context[mbmi->mode]]
3685 [mbmi->tx_type];
Fergus Simpson4063a682017-02-28 16:52:22 -08003686#endif // CONFIG_EXT_TX
Urvang Joshifeb925f2016-12-05 10:37:29 -08003687 assert(mbmi->tx_size == tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003688 cost += rate_tx_type;
3689 tot_rate_y += rate_tx_type;
3690 }
3691
3692 *rate = cost;
3693 *rate_y = tot_rate_y;
3694 *distortion = total_distortion;
3695
Urvang Joshi70006e42017-06-14 16:08:55 -07003696 return RDCOST(mb->rdmult, cost, total_distortion);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003697}
3698
hui su5db97432016-10-14 16:10:14 -07003699#if CONFIG_FILTER_INTRA
3700// Return 1 if an filter intra mode is selected; return 0 otherwise.
3701static int rd_pick_filter_intra_sby(const AV1_COMP *const cpi, MACROBLOCK *x,
3702 int *rate, int *rate_tokenonly,
3703 int64_t *distortion, int *skippable,
3704 BLOCK_SIZE bsize, int mode_cost,
hui su8f4cc0a2017-01-13 15:14:49 -08003705 int64_t *best_rd, int64_t *best_model_rd,
3706 uint16_t skip_mask) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003707 MACROBLOCKD *const xd = &x->e_mbd;
3708 MODE_INFO *const mic = xd->mi[0];
3709 MB_MODE_INFO *mbmi = &mic->mbmi;
hui su5db97432016-10-14 16:10:14 -07003710 int filter_intra_selected_flag = 0;
hui su5db97432016-10-14 16:10:14 -07003711 FILTER_INTRA_MODE mode;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003712 TX_SIZE best_tx_size = TX_4X4;
hui su5db97432016-10-14 16:10:14 -07003713 FILTER_INTRA_MODE_INFO filter_intra_mode_info;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003714 TX_TYPE best_tx_type;
3715
hui su5db97432016-10-14 16:10:14 -07003716 av1_zero(filter_intra_mode_info);
3717 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003718 mbmi->mode = DC_PRED;
3719 mbmi->palette_mode_info.palette_size[0] = 0;
3720
3721 for (mode = 0; mode < FILTER_INTRA_MODES; ++mode) {
hui su8f4cc0a2017-01-13 15:14:49 -08003722 int this_rate;
3723 int64_t this_rd, this_model_rd;
3724 RD_STATS tokenonly_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003725 if (skip_mask & (1 << mode)) continue;
hui su5db97432016-10-14 16:10:14 -07003726 mbmi->filter_intra_mode_info.filter_intra_mode[0] = mode;
hui su8f4cc0a2017-01-13 15:14:49 -08003727 this_model_rd = intra_model_yrd(cpi, x, bsize, mode_cost);
3728 if (*best_model_rd != INT64_MAX &&
3729 this_model_rd > *best_model_rd + (*best_model_rd >> 1))
3730 continue;
3731 if (this_model_rd < *best_model_rd) *best_model_rd = this_model_rd;
Angie Chiang0e9a2e92016-11-08 09:45:40 -08003732 super_block_yrd(cpi, x, &tokenonly_rd_stats, bsize, *best_rd);
3733 if (tokenonly_rd_stats.rate == INT_MAX) continue;
Angie Chiang0e9a2e92016-11-08 09:45:40 -08003734 this_rate = tokenonly_rd_stats.rate +
hui su5db97432016-10-14 16:10:14 -07003735 av1_cost_bit(cpi->common.fc->filter_intra_probs[0], 1) +
Yaowu Xuc27fc142016-08-22 16:08:15 -07003736 write_uniform_cost(FILTER_INTRA_MODES, mode) + mode_cost;
Urvang Joshi70006e42017-06-14 16:08:55 -07003737 this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003738
3739 if (this_rd < *best_rd) {
3740 *best_rd = this_rd;
3741 best_tx_size = mic->mbmi.tx_size;
hui su5db97432016-10-14 16:10:14 -07003742 filter_intra_mode_info = mbmi->filter_intra_mode_info;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003743 best_tx_type = mic->mbmi.tx_type;
3744 *rate = this_rate;
Angie Chiang0e9a2e92016-11-08 09:45:40 -08003745 *rate_tokenonly = tokenonly_rd_stats.rate;
3746 *distortion = tokenonly_rd_stats.dist;
3747 *skippable = tokenonly_rd_stats.skip;
hui su5db97432016-10-14 16:10:14 -07003748 filter_intra_selected_flag = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003749 }
3750 }
3751
hui su5db97432016-10-14 16:10:14 -07003752 if (filter_intra_selected_flag) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003753 mbmi->mode = DC_PRED;
3754 mbmi->tx_size = best_tx_size;
hui su5db97432016-10-14 16:10:14 -07003755 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] =
3756 filter_intra_mode_info.use_filter_intra_mode[0];
3757 mbmi->filter_intra_mode_info.filter_intra_mode[0] =
3758 filter_intra_mode_info.filter_intra_mode[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -07003759 mbmi->tx_type = best_tx_type;
3760 return 1;
3761 } else {
3762 return 0;
3763 }
3764}
hui su5db97432016-10-14 16:10:14 -07003765#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07003766
hui su5db97432016-10-14 16:10:14 -07003767#if CONFIG_EXT_INTRA
hui su45dc5972016-12-08 17:42:50 -08003768// Run RD calculation with given luma intra prediction angle., and return
3769// the RD cost. Update the best mode info. if the RD cost is the best so far.
3770static int64_t calc_rd_given_intra_angle(
3771 const AV1_COMP *const cpi, MACROBLOCK *x, BLOCK_SIZE bsize, int mode_cost,
3772 int64_t best_rd_in, int8_t angle_delta, int max_angle_delta, int *rate,
3773 RD_STATS *rd_stats, int *best_angle_delta, TX_SIZE *best_tx_size,
3774 TX_TYPE *best_tx_type,
hui sueda3d762016-12-06 16:58:23 -08003775#if CONFIG_INTRA_INTERP
3776 INTRA_FILTER *best_filter,
3777#endif // CONFIG_INTRA_INTERP
hui su9a416f52017-01-13 11:37:53 -08003778 int64_t *best_rd, int64_t *best_model_rd) {
Angie Chiang0e9a2e92016-11-08 09:45:40 -08003779 int this_rate;
3780 RD_STATS tokenonly_rd_stats;
hui su9a416f52017-01-13 11:37:53 -08003781 int64_t this_rd, this_model_rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003782 MB_MODE_INFO *mbmi = &x->e_mbd.mi[0]->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07003783 assert(!is_inter_block(mbmi));
Yaowu Xuc27fc142016-08-22 16:08:15 -07003784
hui su45dc5972016-12-08 17:42:50 -08003785 mbmi->angle_delta[0] = angle_delta;
hui su9a416f52017-01-13 11:37:53 -08003786 this_model_rd = intra_model_yrd(cpi, x, bsize, mode_cost);
3787 if (*best_model_rd != INT64_MAX &&
3788 this_model_rd > *best_model_rd + (*best_model_rd >> 1))
3789 return INT64_MAX;
3790 if (this_model_rd < *best_model_rd) *best_model_rd = this_model_rd;
hui su45dc5972016-12-08 17:42:50 -08003791 super_block_yrd(cpi, x, &tokenonly_rd_stats, bsize, best_rd_in);
3792 if (tokenonly_rd_stats.rate == INT_MAX) return INT64_MAX;
3793
3794 this_rate = tokenonly_rd_stats.rate + mode_cost +
3795 write_uniform_cost(2 * max_angle_delta + 1,
3796 mbmi->angle_delta[0] + max_angle_delta);
Urvang Joshi70006e42017-06-14 16:08:55 -07003797 this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003798
3799 if (this_rd < *best_rd) {
3800 *best_rd = this_rd;
3801 *best_angle_delta = mbmi->angle_delta[0];
3802 *best_tx_size = mbmi->tx_size;
hui sueda3d762016-12-06 16:58:23 -08003803#if CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -07003804 *best_filter = mbmi->intra_filter;
hui sueda3d762016-12-06 16:58:23 -08003805#endif // CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -07003806 *best_tx_type = mbmi->tx_type;
3807 *rate = this_rate;
hui su45dc5972016-12-08 17:42:50 -08003808 rd_stats->rate = tokenonly_rd_stats.rate;
3809 rd_stats->dist = tokenonly_rd_stats.dist;
3810 rd_stats->skip = tokenonly_rd_stats.skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003811 }
hui su45dc5972016-12-08 17:42:50 -08003812 return this_rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003813}
3814
hui su45dc5972016-12-08 17:42:50 -08003815// With given luma directional intra prediction mode, pick the best angle delta
3816// Return the RD cost corresponding to the best angle delta.
Urvang Joshi52648442016-10-13 17:27:51 -07003817static int64_t rd_pick_intra_angle_sby(const AV1_COMP *const cpi, MACROBLOCK *x,
hui su45dc5972016-12-08 17:42:50 -08003818 int *rate, RD_STATS *rd_stats,
3819 BLOCK_SIZE bsize, int mode_cost,
hui su9a416f52017-01-13 11:37:53 -08003820 int64_t best_rd,
3821 int64_t *best_model_rd) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003822 MACROBLOCKD *const xd = &x->e_mbd;
3823 MODE_INFO *const mic = xd->mi[0];
3824 MB_MODE_INFO *mbmi = &mic->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07003825 assert(!is_inter_block(mbmi));
hui su45dc5972016-12-08 17:42:50 -08003826 int i, angle_delta, best_angle_delta = 0;
hui su45dc5972016-12-08 17:42:50 -08003827 int first_try = 1;
hui sueda3d762016-12-06 16:58:23 -08003828#if CONFIG_INTRA_INTERP
3829 int p_angle;
Yaowu Xuf883b422016-08-30 14:01:10 -07003830 const int intra_filter_ctx = av1_get_pred_context_intra_interp(xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003831 INTRA_FILTER filter, best_filter = INTRA_FILTER_LINEAR;
hui sueda3d762016-12-06 16:58:23 -08003832#endif // CONFIG_INTRA_INTERP
Debargha Mukherjeedf0e0d72017-04-27 15:16:53 -07003833 int64_t this_rd, best_rd_in, rd_cost[2 * (MAX_ANGLE_DELTA + 2)];
Yaowu Xuc27fc142016-08-22 16:08:15 -07003834 TX_SIZE best_tx_size = mic->mbmi.tx_size;
3835 TX_TYPE best_tx_type = mbmi->tx_type;
3836
hui su0a6731f2017-04-26 15:23:47 -07003837 for (i = 0; i < 2 * (MAX_ANGLE_DELTA + 2); ++i) rd_cost[i] = INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003838
hui su0a6731f2017-04-26 15:23:47 -07003839 for (angle_delta = 0; angle_delta <= MAX_ANGLE_DELTA; angle_delta += 2) {
hui sueda3d762016-12-06 16:58:23 -08003840#if CONFIG_INTRA_INTERP
hui su45dc5972016-12-08 17:42:50 -08003841 for (filter = INTRA_FILTER_LINEAR; filter < INTRA_FILTERS; ++filter) {
3842 if (FILTER_FAST_SEARCH && filter != INTRA_FILTER_LINEAR) continue;
3843 mic->mbmi.intra_filter = filter;
hui sueda3d762016-12-06 16:58:23 -08003844#endif // CONFIG_INTRA_INTERP
hui su45dc5972016-12-08 17:42:50 -08003845 for (i = 0; i < 2; ++i) {
3846 best_rd_in = (best_rd == INT64_MAX)
3847 ? INT64_MAX
3848 : (best_rd + (best_rd >> (first_try ? 3 : 5)));
3849 this_rd = calc_rd_given_intra_angle(
3850 cpi, x, bsize,
hui sueda3d762016-12-06 16:58:23 -08003851#if CONFIG_INTRA_INTERP
Yue Chenb23d00a2017-07-28 17:01:21 -07003852 mode_cost + x->intra_filter_cost[intra_filter_ctx][filter],
hui sueda3d762016-12-06 16:58:23 -08003853#else
hui su45dc5972016-12-08 17:42:50 -08003854 mode_cost,
hui sueda3d762016-12-06 16:58:23 -08003855#endif // CONFIG_INTRA_INTERP
hui su0a6731f2017-04-26 15:23:47 -07003856 best_rd_in, (1 - 2 * i) * angle_delta, MAX_ANGLE_DELTA, rate,
hui su45dc5972016-12-08 17:42:50 -08003857 rd_stats, &best_angle_delta, &best_tx_size, &best_tx_type,
hui sueda3d762016-12-06 16:58:23 -08003858#if CONFIG_INTRA_INTERP
3859 &best_filter,
3860#endif // CONFIG_INTRA_INTERP
hui su9a416f52017-01-13 11:37:53 -08003861 &best_rd, best_model_rd);
hui su45dc5972016-12-08 17:42:50 -08003862 rd_cost[2 * angle_delta + i] = this_rd;
3863 if (first_try && this_rd == INT64_MAX) return best_rd;
3864 first_try = 0;
3865 if (angle_delta == 0) {
3866 rd_cost[1] = this_rd;
3867 break;
3868 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07003869 }
hui su45dc5972016-12-08 17:42:50 -08003870#if CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -07003871 }
hui su45dc5972016-12-08 17:42:50 -08003872#endif // CONFIG_INTRA_INTERP
3873 }
3874
3875 assert(best_rd != INT64_MAX);
hui su0a6731f2017-04-26 15:23:47 -07003876 for (angle_delta = 1; angle_delta <= MAX_ANGLE_DELTA; angle_delta += 2) {
hui su45dc5972016-12-08 17:42:50 -08003877 int64_t rd_thresh;
3878#if CONFIG_INTRA_INTERP
3879 for (filter = INTRA_FILTER_LINEAR; filter < INTRA_FILTERS; ++filter) {
3880 if (FILTER_FAST_SEARCH && filter != INTRA_FILTER_LINEAR) continue;
3881 mic->mbmi.intra_filter = filter;
3882#endif // CONFIG_INTRA_INTERP
3883 for (i = 0; i < 2; ++i) {
3884 int skip_search = 0;
3885 rd_thresh = best_rd + (best_rd >> 5);
3886 if (rd_cost[2 * (angle_delta + 1) + i] > rd_thresh &&
3887 rd_cost[2 * (angle_delta - 1) + i] > rd_thresh)
3888 skip_search = 1;
3889 if (!skip_search) {
Yue Chenb0f808b2017-04-26 11:55:14 -07003890 calc_rd_given_intra_angle(
hui su45dc5972016-12-08 17:42:50 -08003891 cpi, x, bsize,
3892#if CONFIG_INTRA_INTERP
Yue Chenb23d00a2017-07-28 17:01:21 -07003893 mode_cost + x->intra_filter_cost[intra_filter_ctx][filter],
hui su45dc5972016-12-08 17:42:50 -08003894#else
3895 mode_cost,
3896#endif // CONFIG_INTRA_INTERP
hui su0a6731f2017-04-26 15:23:47 -07003897 best_rd, (1 - 2 * i) * angle_delta, MAX_ANGLE_DELTA, rate,
hui su45dc5972016-12-08 17:42:50 -08003898 rd_stats, &best_angle_delta, &best_tx_size, &best_tx_type,
3899#if CONFIG_INTRA_INTERP
3900 &best_filter,
3901#endif // CONFIG_INTRA_INTERP
hui su9a416f52017-01-13 11:37:53 -08003902 &best_rd, best_model_rd);
hui su45dc5972016-12-08 17:42:50 -08003903 }
3904 }
3905#if CONFIG_INTRA_INTERP
3906 }
3907#endif // CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -07003908 }
3909
hui sueda3d762016-12-06 16:58:23 -08003910#if CONFIG_INTRA_INTERP
hui su45dc5972016-12-08 17:42:50 -08003911 if (FILTER_FAST_SEARCH && rd_stats->rate < INT_MAX) {
hui su0a6731f2017-04-26 15:23:47 -07003912 p_angle = mode_to_angle_map[mbmi->mode] + best_angle_delta * ANGLE_STEP;
Yaowu Xuf883b422016-08-30 14:01:10 -07003913 if (av1_is_intra_filter_switchable(p_angle)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003914 for (filter = INTRA_FILTER_LINEAR + 1; filter < INTRA_FILTERS; ++filter) {
3915 mic->mbmi.intra_filter = filter;
hui su45dc5972016-12-08 17:42:50 -08003916 this_rd = calc_rd_given_intra_angle(
3917 cpi, x, bsize,
Yue Chenb23d00a2017-07-28 17:01:21 -07003918 mode_cost + x->intra_filter_cost[intra_filter_ctx][filter], best_rd,
3919 best_angle_delta, MAX_ANGLE_DELTA, rate, rd_stats,
Yaowu Xuc27fc142016-08-22 16:08:15 -07003920 &best_angle_delta, &best_tx_size, &best_tx_type, &best_filter,
hui su9a416f52017-01-13 11:37:53 -08003921 &best_rd, best_model_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003922 }
3923 }
3924 }
hui sueda3d762016-12-06 16:58:23 -08003925#endif // CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -07003926
3927 mbmi->tx_size = best_tx_size;
3928 mbmi->angle_delta[0] = best_angle_delta;
hui sueda3d762016-12-06 16:58:23 -08003929#if CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -07003930 mic->mbmi.intra_filter = best_filter;
hui sueda3d762016-12-06 16:58:23 -08003931#endif // CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -07003932 mbmi->tx_type = best_tx_type;
3933 return best_rd;
3934}
3935
3936// Indices are sign, integer, and fractional part of the gradient value
3937static const uint8_t gradient_to_angle_bin[2][7][16] = {
3938 {
3939 { 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0 },
3940 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 },
3941 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
3942 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
3943 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
3944 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
3945 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
3946 },
3947 {
3948 { 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4 },
3949 { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3 },
3950 { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
3951 { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
3952 { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
3953 { 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
3954 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
3955 },
3956};
3957
Yue Chen56e226e2017-05-02 16:21:40 -07003958/* clang-format off */
Yaowu Xuc27fc142016-08-22 16:08:15 -07003959static const uint8_t mode_to_angle_bin[INTRA_MODES] = {
3960 0, 2, 6, 0, 4, 3, 5, 7, 1, 0,
hui su9cc10652017-04-27 17:22:07 -07003961 0,
Yaowu Xuc27fc142016-08-22 16:08:15 -07003962};
Yue Chen56e226e2017-05-02 16:21:40 -07003963/* clang-format on */
Yaowu Xuc27fc142016-08-22 16:08:15 -07003964
3965static void angle_estimation(const uint8_t *src, int src_stride, int rows,
hui su9cc10652017-04-27 17:22:07 -07003966 int cols, BLOCK_SIZE bsize,
3967 uint8_t *directional_mode_skip_mask) {
3968 memset(directional_mode_skip_mask, 0,
3969 INTRA_MODES * sizeof(*directional_mode_skip_mask));
Joe Young830d4ce2017-05-30 17:48:13 -07003970 // Check if angle_delta is used
3971 if (!av1_use_angle_delta(bsize)) return;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003972 uint64_t hist[DIRECTIONAL_MODES];
Yaowu Xuc27fc142016-08-22 16:08:15 -07003973 memset(hist, 0, DIRECTIONAL_MODES * sizeof(hist[0]));
3974 src += src_stride;
hui su9cc10652017-04-27 17:22:07 -07003975 int r, c, dx, dy;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003976 for (r = 1; r < rows; ++r) {
3977 for (c = 1; c < cols; ++c) {
3978 dx = src[c] - src[c - 1];
3979 dy = src[c] - src[c - src_stride];
hui su9cc10652017-04-27 17:22:07 -07003980 int index;
3981 const int temp = dx * dx + dy * dy;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003982 if (dy == 0) {
3983 index = 2;
3984 } else {
hui su9cc10652017-04-27 17:22:07 -07003985 const int sn = (dx > 0) ^ (dy > 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003986 dx = abs(dx);
3987 dy = abs(dy);
hui su9cc10652017-04-27 17:22:07 -07003988 const int remd = (dx % dy) * 16 / dy;
3989 const int quot = dx / dy;
Yaowu Xuf883b422016-08-30 14:01:10 -07003990 index = gradient_to_angle_bin[sn][AOMMIN(quot, 6)][AOMMIN(remd, 15)];
Yaowu Xuc27fc142016-08-22 16:08:15 -07003991 }
3992 hist[index] += temp;
3993 }
3994 src += src_stride;
3995 }
3996
hui su9cc10652017-04-27 17:22:07 -07003997 int i;
3998 uint64_t hist_sum = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003999 for (i = 0; i < DIRECTIONAL_MODES; ++i) hist_sum += hist[i];
4000 for (i = 0; i < INTRA_MODES; ++i) {
hui su9cc10652017-04-27 17:22:07 -07004001 if (av1_is_directional_mode(i, bsize)) {
Urvang Joshida70e7b2016-10-19 11:48:54 -07004002 const uint8_t angle_bin = mode_to_angle_bin[i];
4003 uint64_t score = 2 * hist[angle_bin];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004004 int weight = 2;
Urvang Joshida70e7b2016-10-19 11:48:54 -07004005 if (angle_bin > 0) {
4006 score += hist[angle_bin - 1];
4007 ++weight;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004008 }
Urvang Joshida70e7b2016-10-19 11:48:54 -07004009 if (angle_bin < DIRECTIONAL_MODES - 1) {
4010 score += hist[angle_bin + 1];
4011 ++weight;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004012 }
4013 if (score * ANGLE_SKIP_THRESH < hist_sum * weight)
4014 directional_mode_skip_mask[i] = 1;
4015 }
4016 }
4017}
4018
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02004019#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07004020static void highbd_angle_estimation(const uint8_t *src8, int src_stride,
hui su9cc10652017-04-27 17:22:07 -07004021 int rows, int cols, BLOCK_SIZE bsize,
Yaowu Xuc27fc142016-08-22 16:08:15 -07004022 uint8_t *directional_mode_skip_mask) {
hui su9cc10652017-04-27 17:22:07 -07004023 memset(directional_mode_skip_mask, 0,
4024 INTRA_MODES * sizeof(*directional_mode_skip_mask));
Joe Young830d4ce2017-05-30 17:48:13 -07004025 // Check if angle_delta is used
4026 if (!av1_use_angle_delta(bsize)) return;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004027 uint16_t *src = CONVERT_TO_SHORTPTR(src8);
hui su9cc10652017-04-27 17:22:07 -07004028 uint64_t hist[DIRECTIONAL_MODES];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004029 memset(hist, 0, DIRECTIONAL_MODES * sizeof(hist[0]));
4030 src += src_stride;
hui su9cc10652017-04-27 17:22:07 -07004031 int r, c, dx, dy;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004032 for (r = 1; r < rows; ++r) {
4033 for (c = 1; c < cols; ++c) {
4034 dx = src[c] - src[c - 1];
4035 dy = src[c] - src[c - src_stride];
hui su9cc10652017-04-27 17:22:07 -07004036 int index;
4037 const int temp = dx * dx + dy * dy;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004038 if (dy == 0) {
4039 index = 2;
4040 } else {
hui su9cc10652017-04-27 17:22:07 -07004041 const int sn = (dx > 0) ^ (dy > 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004042 dx = abs(dx);
4043 dy = abs(dy);
hui su9cc10652017-04-27 17:22:07 -07004044 const int remd = (dx % dy) * 16 / dy;
4045 const int quot = dx / dy;
Yaowu Xuf883b422016-08-30 14:01:10 -07004046 index = gradient_to_angle_bin[sn][AOMMIN(quot, 6)][AOMMIN(remd, 15)];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004047 }
4048 hist[index] += temp;
4049 }
4050 src += src_stride;
4051 }
4052
hui su9cc10652017-04-27 17:22:07 -07004053 int i;
4054 uint64_t hist_sum = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004055 for (i = 0; i < DIRECTIONAL_MODES; ++i) hist_sum += hist[i];
4056 for (i = 0; i < INTRA_MODES; ++i) {
hui su9cc10652017-04-27 17:22:07 -07004057 if (av1_is_directional_mode(i, bsize)) {
Urvang Joshida70e7b2016-10-19 11:48:54 -07004058 const uint8_t angle_bin = mode_to_angle_bin[i];
4059 uint64_t score = 2 * hist[angle_bin];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004060 int weight = 2;
Urvang Joshida70e7b2016-10-19 11:48:54 -07004061 if (angle_bin > 0) {
4062 score += hist[angle_bin - 1];
4063 ++weight;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004064 }
Urvang Joshida70e7b2016-10-19 11:48:54 -07004065 if (angle_bin < DIRECTIONAL_MODES - 1) {
4066 score += hist[angle_bin + 1];
4067 ++weight;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004068 }
4069 if (score * ANGLE_SKIP_THRESH < hist_sum * weight)
4070 directional_mode_skip_mask[i] = 1;
4071 }
4072 }
4073}
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02004074#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07004075#endif // CONFIG_EXT_INTRA
4076
Urvang Joshic9e71d42017-08-09 18:58:33 -07004077// Returns true if palette can be used for this block.
4078static int can_use_palette(const AV1_COMP *const cpi,
4079 const MB_MODE_INFO *const mbmi) {
4080 return cpi->common.allow_screen_content_tools && mbmi->sb_type >= BLOCK_8X8 &&
4081 mbmi->sb_type <= BLOCK_LARGEST;
4082}
Urvang Joshic9e71d42017-08-09 18:58:33 -07004083
Yaowu Xuc27fc142016-08-22 16:08:15 -07004084// This function is used only for intra_only frames
Urvang Joshi52648442016-10-13 17:27:51 -07004085static int64_t rd_pick_intra_sby_mode(const AV1_COMP *const cpi, MACROBLOCK *x,
4086 int *rate, int *rate_tokenonly,
4087 int64_t *distortion, int *skippable,
4088 BLOCK_SIZE bsize, int64_t best_rd) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07004089 MACROBLOCKD *const xd = &x->e_mbd;
4090 MODE_INFO *const mic = xd->mi[0];
hui sude0c70a2017-01-09 17:12:17 -08004091 MB_MODE_INFO *const mbmi = &mic->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07004092 assert(!is_inter_block(mbmi));
hui sude0c70a2017-01-09 17:12:17 -08004093 MB_MODE_INFO best_mbmi = *mbmi;
hui su308a6392017-01-12 14:49:57 -08004094 int64_t best_model_rd = INT64_MAX;
hui sude0c70a2017-01-09 17:12:17 -08004095#if CONFIG_EXT_INTRA
Jingning Hanae5cfde2016-11-30 12:01:44 -08004096 const int rows = block_size_high[bsize];
4097 const int cols = block_size_wide[bsize];
hui sueda3d762016-12-06 16:58:23 -08004098#if CONFIG_INTRA_INTERP
Yaowu Xuf883b422016-08-30 14:01:10 -07004099 const int intra_filter_ctx = av1_get_pred_context_intra_interp(xd);
hui sueda3d762016-12-06 16:58:23 -08004100#endif // CONFIG_INTRA_INTERP
hui sude0c70a2017-01-09 17:12:17 -08004101 int is_directional_mode;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004102 uint8_t directional_mode_skip_mask[INTRA_MODES];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004103 const int src_stride = x->plane[0].src.stride;
4104 const uint8_t *src = x->plane[0].src.buf;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004105#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -07004106#if CONFIG_FILTER_INTRA
4107 int beat_best_rd = 0;
hui su5db97432016-10-14 16:10:14 -07004108 uint16_t filter_intra_mode_skip_mask = (1 << FILTER_INTRA_MODES) - 1;
4109#endif // CONFIG_FILTER_INTRA
Urvang Joshi52648442016-10-13 17:27:51 -07004110 const int *bmode_costs;
hui sude0c70a2017-01-09 17:12:17 -08004111 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004112 uint8_t *best_palette_color_map =
4113 cpi->common.allow_screen_content_tools
4114 ? x->palette_buffer->best_palette_color_map
4115 : NULL;
Urvang Joshi23a61112017-01-30 14:59:27 -08004116 int palette_y_mode_ctx = 0;
Urvang Joshic9e71d42017-08-09 18:58:33 -07004117 const int try_palette = can_use_palette(cpi, mbmi);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004118 const MODE_INFO *above_mi = xd->above_mi;
4119 const MODE_INFO *left_mi = xd->left_mi;
Yaowu Xuf883b422016-08-30 14:01:10 -07004120 const PREDICTION_MODE A = av1_above_block_mode(mic, above_mi, 0);
4121 const PREDICTION_MODE L = av1_left_block_mode(mic, left_mi, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004122 const PREDICTION_MODE FINAL_MODE_SEARCH = TM_PRED + 1;
Yushin Cho77bba8d2016-11-04 16:36:56 -07004123#if CONFIG_PVQ
4124 od_rollback_buffer pre_buf, post_buf;
4125
4126 od_encode_checkpoint(&x->daala_enc, &pre_buf);
4127 od_encode_checkpoint(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08004128#endif // CONFIG_PVQ
Yue Chenb23d00a2017-07-28 17:01:21 -07004129 bmode_costs = x->y_mode_costs[A][L];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004130
4131#if CONFIG_EXT_INTRA
hui sude0c70a2017-01-09 17:12:17 -08004132 mbmi->angle_delta[0] = 0;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02004133#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07004134 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
hui su9cc10652017-04-27 17:22:07 -07004135 highbd_angle_estimation(src, src_stride, rows, cols, bsize,
Yaowu Xuc27fc142016-08-22 16:08:15 -07004136 directional_mode_skip_mask);
4137 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02004138#endif // CONFIG_HIGHBITDEPTH
hui su9cc10652017-04-27 17:22:07 -07004139 angle_estimation(src, src_stride, rows, cols, bsize,
4140 directional_mode_skip_mask);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004141#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -07004142#if CONFIG_FILTER_INTRA
hui sude0c70a2017-01-09 17:12:17 -08004143 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] = 0;
hui su5db97432016-10-14 16:10:14 -07004144#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07004145 pmi->palette_size[0] = 0;
4146 if (above_mi)
Urvang Joshi23a61112017-01-30 14:59:27 -08004147 palette_y_mode_ctx +=
4148 (above_mi->mbmi.palette_mode_info.palette_size[0] > 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004149 if (left_mi)
Urvang Joshi23a61112017-01-30 14:59:27 -08004150 palette_y_mode_ctx += (left_mi->mbmi.palette_mode_info.palette_size[0] > 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004151
4152 if (cpi->sf.tx_type_search.fast_intra_tx_type_search)
4153 x->use_default_intra_tx_type = 1;
4154 else
4155 x->use_default_intra_tx_type = 0;
4156
4157 /* Y Search for intra prediction mode */
hui su8a516a82017-07-06 10:00:36 -07004158 for (int mode_idx = DC_PRED; mode_idx <= FINAL_MODE_SEARCH; ++mode_idx) {
Angie Chiang0e9a2e92016-11-08 09:45:40 -08004159 RD_STATS this_rd_stats;
hui su308a6392017-01-12 14:49:57 -08004160 int this_rate, this_rate_tokenonly, s;
4161 int64_t this_distortion, this_rd, this_model_rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004162 if (mode_idx == FINAL_MODE_SEARCH) {
4163 if (x->use_default_intra_tx_type == 0) break;
hui sude0c70a2017-01-09 17:12:17 -08004164 mbmi->mode = best_mbmi.mode;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004165 x->use_default_intra_tx_type = 0;
4166 } else {
hui su8a516a82017-07-06 10:00:36 -07004167 assert(mode_idx < INTRA_MODES);
4168 mbmi->mode = intra_rd_search_mode_order[mode_idx];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004169 }
Yushin Cho77bba8d2016-11-04 16:36:56 -07004170#if CONFIG_PVQ
4171 od_encode_rollback(&x->daala_enc, &pre_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08004172#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -07004173#if CONFIG_EXT_INTRA
hui su308a6392017-01-12 14:49:57 -08004174 mbmi->angle_delta[0] = 0;
4175#endif // CONFIG_EXT_INTRA
hui su9a416f52017-01-13 11:37:53 -08004176 this_model_rd = intra_model_yrd(cpi, x, bsize, bmode_costs[mbmi->mode]);
hui su308a6392017-01-12 14:49:57 -08004177 if (best_model_rd != INT64_MAX &&
4178 this_model_rd > best_model_rd + (best_model_rd >> 1))
4179 continue;
4180 if (this_model_rd < best_model_rd) best_model_rd = this_model_rd;
4181#if CONFIG_EXT_INTRA
hui sude0c70a2017-01-09 17:12:17 -08004182 is_directional_mode = av1_is_directional_mode(mbmi->mode, bsize);
4183 if (is_directional_mode && directional_mode_skip_mask[mbmi->mode]) continue;
Joe Young830d4ce2017-05-30 17:48:13 -07004184 if (is_directional_mode && av1_use_angle_delta(bsize)) {
hui su45dc5972016-12-08 17:42:50 -08004185 this_rd_stats.rate = INT_MAX;
Yue Chenb0f808b2017-04-26 11:55:14 -07004186 rd_pick_intra_angle_sby(cpi, x, &this_rate, &this_rd_stats, bsize,
4187 bmode_costs[mbmi->mode], best_rd, &best_model_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004188 } else {
Angie Chiang0e9a2e92016-11-08 09:45:40 -08004189 super_block_yrd(cpi, x, &this_rd_stats, bsize, best_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004190 }
4191#else
Angie Chiang0e9a2e92016-11-08 09:45:40 -08004192 super_block_yrd(cpi, x, &this_rd_stats, bsize, best_rd);
hui su45dc5972016-12-08 17:42:50 -08004193#endif // CONFIG_EXT_INTRA
Angie Chiang0e9a2e92016-11-08 09:45:40 -08004194 this_rate_tokenonly = this_rd_stats.rate;
4195 this_distortion = this_rd_stats.dist;
4196 s = this_rd_stats.skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004197
4198 if (this_rate_tokenonly == INT_MAX) continue;
4199
hui sude0c70a2017-01-09 17:12:17 -08004200 this_rate = this_rate_tokenonly + bmode_costs[mbmi->mode];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004201
hui sude0c70a2017-01-09 17:12:17 -08004202 if (!xd->lossless[mbmi->segment_id] && mbmi->sb_type >= BLOCK_8X8) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07004203 // super_block_yrd above includes the cost of the tx_size in the
4204 // tokenonly rate, but for intra blocks, tx_size is always coded
4205 // (prediction granularity), so we account for it in the full rate,
4206 // not the tokenonly rate.
Urvang Joshifeb925f2016-12-05 10:37:29 -08004207 this_rate_tokenonly -= tx_size_cost(cpi, x, bsize, mbmi->tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004208 }
hui su9bc1d8d2017-03-24 12:36:03 -07004209 if (try_palette && mbmi->mode == DC_PRED) {
Urvang Joshi23a61112017-01-30 14:59:27 -08004210 this_rate +=
4211 av1_cost_bit(av1_default_palette_y_mode_prob[bsize - BLOCK_8X8]
4212 [palette_y_mode_ctx],
4213 0);
hui su9bc1d8d2017-03-24 12:36:03 -07004214 }
hui su5db97432016-10-14 16:10:14 -07004215#if CONFIG_FILTER_INTRA
hui sude0c70a2017-01-09 17:12:17 -08004216 if (mbmi->mode == DC_PRED)
hui su5db97432016-10-14 16:10:14 -07004217 this_rate += av1_cost_bit(cpi->common.fc->filter_intra_probs[0], 0);
4218#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07004219#if CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07004220 if (is_directional_mode) {
hui sueda3d762016-12-06 16:58:23 -08004221#if CONFIG_INTRA_INTERP
hui su0a6731f2017-04-26 15:23:47 -07004222 const int p_angle =
4223 mode_to_angle_map[mbmi->mode] + mbmi->angle_delta[0] * ANGLE_STEP;
Yaowu Xuf883b422016-08-30 14:01:10 -07004224 if (av1_is_intra_filter_switchable(p_angle))
Yue Chenb23d00a2017-07-28 17:01:21 -07004225 this_rate += x->intra_filter_cost[intra_filter_ctx][mbmi->intra_filter];
hui sueda3d762016-12-06 16:58:23 -08004226#endif // CONFIG_INTRA_INTERP
Joe Young830d4ce2017-05-30 17:48:13 -07004227 if (av1_use_angle_delta(bsize)) {
4228 this_rate += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
4229 MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
4230 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07004231 }
4232#endif // CONFIG_EXT_INTRA
Hui Su8dc00922017-09-14 16:15:55 -07004233#if CONFIG_INTRABC
4234 if (bsize >= BLOCK_8X8 && cpi->common.allow_screen_content_tools)
4235 this_rate += x->intrabc_cost[0];
4236#endif // CONFIG_INTRABC
Urvang Joshi70006e42017-06-14 16:08:55 -07004237 this_rd = RDCOST(x->rdmult, this_rate, this_distortion);
hui su5db97432016-10-14 16:10:14 -07004238#if CONFIG_FILTER_INTRA
Debargha Mukherjee1ae9f2c2016-10-04 14:30:16 -07004239 if (best_rd == INT64_MAX || this_rd - best_rd < (best_rd >> 4)) {
hui sude0c70a2017-01-09 17:12:17 -08004240 filter_intra_mode_skip_mask ^= (1 << mbmi->mode);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004241 }
hui su5db97432016-10-14 16:10:14 -07004242#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07004243
4244 if (this_rd < best_rd) {
hui sude0c70a2017-01-09 17:12:17 -08004245 best_mbmi = *mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004246 best_rd = this_rd;
hui su5db97432016-10-14 16:10:14 -07004247#if CONFIG_FILTER_INTRA
4248 beat_best_rd = 1;
4249#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07004250 *rate = this_rate;
4251 *rate_tokenonly = this_rate_tokenonly;
4252 *distortion = this_distortion;
4253 *skippable = s;
Yushin Cho77bba8d2016-11-04 16:36:56 -07004254#if CONFIG_PVQ
4255 od_encode_checkpoint(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08004256#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -07004257 }
4258 }
4259
Yushin Cho77bba8d2016-11-04 16:36:56 -07004260#if CONFIG_PVQ
4261 od_encode_rollback(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08004262#endif // CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -07004263
hui su9bc1d8d2017-03-24 12:36:03 -07004264 if (try_palette) {
Urvang Joshi23a61112017-01-30 14:59:27 -08004265 rd_pick_palette_intra_sby(cpi, x, bsize, palette_y_mode_ctx,
4266 bmode_costs[DC_PRED], &best_mbmi,
4267 best_palette_color_map, &best_rd, &best_model_rd,
4268 rate, rate_tokenonly, distortion, skippable);
hui sude0c70a2017-01-09 17:12:17 -08004269 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07004270
hui su5db97432016-10-14 16:10:14 -07004271#if CONFIG_FILTER_INTRA
4272 if (beat_best_rd) {
4273 if (rd_pick_filter_intra_sby(cpi, x, rate, rate_tokenonly, distortion,
4274 skippable, bsize, bmode_costs[DC_PRED],
hui su8f4cc0a2017-01-13 15:14:49 -08004275 &best_rd, &best_model_rd,
4276 filter_intra_mode_skip_mask)) {
hui sude0c70a2017-01-09 17:12:17 -08004277 best_mbmi = *mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004278 }
4279 }
hui su5db97432016-10-14 16:10:14 -07004280#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07004281
hui sude0c70a2017-01-09 17:12:17 -08004282 *mbmi = best_mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004283 return best_rd;
4284}
4285
Yue Chena1e48dc2016-08-29 17:29:33 -07004286// Return value 0: early termination triggered, no valid rd cost available;
4287// 1: rd cost values are valid.
Angie Chiang284d7772016-11-08 11:06:45 -08004288static int super_block_uvrd(const AV1_COMP *const cpi, MACROBLOCK *x,
4289 RD_STATS *rd_stats, BLOCK_SIZE bsize,
4290 int64_t ref_best_rd) {
Yue Chena1e48dc2016-08-29 17:29:33 -07004291 MACROBLOCKD *const xd = &x->e_mbd;
4292 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
hui su0c6244b2017-07-12 17:11:43 -07004293 const TX_SIZE uv_tx_size = av1_get_uv_tx_size(mbmi, &xd->plane[1]);
Yue Chena1e48dc2016-08-29 17:29:33 -07004294 int plane;
Yue Chena1e48dc2016-08-29 17:29:33 -07004295 int is_cost_valid = 1;
Angie Chiang284d7772016-11-08 11:06:45 -08004296 av1_init_rd_stats(rd_stats);
Yue Chena1e48dc2016-08-29 17:29:33 -07004297
4298 if (ref_best_rd < 0) is_cost_valid = 0;
Jingning Han9ce464c2017-02-20 15:36:30 -08004299
Jingning Han31b6a4f2017-02-23 11:05:53 -08004300#if CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
Jingning Han9ce464c2017-02-20 15:36:30 -08004301 if (x->skip_chroma_rd) return is_cost_valid;
Jingning Han2d2dac22017-04-11 09:41:10 -07004302
4303 bsize = scale_chroma_bsize(bsize, xd->plane[1].subsampling_x,
4304 xd->plane[1].subsampling_y);
Fergus Simpson4063a682017-02-28 16:52:22 -08004305#endif // CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
Jingning Han9ce464c2017-02-20 15:36:30 -08004306
Yushin Cho77bba8d2016-11-04 16:36:56 -07004307#if !CONFIG_PVQ
Yue Chena1e48dc2016-08-29 17:29:33 -07004308 if (is_inter_block(mbmi) && is_cost_valid) {
Yue Chena1e48dc2016-08-29 17:29:33 -07004309 for (plane = 1; plane < MAX_MB_PLANE; ++plane)
4310 av1_subtract_plane(x, bsize, plane);
4311 }
Fergus Simpson4063a682017-02-28 16:52:22 -08004312#endif // !CONFIG_PVQ
Yue Chena1e48dc2016-08-29 17:29:33 -07004313
Yushin Cho09de28b2016-06-21 14:51:23 -07004314 if (is_cost_valid) {
4315 for (plane = 1; plane < MAX_MB_PLANE; ++plane) {
Angie Chiang7c2b7f22016-11-07 16:00:00 -08004316 RD_STATS pn_rd_stats;
4317 txfm_rd_in_plane(x, cpi, &pn_rd_stats, ref_best_rd, plane, bsize,
4318 uv_tx_size, cpi->sf.use_fast_coef_costing);
4319 if (pn_rd_stats.rate == INT_MAX) {
Yushin Cho09de28b2016-06-21 14:51:23 -07004320 is_cost_valid = 0;
4321 break;
4322 }
Angie Chiang284d7772016-11-08 11:06:45 -08004323 av1_merge_rd_stats(rd_stats, &pn_rd_stats);
Urvang Joshi70006e42017-06-14 16:08:55 -07004324 if (RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist) > ref_best_rd &&
4325 RDCOST(x->rdmult, 0, rd_stats->sse) > ref_best_rd) {
Yushin Cho09de28b2016-06-21 14:51:23 -07004326 is_cost_valid = 0;
4327 break;
4328 }
Yue Chena1e48dc2016-08-29 17:29:33 -07004329 }
4330 }
4331
4332 if (!is_cost_valid) {
4333 // reset cost value
Angie Chiang284d7772016-11-08 11:06:45 -08004334 av1_invalid_rd_stats(rd_stats);
Yue Chena1e48dc2016-08-29 17:29:33 -07004335 }
4336
4337 return is_cost_valid;
4338}
4339
Yaowu Xuc27fc142016-08-22 16:08:15 -07004340#if CONFIG_VAR_TX
Yaowu Xuf883b422016-08-30 14:01:10 -07004341void av1_tx_block_rd_b(const AV1_COMP *cpi, MACROBLOCK *x, TX_SIZE tx_size,
4342 int blk_row, int blk_col, int plane, int block,
Angie Chiang77368af2017-03-23 16:22:07 -07004343 int plane_bsize, const ENTROPY_CONTEXT *a,
4344 const ENTROPY_CONTEXT *l, RD_STATS *rd_stats) {
Angie Chiang22ba7512016-10-20 17:10:33 -07004345 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004346 MACROBLOCKD *xd = &x->e_mbd;
4347 const struct macroblock_plane *const p = &x->plane[plane];
4348 struct macroblockd_plane *const pd = &xd->plane[plane];
Jingning Han243b66b2017-06-23 12:11:47 -07004349
4350#if CONFIG_TXK_SEL
4351 av1_search_txk_type(cpi, x, plane, block, blk_row, blk_col, plane_bsize,
4352 tx_size, a, l, 0, rd_stats);
4353 return;
4354#endif
4355
Yaowu Xuc27fc142016-08-22 16:08:15 -07004356 int64_t tmp;
4357 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
Sarah Parker99e7daa2017-08-29 10:30:13 -07004358#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
4359 uint8_t *mrc_mask = BLOCK_OFFSET(xd->mrc_mask, block);
4360#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
Luc Trudeau005feb62017-02-22 13:34:01 -05004361 PLANE_TYPE plane_type = get_plane_type(plane);
Jingning Han19b5c8f2017-07-06 15:10:12 -07004362 TX_TYPE tx_type =
4363 av1_get_tx_type(plane_type, xd, blk_row, blk_col, block, tx_size);
Urvang Joshi03f6fdc2016-10-14 15:53:39 -07004364 const SCAN_ORDER *const scan_order =
Angie Chiangbd99b382017-06-20 15:11:16 -07004365 get_scan(cm, tx_size, tx_type, &xd->mi[0]->mbmi);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004366 BLOCK_SIZE txm_bsize = txsize_to_bsize[tx_size];
Jingning Han9fdc4222016-10-27 21:32:19 -07004367 int bh = block_size_high[txm_bsize];
4368 int bw = block_size_wide[txm_bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004369 int src_stride = p->src.stride;
Jingning Han9ca05b72017-01-03 14:41:36 -08004370 uint8_t *src =
4371 &p->src.buf[(blk_row * src_stride + blk_col) << tx_size_wide_log2[0]];
4372 uint8_t *dst =
4373 &pd->dst
4374 .buf[(blk_row * pd->dst.stride + blk_col) << tx_size_wide_log2[0]];
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02004375#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07004376 DECLARE_ALIGNED(16, uint16_t, rec_buffer16[MAX_TX_SQUARE]);
4377 uint8_t *rec_buffer;
4378#else
4379 DECLARE_ALIGNED(16, uint8_t, rec_buffer[MAX_TX_SQUARE]);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02004380#endif // CONFIG_HIGHBITDEPTH
Timothy B. Terriberryd62e2a32017-06-10 16:04:21 -07004381 const int diff_stride = block_size_wide[plane_bsize];
Jingning Han9ca05b72017-01-03 14:41:36 -08004382 const int16_t *diff =
4383 &p->src_diff[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
Angie Chiangd81fdb42016-11-03 12:20:58 -07004384 int txb_coeff_cost;
Jingning Hand3fada82016-11-22 10:46:55 -08004385
4386 assert(tx_size < TX_SIZES_ALL);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004387
Angie Chiang77368af2017-03-23 16:22:07 -07004388 int coeff_ctx = get_entropy_context(tx_size, a, l);
4389
Jingning Han1a7f0a82017-07-27 09:48:05 -07004390 tmp = pixel_diff_dist(x, plane, diff, diff_stride, blk_row, blk_col,
4391 plane_bsize, txm_bsize);
4392
4393#if CONFIG_HIGHBITDEPTH
4394 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
4395 tmp = ROUND_POWER_OF_TWO(tmp, (xd->bd - 8) * 2);
4396#endif // CONFIG_HIGHBITDEPTH
4397 rd_stats->sse += tmp << 4;
4398
4399 if (rd_stats->invalid_rate) {
4400 rd_stats->dist += tmp << 4;
4401 rd_stats->rate += rd_stats->zero_rate;
4402 rd_stats->skip = 1;
4403 return;
4404 }
4405
Angie Chiang808d8592017-04-06 18:36:55 -07004406// TODO(any): Use av1_dist_block to compute distortion
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02004407#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07004408 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
4409 rec_buffer = CONVERT_TO_BYTEPTR(rec_buffer16);
Yaowu Xuf883b422016-08-30 14:01:10 -07004410 aom_highbd_convolve_copy(dst, pd->dst.stride, rec_buffer, MAX_TX_SIZE, NULL,
Jingning Han9fdc4222016-10-27 21:32:19 -07004411 0, NULL, 0, bw, bh, xd->bd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004412 } else {
4413 rec_buffer = (uint8_t *)rec_buffer16;
Yaowu Xuf883b422016-08-30 14:01:10 -07004414 aom_convolve_copy(dst, pd->dst.stride, rec_buffer, MAX_TX_SIZE, NULL, 0,
Jingning Han9fdc4222016-10-27 21:32:19 -07004415 NULL, 0, bw, bh);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004416 }
4417#else
Yaowu Xuf883b422016-08-30 14:01:10 -07004418 aom_convolve_copy(dst, pd->dst.stride, rec_buffer, MAX_TX_SIZE, NULL, 0, NULL,
Jingning Han9fdc4222016-10-27 21:32:19 -07004419 0, bw, bh);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02004420#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07004421
Jingning Han3bce7542017-07-25 10:53:57 -07004422#if DISABLE_TRELLISQ_SEARCH
4423 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
4424 coeff_ctx, AV1_XFORM_QUANT_B);
4425
4426#else
4427 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
4428 coeff_ctx, AV1_XFORM_QUANT_FP);
4429
4430 const int shift = (MAX_TX_SCALE - av1_get_tx_scale(tx_size)) * 2;
4431 tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
4432 const int buffer_length = tx_size_2d[tx_size];
Jingning Han1a7f0a82017-07-27 09:48:05 -07004433 int64_t tmp_dist, tmp_sse;
Yunqing Wang24d2d5d2017-09-20 09:45:13 -07004434#if CONFIG_DIST_8X8
Yushin Choc00769a2017-09-14 14:44:30 -07004435 int disable_early_skip =
4436 x->using_dist_8x8 && plane == 0 && plane_bsize >= BLOCK_8X8 &&
4437 (tx_size == TX_4X4 || tx_size == TX_4X8 || tx_size == TX_8X4) &&
4438 x->tune_metric != AOM_TUNE_PSNR;
Yunqing Wang24d2d5d2017-09-20 09:45:13 -07004439#endif // CONFIG_DIST_8X8
4440
Jingning Han3bce7542017-07-25 10:53:57 -07004441#if CONFIG_HIGHBITDEPTH
4442 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
Debargha Mukherjeeb02d2f32017-10-03 11:06:40 -07004443 tmp_dist =
4444 av1_highbd_block_error(coeff, dqcoeff, buffer_length, &tmp_sse, xd->bd);
Jingning Han3bce7542017-07-25 10:53:57 -07004445 else
4446#endif
Debargha Mukherjeeb02d2f32017-10-03 11:06:40 -07004447 tmp_dist = av1_block_error(coeff, dqcoeff, buffer_length, &tmp_sse);
4448
4449 tmp_dist = RIGHT_SIGNED_SHIFT(tmp_dist, shift);
Jingning Han3bce7542017-07-25 10:53:57 -07004450
Sarah Parkerde6f0722017-08-07 20:23:46 -07004451#if CONFIG_MRC_TX
4452 if (tx_type == MRC_DCT && !xd->mi[0]->mbmi.valid_mrc_mask) {
4453 av1_invalid_rd_stats(rd_stats);
4454 return;
4455 }
4456#endif // CONFIG_MRC_TX
Yushin Choa4817a62017-07-27 13:09:43 -07004457 if (
4458#if CONFIG_DIST_8X8
Yushin Choc00769a2017-09-14 14:44:30 -07004459 disable_early_skip ||
Yushin Choa4817a62017-07-27 13:09:43 -07004460#endif
4461 RDCOST(x->rdmult, 0, tmp_dist) < rd_stats->ref_rdcost) {
Jingning Han3bce7542017-07-25 10:53:57 -07004462 av1_optimize_b(cm, x, plane, blk_row, blk_col, block, plane_bsize, tx_size,
Angie Chiang25645b72017-09-24 14:28:49 -07004463 a, l, 1);
Jingning Han1a7f0a82017-07-27 09:48:05 -07004464 } else {
4465 rd_stats->rate += rd_stats->zero_rate;
Debargha Mukherjeeb02d2f32017-10-03 11:06:40 -07004466 rd_stats->dist += RIGHT_SIGNED_SHIFT(tmp_sse, shift);
4467 rd_stats->sse += RIGHT_SIGNED_SHIFT(tmp_sse, shift);
Jingning Han1a7f0a82017-07-27 09:48:05 -07004468 rd_stats->skip = 1;
4469 rd_stats->invalid_rate = 1;
4470 return;
Jingning Han3bce7542017-07-25 10:53:57 -07004471 }
4472#endif // DISABLE_TRELLISQ_SEARCH
4473
Angie Chiang41fffae2017-04-03 10:33:18 -07004474 const int eob = p->eobs[block];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004475
Lester Lu918fe692017-08-17 14:39:29 -07004476 av1_inverse_transform_block(xd, dqcoeff,
Lester Lu708c1ec2017-06-14 14:54:49 -07004477#if CONFIG_LGT
Lester Lu918fe692017-08-17 14:39:29 -07004478 xd->mi[0]->mbmi.mode,
Lester Lu708c1ec2017-06-14 14:54:49 -07004479#endif
Sarah Parker99e7daa2017-08-29 10:30:13 -07004480#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
4481 mrc_mask,
4482#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
Lester Lu918fe692017-08-17 14:39:29 -07004483 tx_type, tx_size, rec_buffer, MAX_TX_SIZE, eob);
Angie Chiang41fffae2017-04-03 10:33:18 -07004484 if (eob > 0) {
Yushin Chob7b60c52017-07-14 16:18:52 -07004485#if CONFIG_DIST_8X8
Yushin Cho55104332017-08-14 16:15:43 -07004486 if (x->using_dist_8x8 && plane == 0 && (bw < 8 && bh < 8)) {
Yushin Cho04749122017-05-25 14:19:07 -07004487 // Save sub8x8 luma decoded pixels
4488 // since 8x8 luma decoded pixels are not available for daala-dist
4489 // after recursive split of BLOCK_8x8 is done.
4490 const int pred_stride = block_size_wide[plane_bsize];
4491 const int pred_idx = (blk_row * pred_stride + blk_col)
4492 << tx_size_wide_log2[0];
4493 int16_t *decoded = &pd->pred[pred_idx];
4494 int i, j;
4495
Yushin Cho8ab875d2017-06-23 14:47:21 -07004496#if CONFIG_HIGHBITDEPTH
4497 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
4498 for (j = 0; j < bh; j++)
4499 for (i = 0; i < bw; i++)
4500 decoded[j * pred_stride + i] =
4501 CONVERT_TO_SHORTPTR(rec_buffer)[j * MAX_TX_SIZE + i];
4502 } else {
4503#endif
4504 for (j = 0; j < bh; j++)
4505 for (i = 0; i < bw; i++)
4506 decoded[j * pred_stride + i] = rec_buffer[j * MAX_TX_SIZE + i];
4507#if CONFIG_HIGHBITDEPTH
4508 }
4509#endif // CONFIG_HIGHBITDEPTH
Yushin Cho04749122017-05-25 14:19:07 -07004510 }
Yushin Chob7b60c52017-07-14 16:18:52 -07004511#endif // CONFIG_DIST_8X8
Yushin Cho75b01002017-06-21 13:43:57 -07004512 tmp = pixel_dist(cpi, x, plane, src, src_stride, rec_buffer, MAX_TX_SIZE,
4513 blk_row, blk_col, plane_bsize, txm_bsize);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004514 }
Angie Chiangb5dda482016-11-02 16:19:58 -07004515 rd_stats->dist += tmp * 16;
Jingning Han7eab9ff2017-07-06 10:12:54 -07004516 txb_coeff_cost = av1_cost_coeffs(cpi, x, plane, blk_row, blk_col, block,
4517 tx_size, scan_order, a, l, 0);
Angie Chiangd81fdb42016-11-03 12:20:58 -07004518 rd_stats->rate += txb_coeff_cost;
Angie Chiang41fffae2017-04-03 10:33:18 -07004519 rd_stats->skip &= (eob == 0);
Jingning Han63cbf342016-11-09 15:37:48 -08004520
Angie Chiangd81fdb42016-11-03 12:20:58 -07004521#if CONFIG_RD_DEBUG
Angie Chiange94556b2016-11-09 10:59:30 -08004522 av1_update_txb_coeff_cost(rd_stats, plane, tx_size, blk_row, blk_col,
4523 txb_coeff_cost);
Fergus Simpson4063a682017-02-28 16:52:22 -08004524#endif // CONFIG_RD_DEBUG
Yaowu Xuc27fc142016-08-22 16:08:15 -07004525}
4526
Yaowu Xuf883b422016-08-30 14:01:10 -07004527static void select_tx_block(const AV1_COMP *cpi, MACROBLOCK *x, int blk_row,
Jingning Han63cbf342016-11-09 15:37:48 -08004528 int blk_col, int plane, int block, int block32,
4529 TX_SIZE tx_size, int depth, BLOCK_SIZE plane_bsize,
Jingning Han94d5bfc2016-10-21 10:14:36 -07004530 ENTROPY_CONTEXT *ta, ENTROPY_CONTEXT *tl,
4531 TXFM_CONTEXT *tx_above, TXFM_CONTEXT *tx_left,
Angie Chiangb5dda482016-11-02 16:19:58 -07004532 RD_STATS *rd_stats, int64_t ref_best_rd,
Jingning Han63cbf342016-11-09 15:37:48 -08004533 int *is_cost_valid, RD_STATS *rd_stats_stack) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07004534 MACROBLOCKD *const xd = &x->e_mbd;
4535 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
4536 struct macroblock_plane *const p = &x->plane[plane];
4537 struct macroblockd_plane *const pd = &xd->plane[plane];
4538 const int tx_row = blk_row >> (1 - pd->subsampling_y);
4539 const int tx_col = blk_col >> (1 - pd->subsampling_x);
clang-format67948d32016-09-07 22:40:40 -07004540 TX_SIZE(*const inter_tx_size)
Yaowu Xuc27fc142016-08-22 16:08:15 -07004541 [MAX_MIB_SIZE] =
4542 (TX_SIZE(*)[MAX_MIB_SIZE]) & mbmi->inter_tx_size[tx_row][tx_col];
Jingning Hanf65b8702016-10-31 12:13:20 -07004543 const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
4544 const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
Jingning Han58224042016-10-27 16:35:32 -07004545 const int bw = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004546 int64_t this_rd = INT64_MAX;
4547 ENTROPY_CONTEXT *pta = ta + blk_col;
4548 ENTROPY_CONTEXT *ptl = tl + blk_row;
Jingning Han5a995d72017-07-02 15:20:54 -07004549 int i;
Jingning Han331662e2017-05-30 17:03:32 -07004550 int ctx = txfm_partition_context(tx_above + blk_col, tx_left + blk_row,
4551 mbmi->sb_type, tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004552 int64_t sum_rd = INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004553 int tmp_eob = 0;
4554 int zero_blk_rate;
Angie Chiangd7246172016-11-03 11:49:15 -07004555 RD_STATS sum_rd_stats;
Jingning Hane3b81bc2017-06-23 11:43:52 -07004556#if CONFIG_TXK_SEL
4557 TX_TYPE best_tx_type = TX_TYPES;
Jingning Han19b5c8f2017-07-06 15:10:12 -07004558 int txk_idx = (blk_row << 4) + blk_col;
Jingning Hane3b81bc2017-06-23 11:43:52 -07004559#endif
Yue Chend6bdd462017-07-19 16:05:43 -07004560#if CONFIG_RECT_TX_EXT
4561 TX_SIZE quarter_txsize = quarter_txsize_lookup[mbmi->sb_type];
4562 int check_qttx = is_quarter_tx_allowed(xd, mbmi, is_inter_block(mbmi)) &&
4563 tx_size == max_txsize_rect_lookup[mbmi->sb_type] &&
4564 quarter_txsize != tx_size;
4565 int is_qttx_picked = 0;
4566 int eobs_qttx[2] = { 0, 0 };
4567 int skip_qttx[2] = { 0, 0 };
4568 int block_offset_qttx = check_qttx
4569 ? tx_size_wide_unit[quarter_txsize] *
4570 tx_size_high_unit[quarter_txsize]
4571 : 0;
4572 int blk_row_offset, blk_col_offset;
4573 int is_wide_qttx =
4574 tx_size_wide_unit[quarter_txsize] > tx_size_high_unit[quarter_txsize];
4575 blk_row_offset = is_wide_qttx ? tx_size_high_unit[quarter_txsize] : 0;
4576 blk_col_offset = is_wide_qttx ? 0 : tx_size_wide_unit[quarter_txsize];
4577#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07004578
Jingning Han63cbf342016-11-09 15:37:48 -08004579 av1_init_rd_stats(&sum_rd_stats);
Jingning Hanfe45b212016-11-22 10:30:23 -08004580
Jingning Hand3fada82016-11-22 10:46:55 -08004581 assert(tx_size < TX_SIZES_ALL);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004582
4583 if (ref_best_rd < 0) {
4584 *is_cost_valid = 0;
4585 return;
4586 }
4587
Angie Chiangc0feea82016-11-03 15:36:18 -07004588 av1_init_rd_stats(rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004589
4590 if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
4591
Jingning Han5a995d72017-07-02 15:20:54 -07004592#if CONFIG_LV_MAP
4593 TX_SIZE txs_ctx = get_txsize_context(tx_size);
4594 TXB_CTX txb_ctx;
4595 get_txb_ctx(plane_bsize, tx_size, plane, pta, ptl, &txb_ctx);
Jingning Hane9814912017-08-31 16:38:59 -07004596
4597#if LV_MAP_PROB
4598 zero_blk_rate = x->coeff_costs[txs_ctx][get_plane_type(plane)]
4599 .txb_skip_cost[txb_ctx.txb_skip_ctx][1];
4600#else
Jingning Han5a995d72017-07-02 15:20:54 -07004601 zero_blk_rate =
4602 av1_cost_bit(xd->fc->txb_skip[txs_ctx][txb_ctx.txb_skip_ctx], 1);
Jingning Hane9814912017-08-31 16:38:59 -07004603#endif // LV_MAP_PROB
Jingning Han5a995d72017-07-02 15:20:54 -07004604#else
Urvang Joshi9752a2e2017-10-02 17:32:27 -07004605 TX_SIZE tx_size_ctx = txsize_sqr_map[tx_size];
Jingning Han5a995d72017-07-02 15:20:54 -07004606 int coeff_ctx = get_entropy_context(tx_size, pta, ptl);
hui suc0cf71d2017-07-20 16:38:50 -07004607 zero_blk_rate =
4608 x->token_head_costs[tx_size_ctx][pd->plane_type][1][0][coeff_ctx][0];
Jingning Han5a995d72017-07-02 15:20:54 -07004609#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07004610
Jingning Han3bce7542017-07-25 10:53:57 -07004611 rd_stats->ref_rdcost = ref_best_rd;
4612 rd_stats->zero_rate = zero_blk_rate;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004613 if (cpi->common.tx_mode == TX_MODE_SELECT || tx_size == TX_4X4) {
4614 inter_tx_size[0][0] = tx_size;
Yushin Choc5a1f262017-10-02 17:17:19 -07004615 if (tx_size == TX_32X32 && mbmi->tx_type != DCT_DCT &&
4616 rd_stats_stack[block32].rate != INT_MAX
Sarah Parkerde6f0722017-08-07 20:23:46 -07004617#if CONFIG_MRC_TX
Yushin Choc5a1f262017-10-02 17:17:19 -07004618 && !USE_MRC_INTER
Sarah Parkerde6f0722017-08-07 20:23:46 -07004619#endif // CONFIG_MRC_TX
Yushin Choc5a1f262017-10-02 17:17:19 -07004620 ) {
Jingning Han63cbf342016-11-09 15:37:48 -08004621 *rd_stats = rd_stats_stack[block32];
4622 p->eobs[block] = !rd_stats->skip;
4623 x->blk_skip[plane][blk_row * bw + blk_col] = rd_stats->skip;
4624 } else {
4625 av1_tx_block_rd_b(cpi, x, tx_size, blk_row, blk_col, plane, block,
Angie Chiang77368af2017-03-23 16:22:07 -07004626 plane_bsize, pta, ptl, rd_stats);
Jingning Han63cbf342016-11-09 15:37:48 -08004627 if (tx_size == TX_32X32) {
4628 rd_stats_stack[block32] = *rd_stats;
4629 }
4630 }
Sarah Parkerde6f0722017-08-07 20:23:46 -07004631 if (rd_stats->rate == INT_MAX) return;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004632
Urvang Joshi70006e42017-06-14 16:08:55 -07004633 if ((RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist) >=
4634 RDCOST(x->rdmult, zero_blk_rate, rd_stats->sse) ||
Angie Chiangb5dda482016-11-02 16:19:58 -07004635 rd_stats->skip == 1) &&
Yaowu Xuc27fc142016-08-22 16:08:15 -07004636 !xd->lossless[mbmi->segment_id]) {
Jingning Hanc7ea7612017-01-11 15:01:30 -08004637#if CONFIG_RD_DEBUG
4638 av1_update_txb_coeff_cost(rd_stats, plane, tx_size, blk_row, blk_col,
4639 zero_blk_rate - rd_stats->rate);
Fergus Simpson4063a682017-02-28 16:52:22 -08004640#endif // CONFIG_RD_DEBUG
Angie Chiangb5dda482016-11-02 16:19:58 -07004641 rd_stats->rate = zero_blk_rate;
4642 rd_stats->dist = rd_stats->sse;
4643 rd_stats->skip = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004644 x->blk_skip[plane][blk_row * bw + blk_col] = 1;
4645 p->eobs[block] = 0;
Jingning Han19b5c8f2017-07-06 15:10:12 -07004646#if CONFIG_TXK_SEL
4647 mbmi->txk_type[txk_idx] = DCT_DCT;
4648#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07004649 } else {
4650 x->blk_skip[plane][blk_row * bw + blk_col] = 0;
Angie Chiangb5dda482016-11-02 16:19:58 -07004651 rd_stats->skip = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004652 }
4653
Jingning Han571189c2016-10-24 10:38:43 -07004654 if (tx_size > TX_4X4 && depth < MAX_VARTX_DEPTH)
Angie Chiangb5dda482016-11-02 16:19:58 -07004655 rd_stats->rate +=
4656 av1_cost_bit(cpi->common.fc->txfm_partition_prob[ctx], 0);
Yue Chend6bdd462017-07-19 16:05:43 -07004657#if CONFIG_RECT_TX_EXT
4658 if (check_qttx) {
4659 assert(blk_row == 0 && blk_col == 0);
4660 rd_stats->rate += av1_cost_bit(cpi->common.fc->quarter_tx_size_prob, 0);
4661 }
4662#endif
Urvang Joshi70006e42017-06-14 16:08:55 -07004663 this_rd = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
Jingning Han2f42d772017-07-05 16:28:18 -07004664#if CONFIG_LV_MAP
4665 tmp_eob = p->txb_entropy_ctx[block];
4666#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07004667 tmp_eob = p->eobs[block];
Jingning Han2f42d772017-07-05 16:28:18 -07004668#endif
4669
Jingning Hane3b81bc2017-06-23 11:43:52 -07004670#if CONFIG_TXK_SEL
4671 best_tx_type = mbmi->txk_type[txk_idx];
4672#endif
Yue Chend6bdd462017-07-19 16:05:43 -07004673
4674#if CONFIG_RECT_TX_EXT
4675 if (check_qttx) {
4676 assert(blk_row == 0 && blk_col == 0 && block == 0 && plane == 0);
4677
4678 RD_STATS rd_stats_tmp, rd_stats_qttx;
4679 int64_t rd_qttx;
4680
4681 av1_init_rd_stats(&rd_stats_qttx);
4682 av1_init_rd_stats(&rd_stats_tmp);
4683
4684 av1_tx_block_rd_b(cpi, x, quarter_txsize, 0, 0, plane, 0, plane_bsize,
4685 pta, ptl, &rd_stats_qttx);
Sarah Parkerde6f0722017-08-07 20:23:46 -07004686 if (rd_stats->rate == INT_MAX) return;
Yue Chend6bdd462017-07-19 16:05:43 -07004687
4688 tx_size_ctx = txsize_sqr_map[quarter_txsize];
4689 coeff_ctx = get_entropy_context(quarter_txsize, pta, ptl);
hui suc0cf71d2017-07-20 16:38:50 -07004690 zero_blk_rate =
4691 x->token_head_costs[tx_size_ctx][pd->plane_type][1][0][coeff_ctx][0];
Yue Chend6bdd462017-07-19 16:05:43 -07004692 if ((RDCOST(x->rdmult, rd_stats_qttx.rate, rd_stats_qttx.dist) >=
4693 RDCOST(x->rdmult, zero_blk_rate, rd_stats_qttx.sse) ||
4694 rd_stats_qttx.skip == 1) &&
4695 !xd->lossless[mbmi->segment_id]) {
4696#if CONFIG_RD_DEBUG
4697 av1_update_txb_coeff_cost(&rd_stats_qttx, plane, quarter_txsize, 0, 0,
4698 zero_blk_rate - rd_stats_qttx.rate);
4699#endif // CONFIG_RD_DEBUG
4700 rd_stats_qttx.rate = zero_blk_rate;
4701 rd_stats_qttx.dist = rd_stats_qttx.sse;
4702 rd_stats_qttx.skip = 1;
4703 x->blk_skip[plane][blk_row * bw + blk_col] = 1;
4704 skip_qttx[0] = 1;
4705 p->eobs[block] = 0;
4706 } else {
4707 x->blk_skip[plane][blk_row * bw + blk_col] = 0;
4708 skip_qttx[0] = 0;
4709 rd_stats->skip = 0;
4710 }
4711
4712 // Second tx block
4713 av1_tx_block_rd_b(cpi, x, quarter_txsize, blk_row_offset, blk_col_offset,
4714 plane, block_offset_qttx, plane_bsize, pta, ptl,
4715 &rd_stats_tmp);
4716
Sarah Parkerde6f0722017-08-07 20:23:46 -07004717 if (rd_stats->rate == INT_MAX) return;
4718
Tom Fineganac870492017-08-15 16:19:13 -07004719#if !CONFIG_PVQ
Yue Chend6bdd462017-07-19 16:05:43 -07004720 av1_set_txb_context(x, plane, 0, quarter_txsize, pta, ptl);
Tom Fineganac870492017-08-15 16:19:13 -07004721#endif // !CONFIG_PVQ
Yue Chend6bdd462017-07-19 16:05:43 -07004722 coeff_ctx = get_entropy_context(quarter_txsize, pta + blk_col_offset,
4723 ptl + blk_row_offset);
hui suc0cf71d2017-07-20 16:38:50 -07004724 zero_blk_rate =
4725 x->token_head_costs[tx_size_ctx][pd->plane_type][1][0][coeff_ctx][0];
Yue Chend6bdd462017-07-19 16:05:43 -07004726 if ((RDCOST(x->rdmult, rd_stats_tmp.rate, rd_stats_tmp.dist) >=
4727 RDCOST(x->rdmult, zero_blk_rate, rd_stats_tmp.sse) ||
4728 rd_stats_tmp.skip == 1) &&
4729 !xd->lossless[mbmi->segment_id]) {
4730#if CONFIG_RD_DEBUG
4731 av1_update_txb_coeff_cost(&rd_stats_tmp, plane, quarter_txsize, 0, 0,
4732 zero_blk_rate - rd_stats_tmp.rate);
4733#endif // CONFIG_RD_DEBUG
4734 rd_stats_tmp.rate = zero_blk_rate;
4735 rd_stats_tmp.dist = rd_stats_tmp.sse;
4736 rd_stats_tmp.skip = 1;
4737 x->blk_skip[plane][blk_row_offset * bw + blk_col_offset] = 1;
4738 skip_qttx[1] = 1;
4739 p->eobs[block_offset_qttx] = 0;
4740 } else {
4741 x->blk_skip[plane][blk_row_offset * bw + blk_col_offset] = 0;
4742 skip_qttx[1] = 0;
4743 rd_stats_tmp.skip = 0;
4744 }
4745
4746 av1_merge_rd_stats(&rd_stats_qttx, &rd_stats_tmp);
4747
4748 if (tx_size > TX_4X4 && depth < MAX_VARTX_DEPTH) {
4749 rd_stats_qttx.rate +=
4750 av1_cost_bit(cpi->common.fc->txfm_partition_prob[ctx], 0);
4751 }
4752 rd_stats_qttx.rate +=
4753 av1_cost_bit(cpi->common.fc->quarter_tx_size_prob, 1);
4754 rd_qttx = RDCOST(x->rdmult, rd_stats_qttx.rate, rd_stats_qttx.dist);
4755#if CONFIG_LV_MAP
4756 eobs_qttx[0] = p->txb_entropy_ctx[0];
4757 eobs_qttx[1] = p->txb_entropy_ctx[block_offset_qttx];
4758#else
4759 eobs_qttx[0] = p->eobs[0];
4760 eobs_qttx[1] = p->eobs[block_offset_qttx];
4761#endif
4762 if (rd_qttx < this_rd) {
4763 is_qttx_picked = 1;
4764 this_rd = rd_qttx;
4765 rd_stats->rate = rd_stats_qttx.rate;
4766 rd_stats->dist = rd_stats_qttx.dist;
4767 rd_stats->sse = rd_stats_qttx.sse;
4768 rd_stats->skip = rd_stats_qttx.skip;
4769 rd_stats->rdcost = rd_stats_qttx.rdcost;
4770 }
4771 av1_get_entropy_contexts(plane_bsize, 0, pd, ta, tl);
4772 }
4773#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07004774 }
4775
Yushin Choc5a1f262017-10-02 17:17:19 -07004776 if (tx_size > TX_4X4 && depth < MAX_VARTX_DEPTH
Sarah Parker53f93db2017-07-11 17:20:04 -07004777#if CONFIG_MRC_TX
Yushin Choc5a1f262017-10-02 17:17:19 -07004778 // If the tx type we are trying is MRC_DCT, we cannot partition the
4779 // transform into anything smaller than TX_32X32
4780 && mbmi->tx_type != MRC_DCT
4781#endif // CONFIG_MRC_TX
4782 ) {
Jingning Han18482fe2016-11-02 17:01:58 -07004783 const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
4784 const int bsl = tx_size_wide_unit[sub_txs];
Jingning Han58224042016-10-27 16:35:32 -07004785 int sub_step = tx_size_wide_unit[sub_txs] * tx_size_high_unit[sub_txs];
Angie Chiangb5dda482016-11-02 16:19:58 -07004786 RD_STATS this_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004787 int this_cost_valid = 1;
4788 int64_t tmp_rd = 0;
Yushin Chob7b60c52017-07-14 16:18:52 -07004789#if CONFIG_DIST_8X8
Yushin Cho04749122017-05-25 14:19:07 -07004790 int sub8x8_eob[4];
4791#endif
Angie Chiangd7246172016-11-03 11:49:15 -07004792 sum_rd_stats.rate =
4793 av1_cost_bit(cpi->common.fc->txfm_partition_prob[ctx], 1);
Jingning Hand3fada82016-11-22 10:46:55 -08004794
4795 assert(tx_size < TX_SIZES_ALL);
4796
Jingning Han16a9df72017-07-26 15:27:43 -07004797 ref_best_rd = AOMMIN(this_rd, ref_best_rd);
4798
Yaowu Xuc27fc142016-08-22 16:08:15 -07004799 for (i = 0; i < 4 && this_cost_valid; ++i) {
Jingning Han98d6a1f2016-11-03 12:47:47 -07004800 int offsetr = blk_row + (i >> 1) * bsl;
4801 int offsetc = blk_col + (i & 0x01) * bsl;
4802
4803 if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
4804
Jingning Han63cbf342016-11-09 15:37:48 -08004805 select_tx_block(cpi, x, offsetr, offsetc, plane, block, block32, sub_txs,
Jingning Han98d6a1f2016-11-03 12:47:47 -07004806 depth + 1, plane_bsize, ta, tl, tx_above, tx_left,
Jingning Han63cbf342016-11-09 15:37:48 -08004807 &this_rd_stats, ref_best_rd - tmp_rd, &this_cost_valid,
4808 rd_stats_stack);
Yushin Chob7b60c52017-07-14 16:18:52 -07004809#if CONFIG_DIST_8X8
Yushin Cho55104332017-08-14 16:15:43 -07004810 if (x->using_dist_8x8 && plane == 0 && tx_size == TX_8X8) {
Yushin Cho04749122017-05-25 14:19:07 -07004811 sub8x8_eob[i] = p->eobs[block];
4812 }
Yushin Chob7b60c52017-07-14 16:18:52 -07004813#endif // CONFIG_DIST_8X8
Angie Chiangc0feea82016-11-03 15:36:18 -07004814 av1_merge_rd_stats(&sum_rd_stats, &this_rd_stats);
Jingning Han98d6a1f2016-11-03 12:47:47 -07004815
Urvang Joshi70006e42017-06-14 16:08:55 -07004816 tmp_rd = RDCOST(x->rdmult, sum_rd_stats.rate, sum_rd_stats.dist);
Yushin Cho55104332017-08-14 16:15:43 -07004817#if CONFIG_DIST_8X8
4818 if (!x->using_dist_8x8)
Yushin Cho04749122017-05-25 14:19:07 -07004819#endif
Yushin Cho55104332017-08-14 16:15:43 -07004820 if (this_rd < tmp_rd) break;
Jingning Han98d6a1f2016-11-03 12:47:47 -07004821 block += sub_step;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004822 }
Yushin Chob7b60c52017-07-14 16:18:52 -07004823#if CONFIG_DIST_8X8
Yushin Cho55104332017-08-14 16:15:43 -07004824 if (x->using_dist_8x8 && this_cost_valid && plane == 0 &&
4825 tx_size == TX_8X8) {
Yushin Cho04749122017-05-25 14:19:07 -07004826 const int src_stride = p->src.stride;
4827 const int dst_stride = pd->dst.stride;
4828
4829 const uint8_t *src =
4830 &p->src.buf[(blk_row * src_stride + blk_col) << tx_size_wide_log2[0]];
4831 const uint8_t *dst =
4832 &pd->dst
4833 .buf[(blk_row * dst_stride + blk_col) << tx_size_wide_log2[0]];
4834
Yushin Chob7b60c52017-07-14 16:18:52 -07004835 int64_t dist_8x8;
Yushin Cho04749122017-05-25 14:19:07 -07004836 int qindex = x->qindex;
4837 const int pred_stride = block_size_wide[plane_bsize];
4838 const int pred_idx = (blk_row * pred_stride + blk_col)
4839 << tx_size_wide_log2[0];
4840 int16_t *pred = &pd->pred[pred_idx];
4841 int j;
Yushin Cho04749122017-05-25 14:19:07 -07004842 int row, col;
4843
Yushin Cho8ab875d2017-06-23 14:47:21 -07004844#if CONFIG_HIGHBITDEPTH
4845 uint8_t *pred8;
4846 DECLARE_ALIGNED(16, uint16_t, pred8_16[8 * 8]);
4847#else
Yushin Cho04749122017-05-25 14:19:07 -07004848 DECLARE_ALIGNED(16, uint8_t, pred8[8 * 8]);
Yushin Cho8ab875d2017-06-23 14:47:21 -07004849#endif // CONFIG_HIGHBITDEPTH
Yushin Cho04749122017-05-25 14:19:07 -07004850
Yushin Choe30a47c2017-08-15 13:08:30 -07004851 dist_8x8 = av1_dist_8x8(cpi, x, src, src_stride, dst, dst_stride,
Yushin Chob7b60c52017-07-14 16:18:52 -07004852 BLOCK_8X8, 8, 8, 8, 8, qindex) *
4853 16;
4854 sum_rd_stats.sse = dist_8x8;
Yushin Cho04749122017-05-25 14:19:07 -07004855
Yushin Cho8ab875d2017-06-23 14:47:21 -07004856#if CONFIG_HIGHBITDEPTH
4857 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
4858 pred8 = CONVERT_TO_BYTEPTR(pred8_16);
4859 else
4860 pred8 = (uint8_t *)pred8_16;
4861#endif
Yushin Cho04749122017-05-25 14:19:07 -07004862
Yushin Cho8ab875d2017-06-23 14:47:21 -07004863#if CONFIG_HIGHBITDEPTH
4864 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
4865 for (row = 0; row < 2; ++row) {
4866 for (col = 0; col < 2; ++col) {
4867 int idx = row * 2 + col;
4868 int eob = sub8x8_eob[idx];
4869
4870 if (eob > 0) {
4871 for (j = 0; j < 4; j++)
4872 for (i = 0; i < 4; i++)
4873 CONVERT_TO_SHORTPTR(pred8)
4874 [(row * 4 + j) * 8 + 4 * col + i] =
4875 pred[(row * 4 + j) * pred_stride + 4 * col + i];
4876 } else {
4877 for (j = 0; j < 4; j++)
4878 for (i = 0; i < 4; i++)
4879 CONVERT_TO_SHORTPTR(pred8)
4880 [(row * 4 + j) * 8 + 4 * col + i] = CONVERT_TO_SHORTPTR(
4881 dst)[(row * 4 + j) * dst_stride + 4 * col + i];
4882 }
Yushin Cho04749122017-05-25 14:19:07 -07004883 }
4884 }
Yushin Cho8ab875d2017-06-23 14:47:21 -07004885 } else {
4886#endif
4887 for (row = 0; row < 2; ++row) {
4888 for (col = 0; col < 2; ++col) {
4889 int idx = row * 2 + col;
4890 int eob = sub8x8_eob[idx];
4891
4892 if (eob > 0) {
4893 for (j = 0; j < 4; j++)
4894 for (i = 0; i < 4; i++)
4895 pred8[(row * 4 + j) * 8 + 4 * col + i] =
Yaowu Xu7a471702017-09-29 08:38:37 -07004896 (uint8_t)pred[(row * 4 + j) * pred_stride + 4 * col + i];
Yushin Cho8ab875d2017-06-23 14:47:21 -07004897 } else {
4898 for (j = 0; j < 4; j++)
4899 for (i = 0; i < 4; i++)
4900 pred8[(row * 4 + j) * 8 + 4 * col + i] =
4901 dst[(row * 4 + j) * dst_stride + 4 * col + i];
4902 }
4903 }
4904 }
4905#if CONFIG_HIGHBITDEPTH
Yushin Cho04749122017-05-25 14:19:07 -07004906 }
Yushin Cho8ab875d2017-06-23 14:47:21 -07004907#endif // CONFIG_HIGHBITDEPTH
Yushin Choe30a47c2017-08-15 13:08:30 -07004908 dist_8x8 = av1_dist_8x8(cpi, x, src, src_stride, pred8, 8, BLOCK_8X8, 8,
Yushin Chob7b60c52017-07-14 16:18:52 -07004909 8, 8, 8, qindex) *
4910 16;
4911 sum_rd_stats.dist = dist_8x8;
Yushin Cho04749122017-05-25 14:19:07 -07004912 tmp_rd = RDCOST(x->rdmult, sum_rd_stats.rate, sum_rd_stats.dist);
4913 }
Yushin Chob7b60c52017-07-14 16:18:52 -07004914#endif // CONFIG_DIST_8X8
Yaowu Xuc27fc142016-08-22 16:08:15 -07004915 if (this_cost_valid) sum_rd = tmp_rd;
4916 }
4917
4918 if (this_rd < sum_rd) {
4919 int idx, idy;
Yue Chend6bdd462017-07-19 16:05:43 -07004920#if CONFIG_RECT_TX_EXT
4921 TX_SIZE tx_size_selected = is_qttx_picked ? quarter_txsize : tx_size;
4922#else
4923 TX_SIZE tx_size_selected = tx_size;
4924#endif
Jingning Han2f42d772017-07-05 16:28:18 -07004925
Yue Chend6bdd462017-07-19 16:05:43 -07004926#if CONFIG_RECT_TX_EXT
4927 if (is_qttx_picked) {
4928 assert(blk_row == 0 && blk_col == 0 && plane == 0);
Jingning Han2f42d772017-07-05 16:28:18 -07004929#if CONFIG_LV_MAP
Yue Chend6bdd462017-07-19 16:05:43 -07004930 p->txb_entropy_ctx[0] = eobs_qttx[0];
4931 p->txb_entropy_ctx[block_offset_qttx] = eobs_qttx[1];
4932#else
4933 p->eobs[0] = eobs_qttx[0];
4934 p->eobs[block_offset_qttx] = eobs_qttx[1];
4935#endif
4936 } else {
4937#endif
4938#if CONFIG_LV_MAP
4939 p->txb_entropy_ctx[block] = tmp_eob;
Jingning Han2f42d772017-07-05 16:28:18 -07004940#else
4941 p->eobs[block] = tmp_eob;
4942#endif
Yue Chend6bdd462017-07-19 16:05:43 -07004943#if CONFIG_RECT_TX_EXT
4944 }
4945#endif
Jingning Han2f42d772017-07-05 16:28:18 -07004946
Tom Fineganac870492017-08-15 16:19:13 -07004947#if !CONFIG_PVQ
Yue Chend6bdd462017-07-19 16:05:43 -07004948 av1_set_txb_context(x, plane, block, tx_size_selected, pta, ptl);
4949#if CONFIG_RECT_TX_EXT
4950 if (is_qttx_picked)
4951 av1_set_txb_context(x, plane, block_offset_qttx, tx_size_selected,
4952 pta + blk_col_offset, ptl + blk_row_offset);
Tom Fineganac870492017-08-15 16:19:13 -07004953#endif // CONFIG_RECT_TX_EXT
4954#endif // !CONFIG_PVQ
Jingning Han2f42d772017-07-05 16:28:18 -07004955
Jingning Han331662e2017-05-30 17:03:32 -07004956 txfm_partition_update(tx_above + blk_col, tx_left + blk_row, tx_size,
4957 tx_size);
Yue Chend6bdd462017-07-19 16:05:43 -07004958 inter_tx_size[0][0] = tx_size_selected;
Jingning Han58224042016-10-27 16:35:32 -07004959 for (idy = 0; idy < tx_size_high_unit[tx_size] / 2; ++idy)
4960 for (idx = 0; idx < tx_size_wide_unit[tx_size] / 2; ++idx)
Yue Chend6bdd462017-07-19 16:05:43 -07004961 inter_tx_size[idy][idx] = tx_size_selected;
4962 mbmi->tx_size = tx_size_selected;
Jingning Hane3b81bc2017-06-23 11:43:52 -07004963#if CONFIG_TXK_SEL
4964 mbmi->txk_type[txk_idx] = best_tx_type;
4965#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07004966 if (this_rd == INT64_MAX) *is_cost_valid = 0;
Yue Chend6bdd462017-07-19 16:05:43 -07004967#if CONFIG_RECT_TX_EXT
4968 if (is_qttx_picked) {
4969 x->blk_skip[plane][0] = skip_qttx[0];
4970 x->blk_skip[plane][blk_row_offset * bw + blk_col_offset] = skip_qttx[1];
4971 } else {
4972#endif
4973 x->blk_skip[plane][blk_row * bw + blk_col] = rd_stats->skip;
4974#if CONFIG_RECT_TX_EXT
4975 }
4976#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07004977 } else {
Angie Chiangd7246172016-11-03 11:49:15 -07004978 *rd_stats = sum_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004979 if (sum_rd == INT64_MAX) *is_cost_valid = 0;
4980 }
4981}
4982
Angie Chiangb5dda482016-11-02 16:19:58 -07004983static void inter_block_yrd(const AV1_COMP *cpi, MACROBLOCK *x,
4984 RD_STATS *rd_stats, BLOCK_SIZE bsize,
Jingning Han63cbf342016-11-09 15:37:48 -08004985 int64_t ref_best_rd, RD_STATS *rd_stats_stack) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07004986 MACROBLOCKD *const xd = &x->e_mbd;
4987 int is_cost_valid = 1;
4988 int64_t this_rd = 0;
4989
4990 if (ref_best_rd < 0) is_cost_valid = 0;
4991
Angie Chiangc0feea82016-11-03 15:36:18 -07004992 av1_init_rd_stats(rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004993
4994 if (is_cost_valid) {
4995 const struct macroblockd_plane *const pd = &xd->plane[0];
4996 const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
Jingning Han9ca05b72017-01-03 14:41:36 -08004997 const int mi_width = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
4998 const int mi_height = block_size_high[plane_bsize] >> tx_size_high_log2[0];
Jingning Han70e5f3f2016-11-09 17:03:07 -08004999 const TX_SIZE max_tx_size = max_txsize_rect_lookup[plane_bsize];
Jingning Han18482fe2016-11-02 17:01:58 -07005000 const int bh = tx_size_high_unit[max_tx_size];
5001 const int bw = tx_size_wide_unit[max_tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005002 int idx, idy;
5003 int block = 0;
Jingning Han63cbf342016-11-09 15:37:48 -08005004 int block32 = 0;
Jingning Han18482fe2016-11-02 17:01:58 -07005005 int step = tx_size_wide_unit[max_tx_size] * tx_size_high_unit[max_tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005006 ENTROPY_CONTEXT ctxa[2 * MAX_MIB_SIZE];
5007 ENTROPY_CONTEXT ctxl[2 * MAX_MIB_SIZE];
Jingning Han331662e2017-05-30 17:03:32 -07005008 TXFM_CONTEXT tx_above[MAX_MIB_SIZE * 2];
5009 TXFM_CONTEXT tx_left[MAX_MIB_SIZE * 2];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005010
Angie Chiangb5dda482016-11-02 16:19:58 -07005011 RD_STATS pn_rd_stats;
Angie Chiangc0feea82016-11-03 15:36:18 -07005012 av1_init_rd_stats(&pn_rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005013
Jingning Han9ca05b72017-01-03 14:41:36 -08005014 av1_get_entropy_contexts(bsize, 0, pd, ctxa, ctxl);
Jingning Han331662e2017-05-30 17:03:32 -07005015 memcpy(tx_above, xd->above_txfm_context, sizeof(TXFM_CONTEXT) * mi_width);
5016 memcpy(tx_left, xd->left_txfm_context, sizeof(TXFM_CONTEXT) * mi_height);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005017
5018 for (idy = 0; idy < mi_height; idy += bh) {
Jingning Han18482fe2016-11-02 17:01:58 -07005019 for (idx = 0; idx < mi_width; idx += bw) {
Jingning Han63cbf342016-11-09 15:37:48 -08005020 select_tx_block(cpi, x, idy, idx, 0, block, block32, max_tx_size,
Jingning Han18482fe2016-11-02 17:01:58 -07005021 mi_height != mi_width, plane_bsize, ctxa, ctxl,
Angie Chiangb5dda482016-11-02 16:19:58 -07005022 tx_above, tx_left, &pn_rd_stats, ref_best_rd - this_rd,
Jingning Han63cbf342016-11-09 15:37:48 -08005023 &is_cost_valid, rd_stats_stack);
Sarah Parkerde6f0722017-08-07 20:23:46 -07005024 if (pn_rd_stats.rate == INT_MAX) {
5025 av1_invalid_rd_stats(rd_stats);
5026 return;
5027 }
Angie Chiangc0feea82016-11-03 15:36:18 -07005028 av1_merge_rd_stats(rd_stats, &pn_rd_stats);
Urvang Joshi70006e42017-06-14 16:08:55 -07005029 this_rd += AOMMIN(RDCOST(x->rdmult, pn_rd_stats.rate, pn_rd_stats.dist),
5030 RDCOST(x->rdmult, 0, pn_rd_stats.sse));
Yaowu Xuc27fc142016-08-22 16:08:15 -07005031 block += step;
Jingning Han63cbf342016-11-09 15:37:48 -08005032 ++block32;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005033 }
5034 }
5035 }
5036
Urvang Joshi70006e42017-06-14 16:08:55 -07005037 this_rd = AOMMIN(RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist),
5038 RDCOST(x->rdmult, 0, rd_stats->sse));
Yaowu Xuc27fc142016-08-22 16:08:15 -07005039 if (this_rd > ref_best_rd) is_cost_valid = 0;
5040
5041 if (!is_cost_valid) {
5042 // reset cost value
Angie Chiangc0feea82016-11-03 15:36:18 -07005043 av1_invalid_rd_stats(rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005044 }
5045}
5046
Yaowu Xuf883b422016-08-30 14:01:10 -07005047static int64_t select_tx_size_fix_type(const AV1_COMP *cpi, MACROBLOCK *x,
Angie Chiangb5dda482016-11-02 16:19:58 -07005048 RD_STATS *rd_stats, BLOCK_SIZE bsize,
Jingning Han63cbf342016-11-09 15:37:48 -08005049 int64_t ref_best_rd, TX_TYPE tx_type,
5050 RD_STATS *rd_stats_stack) {
Yaowu Xuf883b422016-08-30 14:01:10 -07005051 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005052 MACROBLOCKD *const xd = &x->e_mbd;
5053 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005054 const int is_inter = is_inter_block(mbmi);
Yaowu Xuf883b422016-08-30 14:01:10 -07005055 aom_prob skip_prob = av1_get_skip_prob(cm, xd);
5056 int s0 = av1_cost_bit(skip_prob, 0);
5057 int s1 = av1_cost_bit(skip_prob, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005058 int64_t rd;
Jingning Hane67b38a2016-11-04 10:30:00 -07005059 int row, col;
5060 const int max_blocks_high = max_block_high(xd, bsize, 0);
5061 const int max_blocks_wide = max_block_wide(xd, bsize, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005062
5063 mbmi->tx_type = tx_type;
Jingning Han63cbf342016-11-09 15:37:48 -08005064 inter_block_yrd(cpi, x, rd_stats, bsize, ref_best_rd, rd_stats_stack);
Jingning Han70bd76e2017-05-30 10:53:00 -07005065 mbmi->min_tx_size = get_min_tx_size(mbmi->inter_tx_size[0][0]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005066
Angie Chiangb5dda482016-11-02 16:19:58 -07005067 if (rd_stats->rate == INT_MAX) return INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005068
Jingning Hane67b38a2016-11-04 10:30:00 -07005069 for (row = 0; row < max_blocks_high / 2; ++row)
5070 for (col = 0; col < max_blocks_wide / 2; ++col)
5071 mbmi->min_tx_size = AOMMIN(
5072 mbmi->min_tx_size, get_min_tx_size(mbmi->inter_tx_size[row][col]));
5073
Jingning Han1643a0a2017-07-05 15:48:25 -07005074#if !CONFIG_TXK_SEL
Yaowu Xuc27fc142016-08-22 16:08:15 -07005075#if CONFIG_EXT_TX
Sarah Parkere68a3e42017-02-16 14:03:24 -08005076 if (get_ext_tx_types(mbmi->min_tx_size, bsize, is_inter,
5077 cm->reduced_tx_set_used) > 1 &&
Yaowu Xuc27fc142016-08-22 16:08:15 -07005078 !xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Sarah Parkere68a3e42017-02-16 14:03:24 -08005079 const int ext_tx_set = get_ext_tx_set(mbmi->min_tx_size, bsize, is_inter,
5080 cm->reduced_tx_set_used);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005081 if (is_inter) {
5082 if (ext_tx_set > 0)
Angie Chiangb5dda482016-11-02 16:19:58 -07005083 rd_stats->rate +=
Yue Chenb23d00a2017-07-28 17:01:21 -07005084 x->inter_tx_type_costs[ext_tx_set]
5085 [txsize_sqr_map[mbmi->min_tx_size]]
5086 [mbmi->tx_type];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005087 } else {
5088 if (ext_tx_set > 0 && ALLOW_INTRA_EXT_TX)
Yue Chenb23d00a2017-07-28 17:01:21 -07005089 rd_stats->rate += x->intra_tx_type_costs[ext_tx_set][mbmi->min_tx_size]
5090 [mbmi->mode][mbmi->tx_type];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005091 }
5092 }
Jingning Han1643a0a2017-07-05 15:48:25 -07005093#else
Jingning Hane67b38a2016-11-04 10:30:00 -07005094 if (mbmi->min_tx_size < TX_32X32 && !xd->lossless[xd->mi[0]->mbmi.segment_id])
Zoe Liu4508d882017-07-31 15:36:55 -07005095 rd_stats->rate += x->inter_tx_type_costs[mbmi->min_tx_size][mbmi->tx_type];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005096#endif // CONFIG_EXT_TX
Jingning Han1643a0a2017-07-05 15:48:25 -07005097#endif // CONFIG_TXK_SEL
Yaowu Xuc27fc142016-08-22 16:08:15 -07005098
Angie Chiangb5dda482016-11-02 16:19:58 -07005099 if (rd_stats->skip)
Urvang Joshi70006e42017-06-14 16:08:55 -07005100 rd = RDCOST(x->rdmult, s1, rd_stats->sse);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005101 else
Urvang Joshi70006e42017-06-14 16:08:55 -07005102 rd = RDCOST(x->rdmult, rd_stats->rate + s0, rd_stats->dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005103
Angie Chiangb5dda482016-11-02 16:19:58 -07005104 if (is_inter && !xd->lossless[xd->mi[0]->mbmi.segment_id] &&
5105 !(rd_stats->skip))
Urvang Joshi70006e42017-06-14 16:08:55 -07005106 rd = AOMMIN(rd, RDCOST(x->rdmult, s1, rd_stats->sse));
Yaowu Xuc27fc142016-08-22 16:08:15 -07005107
5108 return rd;
5109}
5110
Hui Su1ddf2312017-08-19 15:21:34 -07005111static uint32_t get_block_residue_hash(MACROBLOCK *x, BLOCK_SIZE bsize) {
5112 const int rows = block_size_high[bsize];
5113 const int cols = block_size_wide[bsize];
5114 const int diff_stride = cols;
5115 const struct macroblock_plane *const p = &x->plane[0];
5116 const int16_t *diff = &p->src_diff[0];
5117 uint8_t hash_data[MAX_SB_SQUARE];
5118 for (int r = 0; r < rows; ++r) {
5119 for (int c = 0; c < cols; ++c) {
5120 hash_data[cols * r + c] = clip_pixel(diff[c] + 128);
5121 }
5122 diff += diff_stride;
5123 }
5124 return (av1_get_crc_value(&x->tx_rd_record.crc_calculator, hash_data,
5125 rows * cols)
5126 << 7) +
5127 bsize;
5128}
5129
5130static void save_tx_rd_info(int n4, uint32_t hash, const MACROBLOCK *const x,
5131 const RD_STATS *const rd_stats,
5132 TX_RD_INFO *const tx_rd_info) {
5133 const MACROBLOCKD *const xd = &x->e_mbd;
5134 const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
5135 tx_rd_info->hash_value = hash;
5136 tx_rd_info->tx_type = mbmi->tx_type;
5137 tx_rd_info->tx_size = mbmi->tx_size;
5138#if CONFIG_VAR_TX
5139 tx_rd_info->min_tx_size = mbmi->min_tx_size;
5140 memcpy(tx_rd_info->blk_skip, x->blk_skip[0],
5141 sizeof(tx_rd_info->blk_skip[0]) * n4);
5142 for (int idy = 0; idy < xd->n8_h; ++idy)
5143 for (int idx = 0; idx < xd->n8_w; ++idx)
5144 tx_rd_info->inter_tx_size[idy][idx] = mbmi->inter_tx_size[idy][idx];
5145#endif // CONFIG_VAR_TX
5146#if CONFIG_TXK_SEL
5147 av1_copy(tx_rd_info->txk_type, mbmi->txk_type);
5148#endif // CONFIG_TXK_SEL
5149 tx_rd_info->rd_stats = *rd_stats;
5150}
5151
5152static void fetch_tx_rd_info(int n4, const TX_RD_INFO *const tx_rd_info,
5153 RD_STATS *const rd_stats, MACROBLOCK *const x) {
5154 MACROBLOCKD *const xd = &x->e_mbd;
5155 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
5156 mbmi->tx_type = tx_rd_info->tx_type;
5157 mbmi->tx_size = tx_rd_info->tx_size;
5158#if CONFIG_VAR_TX
5159 mbmi->min_tx_size = tx_rd_info->min_tx_size;
5160 memcpy(x->blk_skip[0], tx_rd_info->blk_skip,
5161 sizeof(tx_rd_info->blk_skip[0]) * n4);
5162 for (int idy = 0; idy < xd->n8_h; ++idy)
5163 for (int idx = 0; idx < xd->n8_w; ++idx)
5164 mbmi->inter_tx_size[idy][idx] = tx_rd_info->inter_tx_size[idy][idx];
5165#endif // CONFIG_VAR_TX
5166#if CONFIG_TXK_SEL
5167 av1_copy(mbmi->txk_type, tx_rd_info->txk_type);
5168#endif // CONFIG_TXK_SEL
5169 *rd_stats = tx_rd_info->rd_stats;
5170}
5171
Angie Chiangb5dda482016-11-02 16:19:58 -07005172static void select_tx_type_yrd(const AV1_COMP *cpi, MACROBLOCK *x,
5173 RD_STATS *rd_stats, BLOCK_SIZE bsize,
Yaowu Xuc27fc142016-08-22 16:08:15 -07005174 int64_t ref_best_rd) {
Jingning Han2b0eeb12017-02-23 15:55:37 -08005175 const AV1_COMMON *cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005176 const TX_SIZE max_tx_size = max_txsize_lookup[bsize];
5177 MACROBLOCKD *const xd = &x->e_mbd;
5178 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
5179 int64_t rd = INT64_MAX;
5180 int64_t best_rd = INT64_MAX;
5181 TX_TYPE tx_type, best_tx_type = DCT_DCT;
5182 const int is_inter = is_inter_block(mbmi);
5183 TX_SIZE best_tx_size[MAX_MIB_SIZE][MAX_MIB_SIZE];
Debargha Mukherjee28d924b2016-10-05 00:48:28 -07005184 TX_SIZE best_tx = max_txsize_lookup[bsize];
Jingning Hane67b38a2016-11-04 10:30:00 -07005185 TX_SIZE best_min_tx_size = TX_SIZES_ALL;
Jingning Han9ca05b72017-01-03 14:41:36 -08005186 uint8_t best_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE * 8];
Jingning Hane3b81bc2017-06-23 11:43:52 -07005187 TX_TYPE txk_start = DCT_DCT;
5188#if CONFIG_TXK_SEL
5189 TX_TYPE txk_end = DCT_DCT + 1;
5190#else
5191 TX_TYPE txk_end = TX_TYPES;
5192#endif
Angie Chiangf1cb0752017-04-10 16:01:20 -07005193 const int n4 = bsize_to_num_blk(bsize);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005194 int idx, idy;
5195 int prune = 0;
Jingning Han2b0eeb12017-02-23 15:55:37 -08005196 const int count32 =
5197 1 << (2 * (cm->mib_size_log2 - mi_width_log2_lookup[BLOCK_32X32]));
Jingning Han89d648b2016-11-22 11:22:08 -08005198#if CONFIG_EXT_PARTITION
Debargha Mukherjee25550652017-10-04 20:22:28 -07005199 RD_STATS *rd_stats_stack = aom_malloc(16 * sizeof(*rd_stats_stack));
Jingning Han89d648b2016-11-22 11:22:08 -08005200#else
Debargha Mukherjee25550652017-10-04 20:22:28 -07005201 RD_STATS *rd_stats_stack = aom_malloc(4 * sizeof(*rd_stats_stack));
Fergus Simpson4063a682017-02-28 16:52:22 -08005202#endif // CONFIG_EXT_PARTITION
Yaowu Xuc27fc142016-08-22 16:08:15 -07005203#if CONFIG_EXT_TX
Hui Suddbcde22017-09-18 17:22:02 -07005204 const TxSetType tx_set_type = get_ext_tx_set_type(
5205 max_tx_size, bsize, is_inter, cm->reduced_tx_set_used);
Sarah Parkere68a3e42017-02-16 14:03:24 -08005206 const int ext_tx_set =
5207 get_ext_tx_set(max_tx_size, bsize, is_inter, cm->reduced_tx_set_used);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005208#endif // CONFIG_EXT_TX
5209
5210 if (is_inter && cpi->sf.tx_type_search.prune_mode > NO_PRUNE)
5211#if CONFIG_EXT_TX
5212 prune = prune_tx_types(cpi, bsize, x, xd, ext_tx_set);
5213#else
5214 prune = prune_tx_types(cpi, bsize, x, xd, 0);
Fergus Simpson4063a682017-02-28 16:52:22 -08005215#endif // CONFIG_EXT_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07005216
Angie Chiangc0feea82016-11-03 15:36:18 -07005217 av1_invalid_rd_stats(rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005218
Jingning Han89d648b2016-11-22 11:22:08 -08005219 for (idx = 0; idx < count32; ++idx)
5220 av1_invalid_rd_stats(&rd_stats_stack[idx]);
Jingning Han63cbf342016-11-09 15:37:48 -08005221
Hui Su1ddf2312017-08-19 15:21:34 -07005222 const uint32_t hash = get_block_residue_hash(x, bsize);
5223 TX_RD_RECORD *tx_rd_record = &x->tx_rd_record;
5224
5225 if (ref_best_rd != INT64_MAX) {
5226 for (int i = 0; i < tx_rd_record->num; ++i) {
5227 const int index = (tx_rd_record->index_start + i) % RD_RECORD_BUFFER_LEN;
5228 // If there is a match in the tx_rd_record, fetch the RD decision and
5229 // terminate early.
5230 if (tx_rd_record->tx_rd_info[index].hash_value == hash) {
5231 TX_RD_INFO *tx_rd_info = &tx_rd_record->tx_rd_info[index];
5232 fetch_tx_rd_info(n4, tx_rd_info, rd_stats, x);
Debargha Mukherjee25550652017-10-04 20:22:28 -07005233 aom_free(rd_stats_stack);
Hui Su1ddf2312017-08-19 15:21:34 -07005234 return;
5235 }
5236 }
5237 }
5238
Jingning Hane3b81bc2017-06-23 11:43:52 -07005239 for (tx_type = txk_start; tx_type < txk_end; ++tx_type) {
Angie Chiangb5dda482016-11-02 16:19:58 -07005240 RD_STATS this_rd_stats;
Angie Chiangc0feea82016-11-03 15:36:18 -07005241 av1_init_rd_stats(&this_rd_stats);
Sarah Parker53f93db2017-07-11 17:20:04 -07005242#if CONFIG_MRC_TX
5243 // MRC_DCT only implemented for TX_32X32 so only include this tx in
5244 // the search for TX_32X32
Sarah Parker2e08d962017-08-01 19:51:20 -07005245 if (tx_type == MRC_DCT &&
5246 (max_tx_size != TX_32X32 || (is_inter && !USE_MRC_INTER) ||
5247 (!is_inter && !USE_MRC_INTRA)))
5248 continue;
Sarah Parker53f93db2017-07-11 17:20:04 -07005249#endif // CONFIG_MRC_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07005250#if CONFIG_EXT_TX
Hui Suddbcde22017-09-18 17:22:02 -07005251 if (!av1_ext_tx_used[tx_set_type][tx_type]) continue;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005252 if (is_inter) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005253 if (cpi->sf.tx_type_search.prune_mode > NO_PRUNE) {
5254 if (!do_tx_type_search(tx_type, prune)) continue;
5255 }
5256 } else {
5257 if (!ALLOW_INTRA_EXT_TX && bsize >= BLOCK_8X8) {
5258 if (tx_type != intra_mode_to_tx_type_context[mbmi->mode]) continue;
5259 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07005260 }
5261#else // CONFIG_EXT_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07005262 if (is_inter && cpi->sf.tx_type_search.prune_mode > NO_PRUNE &&
5263 !do_tx_type_search(tx_type, prune))
5264 continue;
5265#endif // CONFIG_EXT_TX
5266 if (is_inter && x->use_default_inter_tx_type &&
5267 tx_type != get_default_tx_type(0, xd, 0, max_tx_size))
5268 continue;
5269
Jingning Hane67b38a2016-11-04 10:30:00 -07005270 if (xd->lossless[mbmi->segment_id])
5271 if (tx_type != DCT_DCT) continue;
5272
Angie Chiangb5dda482016-11-02 16:19:58 -07005273 rd = select_tx_size_fix_type(cpi, x, &this_rd_stats, bsize, ref_best_rd,
Jingning Han63cbf342016-11-09 15:37:48 -08005274 tx_type, rd_stats_stack);
Hui Suda816a12017-08-18 14:46:02 -07005275 ref_best_rd = AOMMIN(rd, ref_best_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005276 if (rd < best_rd) {
5277 best_rd = rd;
Angie Chiangb5dda482016-11-02 16:19:58 -07005278 *rd_stats = this_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005279 best_tx_type = mbmi->tx_type;
5280 best_tx = mbmi->tx_size;
Jingning Hane67b38a2016-11-04 10:30:00 -07005281 best_min_tx_size = mbmi->min_tx_size;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005282 memcpy(best_blk_skip, x->blk_skip[0], sizeof(best_blk_skip[0]) * n4);
5283 for (idy = 0; idy < xd->n8_h; ++idy)
5284 for (idx = 0; idx < xd->n8_w; ++idx)
5285 best_tx_size[idy][idx] = mbmi->inter_tx_size[idy][idx];
5286 }
5287 }
5288
5289 mbmi->tx_type = best_tx_type;
5290 for (idy = 0; idy < xd->n8_h; ++idy)
5291 for (idx = 0; idx < xd->n8_w; ++idx)
5292 mbmi->inter_tx_size[idy][idx] = best_tx_size[idy][idx];
5293 mbmi->tx_size = best_tx;
Jingning Hane67b38a2016-11-04 10:30:00 -07005294 mbmi->min_tx_size = best_min_tx_size;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005295 memcpy(x->blk_skip[0], best_blk_skip, sizeof(best_blk_skip[0]) * n4);
Hui Su1ddf2312017-08-19 15:21:34 -07005296
5297 // Save the RD search results into tx_rd_record.
5298 int index;
5299 if (tx_rd_record->num < RD_RECORD_BUFFER_LEN) {
5300 index =
5301 (tx_rd_record->index_start + tx_rd_record->num) % RD_RECORD_BUFFER_LEN;
5302 ++tx_rd_record->num;
5303 } else {
5304 index = tx_rd_record->index_start;
5305 tx_rd_record->index_start =
5306 (tx_rd_record->index_start + 1) % RD_RECORD_BUFFER_LEN;
5307 }
5308 save_tx_rd_info(n4, hash, x, rd_stats, &tx_rd_record->tx_rd_info[index]);
Debargha Mukherjee25550652017-10-04 20:22:28 -07005309 aom_free(rd_stats_stack);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005310}
5311
Yaowu Xuf883b422016-08-30 14:01:10 -07005312static void tx_block_rd(const AV1_COMP *cpi, MACROBLOCK *x, int blk_row,
Yaowu Xuc27fc142016-08-22 16:08:15 -07005313 int blk_col, int plane, int block, TX_SIZE tx_size,
5314 BLOCK_SIZE plane_bsize, ENTROPY_CONTEXT *above_ctx,
Angie Chiangb5dda482016-11-02 16:19:58 -07005315 ENTROPY_CONTEXT *left_ctx, RD_STATS *rd_stats) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005316 MACROBLOCKD *const xd = &x->e_mbd;
5317 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005318 struct macroblockd_plane *const pd = &xd->plane[plane];
5319 BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
5320 const int tx_row = blk_row >> (1 - pd->subsampling_y);
5321 const int tx_col = blk_col >> (1 - pd->subsampling_x);
5322 TX_SIZE plane_tx_size;
Jingning Han18482fe2016-11-02 17:01:58 -07005323 const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
5324 const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005325
Jingning Hand3fada82016-11-22 10:46:55 -08005326 assert(tx_size < TX_SIZES_ALL);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005327
Yaowu Xuc27fc142016-08-22 16:08:15 -07005328 if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
5329
Debargha Mukherjee2f123402016-08-30 17:43:38 -07005330 plane_tx_size =
5331 plane ? uv_txsize_lookup[bsize][mbmi->inter_tx_size[tx_row][tx_col]][0][0]
5332 : mbmi->inter_tx_size[tx_row][tx_col];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005333
5334 if (tx_size == plane_tx_size) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005335 ENTROPY_CONTEXT *ta = above_ctx + blk_col;
5336 ENTROPY_CONTEXT *tl = left_ctx + blk_row;
Yaowu Xuf883b422016-08-30 14:01:10 -07005337 av1_tx_block_rd_b(cpi, x, tx_size, blk_row, blk_col, plane, block,
Angie Chiang77368af2017-03-23 16:22:07 -07005338 plane_bsize, ta, tl, rd_stats);
Tom Fineganac870492017-08-15 16:19:13 -07005339#if !CONFIG_PVQ
Jingning Han328d57b2017-07-07 14:40:17 -07005340 av1_set_txb_context(x, plane, block, tx_size, ta, tl);
Tom Fineganac870492017-08-15 16:19:13 -07005341#endif // !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -07005342 } else {
Jingning Han18482fe2016-11-02 17:01:58 -07005343 const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
5344 const int bsl = tx_size_wide_unit[sub_txs];
Jingning Han58224042016-10-27 16:35:32 -07005345 int step = tx_size_wide_unit[sub_txs] * tx_size_high_unit[sub_txs];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005346 int i;
5347
5348 assert(bsl > 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005349
5350 for (i = 0; i < 4; ++i) {
Jingning Han98d6a1f2016-11-03 12:47:47 -07005351 int offsetr = blk_row + (i >> 1) * bsl;
5352 int offsetc = blk_col + (i & 0x01) * bsl;
5353
5354 if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
5355
5356 tx_block_rd(cpi, x, offsetr, offsetc, plane, block, sub_txs, plane_bsize,
5357 above_ctx, left_ctx, rd_stats);
5358 block += step;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005359 }
5360 }
5361}
5362
5363// Return value 0: early termination triggered, no valid rd cost available;
5364// 1: rd cost values are valid.
Angie Chiangb5dda482016-11-02 16:19:58 -07005365static int inter_block_uvrd(const AV1_COMP *cpi, MACROBLOCK *x,
5366 RD_STATS *rd_stats, BLOCK_SIZE bsize,
5367 int64_t ref_best_rd) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005368 MACROBLOCKD *const xd = &x->e_mbd;
5369 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
5370 int plane;
5371 int is_cost_valid = 1;
5372 int64_t this_rd;
5373
5374 if (ref_best_rd < 0) is_cost_valid = 0;
5375
Angie Chiangc0feea82016-11-03 15:36:18 -07005376 av1_init_rd_stats(rd_stats);
Yue Chena1e48dc2016-08-29 17:29:33 -07005377
Jingning Han31b6a4f2017-02-23 11:05:53 -08005378#if CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
Jingning Han9ce464c2017-02-20 15:36:30 -08005379 if (x->skip_chroma_rd) return is_cost_valid;
Jingning Han52d2b402017-05-19 09:31:17 -07005380 bsize = scale_chroma_bsize(mbmi->sb_type, xd->plane[1].subsampling_x,
5381 xd->plane[1].subsampling_y);
Fergus Simpson4063a682017-02-28 16:52:22 -08005382#endif // CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
Jingning Han9ce464c2017-02-20 15:36:30 -08005383
Yue Chena1e48dc2016-08-29 17:29:33 -07005384#if CONFIG_EXT_TX && CONFIG_RECT_TX
5385 if (is_rect_tx(mbmi->tx_size)) {
Angie Chiang284d7772016-11-08 11:06:45 -08005386 return super_block_uvrd(cpi, x, rd_stats, bsize, ref_best_rd);
Yue Chena1e48dc2016-08-29 17:29:33 -07005387 }
5388#endif // CONFIG_EXT_TX && CONFIG_RECT_TX
5389
Yaowu Xuc27fc142016-08-22 16:08:15 -07005390 if (is_inter_block(mbmi) && is_cost_valid) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005391 for (plane = 1; plane < MAX_MB_PLANE; ++plane)
Yaowu Xuf883b422016-08-30 14:01:10 -07005392 av1_subtract_plane(x, bsize, plane);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005393 }
5394
Yaowu Xuc27fc142016-08-22 16:08:15 -07005395 for (plane = 1; plane < MAX_MB_PLANE; ++plane) {
5396 const struct macroblockd_plane *const pd = &xd->plane[plane];
5397 const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
Jingning Han9ca05b72017-01-03 14:41:36 -08005398 const int mi_width = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
5399 const int mi_height = block_size_high[plane_bsize] >> tx_size_high_log2[0];
Jingning Han70e5f3f2016-11-09 17:03:07 -08005400 const TX_SIZE max_tx_size = max_txsize_rect_lookup[plane_bsize];
Jingning Han18482fe2016-11-02 17:01:58 -07005401 const int bh = tx_size_high_unit[max_tx_size];
5402 const int bw = tx_size_wide_unit[max_tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005403 int idx, idy;
5404 int block = 0;
Jingning Han18482fe2016-11-02 17:01:58 -07005405 const int step = bh * bw;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005406 ENTROPY_CONTEXT ta[2 * MAX_MIB_SIZE];
5407 ENTROPY_CONTEXT tl[2 * MAX_MIB_SIZE];
Angie Chiangb5dda482016-11-02 16:19:58 -07005408 RD_STATS pn_rd_stats;
Angie Chiangc0feea82016-11-03 15:36:18 -07005409 av1_init_rd_stats(&pn_rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005410
Jingning Han9ca05b72017-01-03 14:41:36 -08005411 av1_get_entropy_contexts(bsize, 0, pd, ta, tl);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005412
5413 for (idy = 0; idy < mi_height; idy += bh) {
Jingning Han18482fe2016-11-02 17:01:58 -07005414 for (idx = 0; idx < mi_width; idx += bw) {
5415 tx_block_rd(cpi, x, idy, idx, plane, block, max_tx_size, plane_bsize,
Angie Chiangb5dda482016-11-02 16:19:58 -07005416 ta, tl, &pn_rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005417 block += step;
5418 }
5419 }
5420
Angie Chiangb5dda482016-11-02 16:19:58 -07005421 if (pn_rd_stats.rate == INT_MAX) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005422 is_cost_valid = 0;
5423 break;
5424 }
5425
Angie Chiang628d7c92016-11-03 16:24:56 -07005426 av1_merge_rd_stats(rd_stats, &pn_rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005427
Urvang Joshi70006e42017-06-14 16:08:55 -07005428 this_rd = AOMMIN(RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist),
5429 RDCOST(x->rdmult, 0, rd_stats->sse));
Yaowu Xuc27fc142016-08-22 16:08:15 -07005430
5431 if (this_rd > ref_best_rd) {
5432 is_cost_valid = 0;
5433 break;
5434 }
5435 }
5436
5437 if (!is_cost_valid) {
5438 // reset cost value
Angie Chiangc0feea82016-11-03 15:36:18 -07005439 av1_invalid_rd_stats(rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005440 }
5441
5442 return is_cost_valid;
5443}
5444#endif // CONFIG_VAR_TX
5445
hui su83c26632017-01-24 17:19:06 -08005446static void rd_pick_palette_intra_sbuv(const AV1_COMP *const cpi, MACROBLOCK *x,
5447 int dc_mode_cost,
5448 uint8_t *best_palette_color_map,
5449 MB_MODE_INFO *const best_mbmi,
5450 int64_t *best_rd, int *rate,
5451 int *rate_tokenonly, int64_t *distortion,
5452 int *skippable) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005453 MACROBLOCKD *const xd = &x->e_mbd;
5454 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07005455 assert(!is_inter_block(mbmi));
hui sude0c70a2017-01-09 17:12:17 -08005456 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005457 const BLOCK_SIZE bsize = mbmi->sb_type;
Urvang Joshic9e71d42017-08-09 18:58:33 -07005458 assert(bsize >= BLOCK_8X8);
Angie Chiang284d7772016-11-08 11:06:45 -08005459 int this_rate;
5460 int64_t this_rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005461 int colors_u, colors_v, colors;
5462 const int src_stride = x->plane[1].src.stride;
5463 const uint8_t *const src_u = x->plane[1].src.buf;
5464 const uint8_t *const src_v = x->plane[2].src.buf;
hui sude0c70a2017-01-09 17:12:17 -08005465 uint8_t *const color_map = xd->plane[1].color_index_map;
Angie Chiang284d7772016-11-08 11:06:45 -08005466 RD_STATS tokenonly_rd_stats;
Urvang Joshi56ba91b2017-01-10 13:22:09 -08005467 int plane_block_width, plane_block_height, rows, cols;
5468 av1_get_block_dimensions(bsize, 1, xd, &plane_block_width,
5469 &plane_block_height, &rows, &cols);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005470 if (rows * cols > PALETTE_MAX_BLOCK_SIZE) return;
5471
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04005472 mbmi->uv_mode = UV_DC_PRED;
hui su5db97432016-10-14 16:10:14 -07005473#if CONFIG_FILTER_INTRA
5474 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] = 0;
5475#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07005476
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005477#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005478 if (cpi->common.use_highbitdepth) {
Yaowu Xuf883b422016-08-30 14:01:10 -07005479 colors_u = av1_count_colors_highbd(src_u, src_stride, rows, cols,
5480 cpi->common.bit_depth);
5481 colors_v = av1_count_colors_highbd(src_v, src_stride, rows, cols,
5482 cpi->common.bit_depth);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005483 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005484#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuf883b422016-08-30 14:01:10 -07005485 colors_u = av1_count_colors(src_u, src_stride, rows, cols);
5486 colors_v = av1_count_colors(src_v, src_stride, rows, cols);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005487#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005488 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005489#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005490
hui su33567b22017-04-30 16:40:19 -07005491#if CONFIG_PALETTE_DELTA_ENCODING
hui su33567b22017-04-30 16:40:19 -07005492 uint16_t color_cache[2 * PALETTE_MAX_SIZE];
Hui Su3748bc22017-08-23 11:30:41 -07005493 const int n_cache = av1_get_palette_cache(xd, 1, color_cache);
hui su33567b22017-04-30 16:40:19 -07005494#endif // CONFIG_PALETTE_DELTA_ENCODING
5495
Yaowu Xuc27fc142016-08-22 16:08:15 -07005496 colors = colors_u > colors_v ? colors_u : colors_v;
5497 if (colors > 1 && colors <= 64) {
5498 int r, c, n, i, j;
5499 const int max_itr = 50;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005500 float lb_u, ub_u, val_u;
5501 float lb_v, ub_v, val_v;
5502 float *const data = x->palette_buffer->kmeans_data_buf;
5503 float centroids[2 * PALETTE_MAX_SIZE];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005504
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005505#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005506 uint16_t *src_u16 = CONVERT_TO_SHORTPTR(src_u);
5507 uint16_t *src_v16 = CONVERT_TO_SHORTPTR(src_v);
5508 if (cpi->common.use_highbitdepth) {
5509 lb_u = src_u16[0];
5510 ub_u = src_u16[0];
5511 lb_v = src_v16[0];
5512 ub_v = src_v16[0];
5513 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005514#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005515 lb_u = src_u[0];
5516 ub_u = src_u[0];
5517 lb_v = src_v[0];
5518 ub_v = src_v[0];
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005519#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005520 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005521#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005522
Yaowu Xuc27fc142016-08-22 16:08:15 -07005523 for (r = 0; r < rows; ++r) {
5524 for (c = 0; c < cols; ++c) {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005525#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005526 if (cpi->common.use_highbitdepth) {
5527 val_u = src_u16[r * src_stride + c];
5528 val_v = src_v16[r * src_stride + c];
5529 data[(r * cols + c) * 2] = val_u;
5530 data[(r * cols + c) * 2 + 1] = val_v;
5531 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005532#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005533 val_u = src_u[r * src_stride + c];
5534 val_v = src_v[r * src_stride + c];
5535 data[(r * cols + c) * 2] = val_u;
5536 data[(r * cols + c) * 2 + 1] = val_v;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005537#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005538 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005539#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005540 if (val_u < lb_u)
5541 lb_u = val_u;
5542 else if (val_u > ub_u)
5543 ub_u = val_u;
5544 if (val_v < lb_v)
5545 lb_v = val_v;
5546 else if (val_v > ub_v)
5547 ub_v = val_v;
5548 }
5549 }
5550
5551 for (n = colors > PALETTE_MAX_SIZE ? PALETTE_MAX_SIZE : colors; n >= 2;
5552 --n) {
5553 for (i = 0; i < n; ++i) {
5554 centroids[i * 2] = lb_u + (2 * i + 1) * (ub_u - lb_u) / n / 2;
5555 centroids[i * 2 + 1] = lb_v + (2 * i + 1) * (ub_v - lb_v) / n / 2;
5556 }
Yaowu Xuf883b422016-08-30 14:01:10 -07005557 av1_k_means(data, centroids, color_map, rows * cols, n, 2, max_itr);
hui sud13c24a2017-04-07 16:13:07 -07005558#if CONFIG_PALETTE_DELTA_ENCODING
hui su33567b22017-04-30 16:40:19 -07005559 optimize_palette_colors(color_cache, n_cache, n, 2, centroids);
hui sud13c24a2017-04-07 16:13:07 -07005560 // Sort the U channel colors in ascending order.
5561 for (i = 0; i < 2 * (n - 1); i += 2) {
5562 int min_idx = i;
5563 float min_val = centroids[i];
5564 for (j = i + 2; j < 2 * n; j += 2)
5565 if (centroids[j] < min_val) min_val = centroids[j], min_idx = j;
5566 if (min_idx != i) {
5567 float temp_u = centroids[i], temp_v = centroids[i + 1];
5568 centroids[i] = centroids[min_idx];
5569 centroids[i + 1] = centroids[min_idx + 1];
5570 centroids[min_idx] = temp_u, centroids[min_idx + 1] = temp_v;
5571 }
5572 }
5573 av1_calc_indices(data, centroids, color_map, rows * cols, n, 2);
5574#endif // CONFIG_PALETTE_DELTA_ENCODING
Urvang Joshi56ba91b2017-01-10 13:22:09 -08005575 extend_palette_color_map(color_map, cols, rows, plane_block_width,
5576 plane_block_height);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005577 pmi->palette_size[1] = n;
5578 for (i = 1; i < 3; ++i) {
5579 for (j = 0; j < n; ++j) {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005580#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005581 if (cpi->common.use_highbitdepth)
5582 pmi->palette_colors[i * PALETTE_MAX_SIZE + j] = clip_pixel_highbd(
5583 (int)centroids[j * 2 + i - 1], cpi->common.bit_depth);
5584 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005585#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005586 pmi->palette_colors[i * PALETTE_MAX_SIZE + j] =
5587 clip_pixel((int)centroids[j * 2 + i - 1]);
5588 }
5589 }
5590
Angie Chiang284d7772016-11-08 11:06:45 -08005591 super_block_uvrd(cpi, x, &tokenonly_rd_stats, bsize, *best_rd);
5592 if (tokenonly_rd_stats.rate == INT_MAX) continue;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005593 this_rate =
Angie Chiang284d7772016-11-08 11:06:45 -08005594 tokenonly_rd_stats.rate + dc_mode_cost +
Yue Chenb23d00a2017-07-28 17:01:21 -07005595 x->palette_uv_size_cost[bsize - BLOCK_8X8][n - PALETTE_MIN_SIZE] +
Yaowu Xuc27fc142016-08-22 16:08:15 -07005596 write_uniform_cost(n, color_map[0]) +
Yaowu Xuf883b422016-08-30 14:01:10 -07005597 av1_cost_bit(
5598 av1_default_palette_uv_mode_prob[pmi->palette_size[0] > 0], 1);
hui su33567b22017-04-30 16:40:19 -07005599 this_rate += av1_palette_color_cost_uv(pmi,
5600#if CONFIG_PALETTE_DELTA_ENCODING
5601 color_cache, n_cache,
5602#endif // CONFIG_PALETTE_DELTA_ENCODING
5603 cpi->common.bit_depth);
Sarah Parker99e7daa2017-08-29 10:30:13 -07005604 this_rate +=
5605 av1_cost_color_map(x, 1, 0, bsize, mbmi->tx_size, PALETTE_MAP);
Urvang Joshi70006e42017-06-14 16:08:55 -07005606 this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005607 if (this_rd < *best_rd) {
5608 *best_rd = this_rd;
hui su83c26632017-01-24 17:19:06 -08005609 *best_mbmi = *mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005610 memcpy(best_palette_color_map, color_map,
Urvang Joshi56ba91b2017-01-10 13:22:09 -08005611 plane_block_width * plane_block_height *
5612 sizeof(best_palette_color_map[0]));
Yaowu Xuc27fc142016-08-22 16:08:15 -07005613 *rate = this_rate;
Angie Chiang284d7772016-11-08 11:06:45 -08005614 *distortion = tokenonly_rd_stats.dist;
5615 *rate_tokenonly = tokenonly_rd_stats.rate;
5616 *skippable = tokenonly_rd_stats.skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005617 }
5618 }
5619 }
hui su83c26632017-01-24 17:19:06 -08005620 if (best_mbmi->palette_mode_info.palette_size[1] > 0) {
hui sude0c70a2017-01-09 17:12:17 -08005621 memcpy(color_map, best_palette_color_map,
Luc Trudeau0401e892017-08-31 00:37:11 -04005622 plane_block_width * plane_block_height *
5623 sizeof(best_palette_color_map[0]));
hui sude0c70a2017-01-09 17:12:17 -08005624 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07005625}
5626
hui su5db97432016-10-14 16:10:14 -07005627#if CONFIG_FILTER_INTRA
5628// Return 1 if an filter intra mode is selected; return 0 otherwise.
5629static int rd_pick_filter_intra_sbuv(const AV1_COMP *const cpi, MACROBLOCK *x,
5630 int *rate, int *rate_tokenonly,
5631 int64_t *distortion, int *skippable,
5632 BLOCK_SIZE bsize, int64_t *best_rd) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005633 MACROBLOCKD *const xd = &x->e_mbd;
5634 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
hui su5db97432016-10-14 16:10:14 -07005635 int filter_intra_selected_flag = 0;
Angie Chiang284d7772016-11-08 11:06:45 -08005636 int this_rate;
5637 int64_t this_rd;
hui su5db97432016-10-14 16:10:14 -07005638 FILTER_INTRA_MODE mode;
5639 FILTER_INTRA_MODE_INFO filter_intra_mode_info;
Angie Chiang284d7772016-11-08 11:06:45 -08005640 RD_STATS tokenonly_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005641
hui su5db97432016-10-14 16:10:14 -07005642 av1_zero(filter_intra_mode_info);
5643 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] = 1;
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04005644 mbmi->uv_mode = UV_DC_PRED;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005645 mbmi->palette_mode_info.palette_size[1] = 0;
5646
5647 for (mode = 0; mode < FILTER_INTRA_MODES; ++mode) {
hui su5db97432016-10-14 16:10:14 -07005648 mbmi->filter_intra_mode_info.filter_intra_mode[1] = mode;
Angie Chiang284d7772016-11-08 11:06:45 -08005649 if (!super_block_uvrd(cpi, x, &tokenonly_rd_stats, bsize, *best_rd))
Yaowu Xuc27fc142016-08-22 16:08:15 -07005650 continue;
5651
Angie Chiang284d7772016-11-08 11:06:45 -08005652 this_rate = tokenonly_rd_stats.rate +
hui su5db97432016-10-14 16:10:14 -07005653 av1_cost_bit(cpi->common.fc->filter_intra_probs[1], 1) +
Yue Chenb23d00a2017-07-28 17:01:21 -07005654 x->intra_uv_mode_cost[mbmi->mode][mbmi->uv_mode] +
Yaowu Xuc27fc142016-08-22 16:08:15 -07005655 write_uniform_cost(FILTER_INTRA_MODES, mode);
Urvang Joshi70006e42017-06-14 16:08:55 -07005656 this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005657 if (this_rd < *best_rd) {
5658 *best_rd = this_rd;
5659 *rate = this_rate;
Angie Chiang284d7772016-11-08 11:06:45 -08005660 *rate_tokenonly = tokenonly_rd_stats.rate;
5661 *distortion = tokenonly_rd_stats.dist;
5662 *skippable = tokenonly_rd_stats.skip;
hui su5db97432016-10-14 16:10:14 -07005663 filter_intra_mode_info = mbmi->filter_intra_mode_info;
5664 filter_intra_selected_flag = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005665 }
5666 }
5667
hui su5db97432016-10-14 16:10:14 -07005668 if (filter_intra_selected_flag) {
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04005669 mbmi->uv_mode = UV_DC_PRED;
hui su5db97432016-10-14 16:10:14 -07005670 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] =
5671 filter_intra_mode_info.use_filter_intra_mode[1];
5672 mbmi->filter_intra_mode_info.filter_intra_mode[1] =
5673 filter_intra_mode_info.filter_intra_mode[1];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005674 return 1;
5675 } else {
5676 return 0;
5677 }
5678}
hui su5db97432016-10-14 16:10:14 -07005679#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07005680
hui su5db97432016-10-14 16:10:14 -07005681#if CONFIG_EXT_INTRA
hui su45dc5972016-12-08 17:42:50 -08005682// Run RD calculation with given chroma intra prediction angle., and return
5683// the RD cost. Update the best mode info. if the RD cost is the best so far.
5684static int64_t pick_intra_angle_routine_sbuv(
5685 const AV1_COMP *const cpi, MACROBLOCK *x, BLOCK_SIZE bsize,
5686 int rate_overhead, int64_t best_rd_in, int *rate, RD_STATS *rd_stats,
5687 int *best_angle_delta, int64_t *best_rd) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005688 MB_MODE_INFO *mbmi = &x->e_mbd.mi[0]->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07005689 assert(!is_inter_block(mbmi));
Angie Chiang284d7772016-11-08 11:06:45 -08005690 int this_rate;
5691 int64_t this_rd;
5692 RD_STATS tokenonly_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005693
hui su45dc5972016-12-08 17:42:50 -08005694 if (!super_block_uvrd(cpi, x, &tokenonly_rd_stats, bsize, best_rd_in))
5695 return INT64_MAX;
Angie Chiang284d7772016-11-08 11:06:45 -08005696 this_rate = tokenonly_rd_stats.rate + rate_overhead;
Urvang Joshi70006e42017-06-14 16:08:55 -07005697 this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005698 if (this_rd < *best_rd) {
5699 *best_rd = this_rd;
5700 *best_angle_delta = mbmi->angle_delta[1];
5701 *rate = this_rate;
hui su45dc5972016-12-08 17:42:50 -08005702 rd_stats->rate = tokenonly_rd_stats.rate;
5703 rd_stats->dist = tokenonly_rd_stats.dist;
5704 rd_stats->skip = tokenonly_rd_stats.skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005705 }
hui su45dc5972016-12-08 17:42:50 -08005706 return this_rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005707}
5708
hui su45dc5972016-12-08 17:42:50 -08005709// With given chroma directional intra prediction mode, pick the best angle
5710// delta. Return true if a RD cost that is smaller than the input one is found.
Urvang Joshi52648442016-10-13 17:27:51 -07005711static int rd_pick_intra_angle_sbuv(const AV1_COMP *const cpi, MACROBLOCK *x,
Urvang Joshi52648442016-10-13 17:27:51 -07005712 BLOCK_SIZE bsize, int rate_overhead,
hui su45dc5972016-12-08 17:42:50 -08005713 int64_t best_rd, int *rate,
5714 RD_STATS *rd_stats) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005715 MACROBLOCKD *const xd = &x->e_mbd;
5716 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07005717 assert(!is_inter_block(mbmi));
hui su45dc5972016-12-08 17:42:50 -08005718 int i, angle_delta, best_angle_delta = 0;
hui su0a6731f2017-04-26 15:23:47 -07005719 int64_t this_rd, best_rd_in, rd_cost[2 * (MAX_ANGLE_DELTA + 2)];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005720
hui su45dc5972016-12-08 17:42:50 -08005721 rd_stats->rate = INT_MAX;
5722 rd_stats->skip = 0;
5723 rd_stats->dist = INT64_MAX;
hui su0a6731f2017-04-26 15:23:47 -07005724 for (i = 0; i < 2 * (MAX_ANGLE_DELTA + 2); ++i) rd_cost[i] = INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005725
hui su0a6731f2017-04-26 15:23:47 -07005726 for (angle_delta = 0; angle_delta <= MAX_ANGLE_DELTA; angle_delta += 2) {
hui su45dc5972016-12-08 17:42:50 -08005727 for (i = 0; i < 2; ++i) {
5728 best_rd_in = (best_rd == INT64_MAX)
5729 ? INT64_MAX
5730 : (best_rd + (best_rd >> ((angle_delta == 0) ? 3 : 5)));
5731 mbmi->angle_delta[1] = (1 - 2 * i) * angle_delta;
5732 this_rd = pick_intra_angle_routine_sbuv(cpi, x, bsize, rate_overhead,
5733 best_rd_in, rate, rd_stats,
5734 &best_angle_delta, &best_rd);
5735 rd_cost[2 * angle_delta + i] = this_rd;
5736 if (angle_delta == 0) {
5737 if (this_rd == INT64_MAX) return 0;
5738 rd_cost[1] = this_rd;
5739 break;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005740 }
5741 }
hui su45dc5972016-12-08 17:42:50 -08005742 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07005743
hui su45dc5972016-12-08 17:42:50 -08005744 assert(best_rd != INT64_MAX);
hui su0a6731f2017-04-26 15:23:47 -07005745 for (angle_delta = 1; angle_delta <= MAX_ANGLE_DELTA; angle_delta += 2) {
hui su45dc5972016-12-08 17:42:50 -08005746 int64_t rd_thresh;
5747 for (i = 0; i < 2; ++i) {
5748 int skip_search = 0;
5749 rd_thresh = best_rd + (best_rd >> 5);
5750 if (rd_cost[2 * (angle_delta + 1) + i] > rd_thresh &&
5751 rd_cost[2 * (angle_delta - 1) + i] > rd_thresh)
5752 skip_search = 1;
5753 if (!skip_search) {
5754 mbmi->angle_delta[1] = (1 - 2 * i) * angle_delta;
Yue Chenb0f808b2017-04-26 11:55:14 -07005755 pick_intra_angle_routine_sbuv(cpi, x, bsize, rate_overhead, best_rd,
5756 rate, rd_stats, &best_angle_delta,
5757 &best_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005758 }
5759 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07005760 }
5761
5762 mbmi->angle_delta[1] = best_angle_delta;
hui su45dc5972016-12-08 17:42:50 -08005763 return rd_stats->rate != INT_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005764}
5765#endif // CONFIG_EXT_INTRA
5766
David Michael Barr2510f642017-07-11 23:39:20 +09005767#if CONFIG_CFL
Luc Trudeau60669132017-09-28 16:49:49 -04005768// TODO(ltrudeau) add support for HBD.
Luc Trudeau4e26d662017-09-11 13:08:40 -04005769static int64_t cfl_alpha_dist(const int16_t *pred_buf_q3, const uint8_t *src,
Luc Trudeau593d02c2017-09-08 11:29:37 -04005770 int src_stride, int width, int height,
5771 int dc_pred, int alpha_q3,
5772 int64_t *dist_neg_out) {
Luc Trudeau4c5df102017-07-08 14:43:27 -04005773 int64_t dist = 0;
David Michael Barr2510f642017-07-11 23:39:20 +09005774 int diff;
5775
5776 if (alpha_q3 == 0) {
5777 for (int j = 0; j < height; j++) {
5778 for (int i = 0; i < width; i++) {
5779 diff = src[i] - dc_pred;
5780 dist += diff * diff;
5781 }
5782 src += src_stride;
5783 }
5784
5785 if (dist_neg_out) *dist_neg_out = dist;
5786
5787 return dist;
5788 }
5789
Luc Trudeau4c5df102017-07-08 14:43:27 -04005790 int64_t dist_neg = 0;
Luc Trudeau593d02c2017-09-08 11:29:37 -04005791 for (int j = 0; j < height; j++) {
5792 for (int i = 0; i < width; i++) {
5793 const int uv = src[i];
Luc Trudeau4e26d662017-09-11 13:08:40 -04005794 const int scaled_luma = get_scaled_luma_q0(alpha_q3, pred_buf_q3[i]);
David Michael Barr2510f642017-07-11 23:39:20 +09005795
Luc Trudeau60669132017-09-28 16:49:49 -04005796 diff = uv - clip_pixel(scaled_luma + dc_pred);
Luc Trudeau593d02c2017-09-08 11:29:37 -04005797 dist += diff * diff;
David Michael Barr2510f642017-07-11 23:39:20 +09005798
Luc Trudeau60669132017-09-28 16:49:49 -04005799 diff = uv - clip_pixel(-scaled_luma + dc_pred);
Luc Trudeau593d02c2017-09-08 11:29:37 -04005800 dist_neg += diff * diff;
David Michael Barr2510f642017-07-11 23:39:20 +09005801 }
Luc Trudeau4e26d662017-09-11 13:08:40 -04005802 pred_buf_q3 += MAX_SB_SIZE;
Luc Trudeau593d02c2017-09-08 11:29:37 -04005803 src += src_stride;
David Michael Barr2510f642017-07-11 23:39:20 +09005804 }
5805
5806 if (dist_neg_out) *dist_neg_out = dist_neg;
5807
5808 return dist;
5809}
5810
David Michael Barr2510f642017-07-11 23:39:20 +09005811static int cfl_rd_pick_alpha(MACROBLOCK *const x, TX_SIZE tx_size) {
5812 const struct macroblock_plane *const p_u = &x->plane[AOM_PLANE_U];
5813 const struct macroblock_plane *const p_v = &x->plane[AOM_PLANE_V];
5814 const uint8_t *const src_u = p_u->src.buf;
5815 const uint8_t *const src_v = p_v->src.buf;
5816 const int src_stride_u = p_u->src.stride;
5817 const int src_stride_v = p_v->src.stride;
5818
5819 MACROBLOCKD *const xd = &x->e_mbd;
David Michael Barr2510f642017-07-11 23:39:20 +09005820 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
5821
5822 CFL_CTX *const cfl = xd->cfl;
5823 cfl_compute_parameters(xd, tx_size);
5824 const int width = cfl->uv_width;
5825 const int height = cfl->uv_height;
5826 const int dc_pred_u = cfl->dc_pred[CFL_PRED_U];
5827 const int dc_pred_v = cfl->dc_pred[CFL_PRED_V];
Luc Trudeau4e26d662017-09-11 13:08:40 -04005828 const int16_t *pred_buf_q3 = cfl->pred_buf_q3;
David Michael Barr2510f642017-07-11 23:39:20 +09005829
Luc Trudeau4c5df102017-07-08 14:43:27 -04005830 int64_t sse[CFL_PRED_PLANES][CFL_MAGS_SIZE];
Luc Trudeau4e26d662017-09-11 13:08:40 -04005831 sse[CFL_PRED_U][0] = cfl_alpha_dist(pred_buf_q3, src_u, src_stride_u, width,
Luc Trudeau593d02c2017-09-08 11:29:37 -04005832 height, dc_pred_u, 0, NULL);
Luc Trudeau4e26d662017-09-11 13:08:40 -04005833 sse[CFL_PRED_V][0] = cfl_alpha_dist(pred_buf_q3, src_v, src_stride_v, width,
Luc Trudeau593d02c2017-09-08 11:29:37 -04005834 height, dc_pred_v, 0, NULL);
David Michael Barr2510f642017-07-11 23:39:20 +09005835
David Michael Barrf6eaa152017-07-19 19:42:28 +09005836 for (int c = 0; c < CFL_ALPHABET_SIZE; c++) {
5837 const int m = c * 2 + 1;
5838 const int abs_alpha_q3 = c + 1;
Luc Trudeau593d02c2017-09-08 11:29:37 -04005839 sse[CFL_PRED_U][m] =
Luc Trudeau4e26d662017-09-11 13:08:40 -04005840 cfl_alpha_dist(pred_buf_q3, src_u, src_stride_u, width, height,
5841 dc_pred_u, abs_alpha_q3, &sse[CFL_PRED_U][m + 1]);
Luc Trudeau593d02c2017-09-08 11:29:37 -04005842 sse[CFL_PRED_V][m] =
Luc Trudeau4e26d662017-09-11 13:08:40 -04005843 cfl_alpha_dist(pred_buf_q3, src_v, src_stride_v, width, height,
5844 dc_pred_v, abs_alpha_q3, &sse[CFL_PRED_V][m + 1]);
David Michael Barr2510f642017-07-11 23:39:20 +09005845 }
5846
Luc Trudeau4c5df102017-07-08 14:43:27 -04005847 int64_t dist;
David Michael Barr2510f642017-07-11 23:39:20 +09005848 int64_t cost;
David Michael Barrf6eaa152017-07-19 19:42:28 +09005849 int64_t best_cost = INT64_MAX;
5850 int best_rate = 0;
David Michael Barr2510f642017-07-11 23:39:20 +09005851
5852 // Compute least squares parameter of the entire block
David Michael Barr2510f642017-07-11 23:39:20 +09005853 int ind = 0;
David Michael Barrf6eaa152017-07-19 19:42:28 +09005854 int signs = 0;
David Michael Barr2510f642017-07-11 23:39:20 +09005855
David Michael Barrf6eaa152017-07-19 19:42:28 +09005856 for (int joint_sign = 0; joint_sign < CFL_JOINT_SIGNS; joint_sign++) {
5857 const int sign_u = CFL_SIGN_U(joint_sign);
5858 const int sign_v = CFL_SIGN_V(joint_sign);
5859 const int size_u = (sign_u == CFL_SIGN_ZERO) ? 1 : CFL_ALPHABET_SIZE;
5860 const int size_v = (sign_v == CFL_SIGN_ZERO) ? 1 : CFL_ALPHABET_SIZE;
5861 for (int u = 0; u < size_u; u++) {
5862 const int idx_u = (sign_u == CFL_SIGN_ZERO) ? 0 : u * 2 + 1;
5863 for (int v = 0; v < size_v; v++) {
5864 const int idx_v = (sign_v == CFL_SIGN_ZERO) ? 0 : v * 2 + 1;
David Michael Barr2510f642017-07-11 23:39:20 +09005865 dist = sse[CFL_PRED_U][idx_u + (sign_u == CFL_SIGN_NEG)] +
5866 sse[CFL_PRED_V][idx_v + (sign_v == CFL_SIGN_NEG)];
5867 dist *= 16;
David Michael Barr38e560c2017-08-16 21:46:37 +09005868 const int rate = x->cfl_cost[joint_sign][CFL_PRED_U][u] +
5869 x->cfl_cost[joint_sign][CFL_PRED_V][v];
David Michael Barrf6eaa152017-07-19 19:42:28 +09005870 cost = RDCOST(x->rdmult, rate, dist);
David Michael Barr2510f642017-07-11 23:39:20 +09005871 if (cost < best_cost) {
5872 best_cost = cost;
David Michael Barrf6eaa152017-07-19 19:42:28 +09005873 best_rate = rate;
5874 ind = (u << CFL_ALPHABET_SIZE_LOG2) + v;
5875 signs = joint_sign;
David Michael Barr2510f642017-07-11 23:39:20 +09005876 }
5877 }
5878 }
5879 }
5880
5881 mbmi->cfl_alpha_idx = ind;
David Michael Barrf6eaa152017-07-19 19:42:28 +09005882 mbmi->cfl_alpha_signs = signs;
5883 return best_rate;
David Michael Barr2510f642017-07-11 23:39:20 +09005884}
5885#endif // CONFIG_CFL
5886
hui sueaddeee2017-05-30 12:19:38 -07005887static void init_sbuv_mode(MB_MODE_INFO *const mbmi) {
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04005888 mbmi->uv_mode = UV_DC_PRED;
hui sueaddeee2017-05-30 12:19:38 -07005889 mbmi->palette_mode_info.palette_size[1] = 0;
hui sueaddeee2017-05-30 12:19:38 -07005890#if CONFIG_FILTER_INTRA
5891 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] = 0;
5892#endif // CONFIG_FILTER_INTRA
5893}
5894
Urvang Joshi52648442016-10-13 17:27:51 -07005895static int64_t rd_pick_intra_sbuv_mode(const AV1_COMP *const cpi, MACROBLOCK *x,
5896 int *rate, int *rate_tokenonly,
5897 int64_t *distortion, int *skippable,
5898 BLOCK_SIZE bsize, TX_SIZE max_tx_size) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005899 MACROBLOCKD *xd = &x->e_mbd;
5900 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07005901 assert(!is_inter_block(mbmi));
hui su83c26632017-01-24 17:19:06 -08005902 MB_MODE_INFO best_mbmi = *mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005903 int64_t best_rd = INT64_MAX, this_rd;
Yushin Cho77bba8d2016-11-04 16:36:56 -07005904#if CONFIG_PVQ
5905 od_rollback_buffer buf;
Yushin Cho77bba8d2016-11-04 16:36:56 -07005906 od_encode_checkpoint(&x->daala_enc, &buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08005907#endif // CONFIG_PVQ
hui sude0c70a2017-01-09 17:12:17 -08005908 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
Urvang Joshic9e71d42017-08-09 18:58:33 -07005909 const int try_palette = can_use_palette(cpi, mbmi);
hui su5db97432016-10-14 16:10:14 -07005910
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04005911 for (int mode_idx = 0; mode_idx < UV_INTRA_MODES; ++mode_idx) {
hui su8a516a82017-07-06 10:00:36 -07005912 int this_rate;
5913 RD_STATS tokenonly_rd_stats;
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04005914 UV_PREDICTION_MODE mode = uv_rd_search_mode_order[mode_idx];
hui su83c26632017-01-24 17:19:06 -08005915#if CONFIG_EXT_INTRA
5916 const int is_directional_mode =
Luc Trudeau6e1cd782017-06-21 13:52:36 -04005917 av1_is_directional_mode(get_uv_mode(mode), mbmi->sb_type);
hui su83c26632017-01-24 17:19:06 -08005918#endif // CONFIG_EXT_INTRA
Urvang Joshifeb925f2016-12-05 10:37:29 -08005919 if (!(cpi->sf.intra_uv_mode_mask[txsize_sqr_up_map[max_tx_size]] &
5920 (1 << mode)))
5921 continue;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005922
5923 mbmi->uv_mode = mode;
David Michael Barr2510f642017-07-11 23:39:20 +09005924#if CONFIG_CFL
5925 int cfl_alpha_rate = 0;
Luc Trudeau6e1cd782017-06-21 13:52:36 -04005926 if (mode == UV_CFL_PRED) {
5927 assert(!is_directional_mode);
Luc Trudeaub05eeae2017-08-18 15:14:30 -04005928 const TX_SIZE uv_tx_size = av1_get_uv_tx_size(mbmi, &xd->plane[1]);
5929 cfl_alpha_rate = cfl_rd_pick_alpha(x, uv_tx_size);
David Michael Barr2510f642017-07-11 23:39:20 +09005930 }
5931#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07005932#if CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07005933 mbmi->angle_delta[1] = 0;
Joe Young830d4ce2017-05-30 17:48:13 -07005934 if (is_directional_mode && av1_use_angle_delta(mbmi->sb_type)) {
Yue Chenb23d00a2017-07-28 17:01:21 -07005935 const int rate_overhead = x->intra_uv_mode_cost[mbmi->mode][mode] +
hui su0a6731f2017-04-26 15:23:47 -07005936 write_uniform_cost(2 * MAX_ANGLE_DELTA + 1, 0);
hui su45dc5972016-12-08 17:42:50 -08005937 if (!rd_pick_intra_angle_sbuv(cpi, x, bsize, rate_overhead, best_rd,
5938 &this_rate, &tokenonly_rd_stats))
Yaowu Xuc27fc142016-08-22 16:08:15 -07005939 continue;
5940 } else {
hui su83c26632017-01-24 17:19:06 -08005941#endif // CONFIG_EXT_INTRA
Angie Chiang284d7772016-11-08 11:06:45 -08005942 if (!super_block_uvrd(cpi, x, &tokenonly_rd_stats, bsize, best_rd)) {
Yushin Cho77bba8d2016-11-04 16:36:56 -07005943#if CONFIG_PVQ
5944 od_encode_rollback(&x->daala_enc, &buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08005945#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -07005946 continue;
Yushin Cho77bba8d2016-11-04 16:36:56 -07005947 }
hui su83c26632017-01-24 17:19:06 -08005948#if CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07005949 }
hui su83c26632017-01-24 17:19:06 -08005950#endif // CONFIG_EXT_INTRA
Angie Chiang284d7772016-11-08 11:06:45 -08005951 this_rate =
Yue Chenb23d00a2017-07-28 17:01:21 -07005952 tokenonly_rd_stats.rate + x->intra_uv_mode_cost[mbmi->mode][mode];
hui su83c26632017-01-24 17:19:06 -08005953
Luc Trudeaudff41922017-07-07 09:47:58 -04005954#if CONFIG_CFL
Luc Trudeau6e1cd782017-06-21 13:52:36 -04005955 if (mode == UV_CFL_PRED) {
David Michael Barr2510f642017-07-11 23:39:20 +09005956 this_rate += cfl_alpha_rate;
Luc Trudeaudff41922017-07-07 09:47:58 -04005957 }
5958#endif
hui su83c26632017-01-24 17:19:06 -08005959#if CONFIG_EXT_INTRA
Joe Young830d4ce2017-05-30 17:48:13 -07005960 if (is_directional_mode && av1_use_angle_delta(mbmi->sb_type)) {
hui su0a6731f2017-04-26 15:23:47 -07005961 this_rate += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
5962 MAX_ANGLE_DELTA + mbmi->angle_delta[1]);
hui su45dc5972016-12-08 17:42:50 -08005963 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07005964#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -07005965#if CONFIG_FILTER_INTRA
Luc Trudeau91357ee2017-09-27 13:40:37 -04005966 if (mbmi->sb_type >= BLOCK_8X8 && mode == UV_DC_PRED)
hui su5db97432016-10-14 16:10:14 -07005967 this_rate += av1_cost_bit(cpi->common.fc->filter_intra_probs[1], 0);
5968#endif // CONFIG_FILTER_INTRA
Rupert Swarbrick6f9cd942017-08-02 15:57:18 +01005969 if (try_palette && mode == UV_DC_PRED)
Yaowu Xuf883b422016-08-30 14:01:10 -07005970 this_rate += av1_cost_bit(
5971 av1_default_palette_uv_mode_prob[pmi->palette_size[0] > 0], 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005972
Yushin Cho77bba8d2016-11-04 16:36:56 -07005973#if CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -07005974 od_encode_rollback(&x->daala_enc, &buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08005975#endif // CONFIG_PVQ
Urvang Joshi70006e42017-06-14 16:08:55 -07005976 this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005977
5978 if (this_rd < best_rd) {
hui su83c26632017-01-24 17:19:06 -08005979 best_mbmi = *mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005980 best_rd = this_rd;
5981 *rate = this_rate;
Angie Chiang284d7772016-11-08 11:06:45 -08005982 *rate_tokenonly = tokenonly_rd_stats.rate;
5983 *distortion = tokenonly_rd_stats.dist;
5984 *skippable = tokenonly_rd_stats.skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005985 }
5986 }
5987
Rupert Swarbrick6f9cd942017-08-02 15:57:18 +01005988 if (try_palette) {
hui su8a516a82017-07-06 10:00:36 -07005989 uint8_t *best_palette_color_map = x->palette_buffer->best_palette_color_map;
hui su83c26632017-01-24 17:19:06 -08005990 rd_pick_palette_intra_sbuv(cpi, x,
Yue Chenb23d00a2017-07-28 17:01:21 -07005991 x->intra_uv_mode_cost[mbmi->mode][UV_DC_PRED],
hui su83c26632017-01-24 17:19:06 -08005992 best_palette_color_map, &best_mbmi, &best_rd,
5993 rate, rate_tokenonly, distortion, skippable);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005994 }
5995
hui su5db97432016-10-14 16:10:14 -07005996#if CONFIG_FILTER_INTRA
5997 if (mbmi->sb_type >= BLOCK_8X8) {
5998 if (rd_pick_filter_intra_sbuv(cpi, x, rate, rate_tokenonly, distortion,
hui su83c26632017-01-24 17:19:06 -08005999 skippable, bsize, &best_rd))
6000 best_mbmi = *mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006001 }
hui su5db97432016-10-14 16:10:14 -07006002#endif // CONFIG_FILTER_INTRA
6003
hui su83c26632017-01-24 17:19:06 -08006004 *mbmi = best_mbmi;
Urvang Joshifeb925f2016-12-05 10:37:29 -08006005 // Make sure we actually chose a mode
6006 assert(best_rd < INT64_MAX);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006007 return best_rd;
6008}
6009
Urvang Joshi52648442016-10-13 17:27:51 -07006010static void choose_intra_uv_mode(const AV1_COMP *const cpi, MACROBLOCK *const x,
Luc Trudeau9d4cbb82017-07-27 17:01:32 -04006011 BLOCK_SIZE bsize, TX_SIZE max_tx_size,
6012 int *rate_uv, int *rate_uv_tokenonly,
6013 int64_t *dist_uv, int *skip_uv,
6014 UV_PREDICTION_MODE *mode_uv) {
Luc Trudeaub05eeae2017-08-18 15:14:30 -04006015 MACROBLOCKD *xd = &x->e_mbd;
6016 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006017 // Use an estimated rd for uv_intra based on DC_PRED if the
6018 // appropriate speed flag is set.
Luc Trudeaub05eeae2017-08-18 15:14:30 -04006019 init_sbuv_mode(mbmi);
Jingning Han271bb2c2016-12-14 12:34:46 -08006020#if CONFIG_CB4X4
Luc Trudeau9d4cbb82017-07-27 17:01:32 -04006021#if !CONFIG_CHROMA_2X2
Jingning Han9ce464c2017-02-20 15:36:30 -08006022 if (x->skip_chroma_rd) {
6023 *rate_uv = 0;
6024 *rate_uv_tokenonly = 0;
6025 *dist_uv = 0;
6026 *skip_uv = 1;
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04006027 *mode_uv = UV_DC_PRED;
Jingning Han9ce464c2017-02-20 15:36:30 -08006028 return;
6029 }
Luc Trudeaub05eeae2017-08-18 15:14:30 -04006030 bsize = scale_chroma_bsize(bsize, xd->plane[AOM_PLANE_U].subsampling_x,
6031 xd->plane[AOM_PLANE_U].subsampling_y);
Luc Trudeau9d4cbb82017-07-27 17:01:32 -04006032#endif // !CONFIG_CHROMA_2X2
Luc Trudeaub05eeae2017-08-18 15:14:30 -04006033#if CONFIG_CFL
6034 // Only store reconstructed luma when there's chroma RDO. When there's no
6035 // chroma RDO, the reconstructed luma will be stored in encode_superblock().
6036 xd->cfl->store_y = !x->skip_chroma_rd;
6037#endif // CONFIG_CFL
Jingning Han31b6a4f2017-02-23 11:05:53 -08006038#else
Luc Trudeau9d4cbb82017-07-27 17:01:32 -04006039 bsize = bsize < BLOCK_8X8 ? BLOCK_8X8 : bsize;
Luc Trudeaub05eeae2017-08-18 15:14:30 -04006040#if CONFIG_CFL
6041 xd->cfl->store_y = 1;
6042#endif // CONFIG_CFL
Jingning Han31b6a4f2017-02-23 11:05:53 -08006043#endif // CONFIG_CB4X4
Luc Trudeaub05eeae2017-08-18 15:14:30 -04006044#if CONFIG_CFL
6045 if (xd->cfl->store_y) {
6046 // Perform one extra call to txfm_rd_in_plane(), with the values chosen
6047 // during luma RDO, so we can store reconstructed luma values
6048 RD_STATS this_rd_stats;
6049 txfm_rd_in_plane(x, cpi, &this_rd_stats, INT64_MAX, AOM_PLANE_Y,
6050 mbmi->sb_type, mbmi->tx_size,
6051 cpi->sf.use_fast_coef_costing);
6052 xd->cfl->store_y = 0;
6053 }
6054#endif // CONFIG_CFL
Luc Trudeau9d4cbb82017-07-27 17:01:32 -04006055 rd_pick_intra_sbuv_mode(cpi, x, rate_uv, rate_uv_tokenonly, dist_uv, skip_uv,
6056 bsize, max_tx_size);
Luc Trudeaub05eeae2017-08-18 15:14:30 -04006057 *mode_uv = mbmi->uv_mode;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006058}
6059
Yue Chenb23d00a2017-07-28 17:01:21 -07006060static int cost_mv_ref(const MACROBLOCK *const x, PREDICTION_MODE mode,
Yaowu Xuc27fc142016-08-22 16:08:15 -07006061 int16_t mode_context) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006062 if (is_inter_compound_mode(mode)) {
Yue Chenb23d00a2017-07-28 17:01:21 -07006063 return x
clang-format55ce9e02017-02-15 22:27:12 -08006064 ->inter_compound_mode_cost[mode_context][INTER_COMPOUND_OFFSET(mode)];
Zoe Liu85b66462017-04-20 14:28:19 -07006065#if CONFIG_COMPOUND_SINGLEREF
6066 } else if (is_inter_singleref_comp_mode(mode)) {
Yue Chenb23d00a2017-07-28 17:01:21 -07006067 return x->inter_singleref_comp_mode_cost[mode_context]
6068 [INTER_SINGLEREF_COMP_OFFSET(mode)];
Zoe Liu85b66462017-04-20 14:28:19 -07006069#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07006070 }
David Barkercb03dc32017-04-07 13:05:09 +01006071
David Barkercb03dc32017-04-07 13:05:09 +01006072 int mode_cost = 0;
6073 int16_t mode_ctx = mode_context & NEWMV_CTX_MASK;
6074 int16_t is_all_zero_mv = mode_context & (1 << ALL_ZERO_FLAG_OFFSET);
6075
6076 assert(is_inter_mode(mode));
6077
6078 if (mode == NEWMV) {
Yue Chenb23d00a2017-07-28 17:01:21 -07006079 mode_cost = x->newmv_mode_cost[mode_ctx][0];
David Barkercb03dc32017-04-07 13:05:09 +01006080 return mode_cost;
6081 } else {
Yue Chenb23d00a2017-07-28 17:01:21 -07006082 mode_cost = x->newmv_mode_cost[mode_ctx][1];
David Barkercb03dc32017-04-07 13:05:09 +01006083 mode_ctx = (mode_context >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
6084
6085 if (is_all_zero_mv) return mode_cost;
6086
6087 if (mode == ZEROMV) {
Yue Chenb23d00a2017-07-28 17:01:21 -07006088 mode_cost += x->zeromv_mode_cost[mode_ctx][0];
David Barkercb03dc32017-04-07 13:05:09 +01006089 return mode_cost;
6090 } else {
Yue Chenb23d00a2017-07-28 17:01:21 -07006091 mode_cost += x->zeromv_mode_cost[mode_ctx][1];
David Barkercb03dc32017-04-07 13:05:09 +01006092 mode_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK;
6093
6094 if (mode_context & (1 << SKIP_NEARESTMV_OFFSET)) mode_ctx = 6;
6095 if (mode_context & (1 << SKIP_NEARMV_OFFSET)) mode_ctx = 7;
6096 if (mode_context & (1 << SKIP_NEARESTMV_SUB8X8_OFFSET)) mode_ctx = 8;
6097
Yue Chenb23d00a2017-07-28 17:01:21 -07006098 mode_cost += x->refmv_mode_cost[mode_ctx][mode != NEARESTMV];
David Barkercb03dc32017-04-07 13:05:09 +01006099 return mode_cost;
6100 }
6101 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07006102}
6103
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006104#if (CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT)
Sarah Parker6fdc8532016-11-16 17:47:13 -08006105static int get_interinter_compound_type_bits(BLOCK_SIZE bsize,
6106 COMPOUND_TYPE comp_type) {
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00006107 (void)bsize;
Sarah Parker6fdc8532016-11-16 17:47:13 -08006108 switch (comp_type) {
6109 case COMPOUND_AVERAGE: return 0;
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00006110#if CONFIG_WEDGE
Sarah Parker6fdc8532016-11-16 17:47:13 -08006111 case COMPOUND_WEDGE: return get_interinter_wedge_bits(bsize);
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00006112#endif // CONFIG_WEDGE
Sarah Parker2f6ce752016-12-08 15:26:46 -08006113#if CONFIG_COMPOUND_SEGMENT
Sarah Parker569edda2016-12-14 14:57:38 -08006114 case COMPOUND_SEG: return 1;
Sarah Parker2f6ce752016-12-08 15:26:46 -08006115#endif // CONFIG_COMPOUND_SEGMENT
Sarah Parker6fdc8532016-11-16 17:47:13 -08006116 default: assert(0); return 0;
6117 }
6118}
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006119#endif // (CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT)
Sarah Parker6fdc8532016-11-16 17:47:13 -08006120
Yaowu Xuc27fc142016-08-22 16:08:15 -07006121typedef struct {
6122 int eobs;
6123 int brate;
6124 int byrate;
6125 int64_t bdist;
6126 int64_t bsse;
6127 int64_t brdcost;
6128 int_mv mvs[2];
Yaowu Xuc27fc142016-08-22 16:08:15 -07006129 int_mv pred_mv[2];
Yaowu Xuc27fc142016-08-22 16:08:15 -07006130 int_mv ref_mv[2];
Jingning Han276c2942016-12-05 12:37:02 -08006131
Timothy B. Terriberryfe67ed62017-04-26 16:53:47 -07006132#if CONFIG_CHROMA_2X2
Jingning Han276c2942016-12-05 12:37:02 -08006133 ENTROPY_CONTEXT ta[4];
6134 ENTROPY_CONTEXT tl[4];
6135#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07006136 ENTROPY_CONTEXT ta[2];
6137 ENTROPY_CONTEXT tl[2];
Timothy B. Terriberryfe67ed62017-04-26 16:53:47 -07006138#endif // CONFIG_CHROMA_2X2
Yaowu Xuc27fc142016-08-22 16:08:15 -07006139} SEG_RDSTAT;
6140
6141typedef struct {
6142 int_mv *ref_mv[2];
6143 int_mv mvp;
6144
6145 int64_t segment_rd;
6146 int r;
6147 int64_t d;
6148 int64_t sse;
6149 int segment_yrate;
6150 PREDICTION_MODE modes[4];
Zoe Liu85b66462017-04-20 14:28:19 -07006151#if CONFIG_COMPOUND_SINGLEREF
6152 SEG_RDSTAT rdstat[4][INTER_MODES + INTER_SINGLEREF_COMP_MODES +
6153 INTER_COMPOUND_MODES];
6154#else // !CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07006155 SEG_RDSTAT rdstat[4][INTER_MODES + INTER_COMPOUND_MODES];
Zoe Liu85b66462017-04-20 14:28:19 -07006156#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07006157 int mvthresh;
6158} BEST_SEG_INFO;
6159
Alex Converse0fa0f422017-04-24 12:51:14 -07006160static INLINE int mv_check_bounds(const MvLimits *mv_limits, const MV *mv) {
6161 return (mv->row >> 3) < mv_limits->row_min ||
6162 (mv->row >> 3) > mv_limits->row_max ||
6163 (mv->col >> 3) < mv_limits->col_min ||
6164 (mv->col >> 3) > mv_limits->col_max;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006165}
6166
Yaowu Xuc27fc142016-08-22 16:08:15 -07006167// Check if NEARESTMV/NEARMV/ZEROMV is the cheapest way encode zero motion.
6168// TODO(aconverse): Find out if this is still productive then clean up or remove
6169static int check_best_zero_mv(
Yue Chenb23d00a2017-07-28 17:01:21 -07006170 const AV1_COMP *const cpi, const MACROBLOCK *const x,
6171 const int16_t mode_context[TOTAL_REFS_PER_FRAME],
Yaowu Xuc27fc142016-08-22 16:08:15 -07006172 const int16_t compound_mode_context[TOTAL_REFS_PER_FRAME],
Yaowu Xuc27fc142016-08-22 16:08:15 -07006173 int_mv frame_mv[MB_MODE_COUNT][TOTAL_REFS_PER_FRAME], int this_mode,
David Barker45390c12017-02-20 14:44:40 +00006174 const MV_REFERENCE_FRAME ref_frames[2], const BLOCK_SIZE bsize, int block,
6175 int mi_row, int mi_col) {
Luc Trudeaud28e91d2017-06-05 14:42:26 -04006176 int_mv zeromv[2] = { {.as_int = 0 } };
Yushin Choc9751c52017-06-12 10:38:29 -07006177#if CONFIG_GLOBAL_MOTION
Sarah Parkerc2d38712017-01-24 15:15:41 -08006178 int comp_pred_mode = ref_frames[1] > INTRA_FRAME;
Yushin Choc9751c52017-06-12 10:38:29 -07006179#endif
David Barker45390c12017-02-20 14:44:40 +00006180 (void)mi_row;
6181 (void)mi_col;
Zoe Liubc030ee2017-07-31 15:20:46 -07006182 (void)cpi;
Sarah Parkerc2d38712017-01-24 15:15:41 -08006183#if CONFIG_GLOBAL_MOTION
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006184 if (this_mode == ZEROMV || this_mode == ZERO_ZEROMV) {
Luc Trudeaud28e91d2017-06-05 14:42:26 -04006185 for (int cur_frm = 0; cur_frm < 1 + comp_pred_mode; cur_frm++) {
Sarah Parkerc2d38712017-01-24 15:15:41 -08006186 zeromv[cur_frm].as_int =
6187 gm_get_motion_vector(&cpi->common.global_motion[ref_frames[cur_frm]],
Sarah Parkerae7c4582017-02-28 16:30:30 -08006188 cpi->common.allow_high_precision_mv, bsize,
RogerZhou3b635242017-09-19 10:06:46 -07006189 mi_col, mi_row, block
6190#if CONFIG_AMVR
6191 ,
6192 cpi->common.cur_frame_mv_precision_level
6193#endif
6194 )
Sarah Parkerc2d38712017-01-24 15:15:41 -08006195 .as_int;
Luc Trudeaud28e91d2017-06-05 14:42:26 -04006196 }
Sarah Parkerc2d38712017-01-24 15:15:41 -08006197 }
Luc Trudeaud28e91d2017-06-05 14:42:26 -04006198#endif // CONFIG_GLOBAL_MOTION
6199
Yaowu Xuc27fc142016-08-22 16:08:15 -07006200 if ((this_mode == NEARMV || this_mode == NEARESTMV || this_mode == ZEROMV) &&
Sarah Parkerc2d38712017-01-24 15:15:41 -08006201 frame_mv[this_mode][ref_frames[0]].as_int == zeromv[0].as_int &&
Yaowu Xuc27fc142016-08-22 16:08:15 -07006202 (ref_frames[1] <= INTRA_FRAME ||
Sarah Parkerc2d38712017-01-24 15:15:41 -08006203 frame_mv[this_mode][ref_frames[1]].as_int == zeromv[1].as_int)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006204 int16_t rfc =
Yaowu Xuf883b422016-08-30 14:01:10 -07006205 av1_mode_context_analyzer(mode_context, ref_frames, bsize, block);
Yue Chenb23d00a2017-07-28 17:01:21 -07006206 int c1 = cost_mv_ref(x, NEARMV, rfc);
6207 int c2 = cost_mv_ref(x, NEARESTMV, rfc);
6208 int c3 = cost_mv_ref(x, ZEROMV, rfc);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006209
Yaowu Xuc27fc142016-08-22 16:08:15 -07006210 if (this_mode == NEARMV) {
6211 if (c1 > c3) return 0;
6212 } else if (this_mode == NEARESTMV) {
6213 if (c2 > c3) return 0;
6214 } else {
6215 assert(this_mode == ZEROMV);
6216 if (ref_frames[1] <= INTRA_FRAME) {
6217 if ((c3 >= c2 && frame_mv[NEARESTMV][ref_frames[0]].as_int == 0) ||
6218 (c3 >= c1 && frame_mv[NEARMV][ref_frames[0]].as_int == 0))
6219 return 0;
6220 } else {
6221 if ((c3 >= c2 && frame_mv[NEARESTMV][ref_frames[0]].as_int == 0 &&
6222 frame_mv[NEARESTMV][ref_frames[1]].as_int == 0) ||
6223 (c3 >= c1 && frame_mv[NEARMV][ref_frames[0]].as_int == 0 &&
6224 frame_mv[NEARMV][ref_frames[1]].as_int == 0))
6225 return 0;
6226 }
6227 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006228 } else if ((this_mode == NEAREST_NEARESTMV || this_mode == NEAR_NEARMV ||
6229 this_mode == ZERO_ZEROMV) &&
6230 frame_mv[this_mode][ref_frames[0]].as_int == zeromv[0].as_int &&
6231 frame_mv[this_mode][ref_frames[1]].as_int == zeromv[1].as_int) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006232 int16_t rfc = compound_mode_context[ref_frames[0]];
Yue Chenb23d00a2017-07-28 17:01:21 -07006233 int c2 = cost_mv_ref(x, NEAREST_NEARESTMV, rfc);
6234 int c3 = cost_mv_ref(x, ZERO_ZEROMV, rfc);
6235 int c5 = cost_mv_ref(x, NEAR_NEARMV, rfc);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006236
Debargha Mukherjeebb6e1342017-04-17 16:05:04 -07006237 if (this_mode == NEAREST_NEARESTMV) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006238 if (c2 > c3) return 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006239 } else if (this_mode == NEAR_NEARMV) {
6240 if (c5 > c3) return 0;
6241 } else {
6242 assert(this_mode == ZERO_ZEROMV);
6243 if ((c3 >= c2 && frame_mv[NEAREST_NEARESTMV][ref_frames[0]].as_int == 0 &&
6244 frame_mv[NEAREST_NEARESTMV][ref_frames[1]].as_int == 0) ||
Yaowu Xuc27fc142016-08-22 16:08:15 -07006245 (c3 >= c5 && frame_mv[NEAR_NEARMV][ref_frames[0]].as_int == 0 &&
Debargha Mukherjeebb6e1342017-04-17 16:05:04 -07006246 frame_mv[NEAR_NEARMV][ref_frames[1]].as_int == 0))
Yaowu Xuc27fc142016-08-22 16:08:15 -07006247 return 0;
6248 }
6249 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07006250 return 1;
6251}
6252
Urvang Joshi52648442016-10-13 17:27:51 -07006253static void joint_motion_search(const AV1_COMP *cpi, MACROBLOCK *x,
Zoe Liu85b66462017-04-20 14:28:19 -07006254 BLOCK_SIZE bsize, int_mv *frame_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006255#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006256 int_mv *frame_comp_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006257#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006258 int mi_row, int mi_col,
David Barkerc155e012017-05-11 13:54:54 +01006259 int_mv *ref_mv_sub8x8[2], const uint8_t *mask,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006260 int mask_stride, int *rate_mv,
6261 const int block) {
Yaowu Xuf883b422016-08-30 14:01:10 -07006262 const AV1_COMMON *const cm = &cpi->common;
Jingning Hanae5cfde2016-11-30 12:01:44 -08006263 const int pw = block_size_wide[bsize];
6264 const int ph = block_size_high[bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -07006265 MACROBLOCKD *xd = &x->e_mbd;
6266 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Zoe Liu85b66462017-04-20 14:28:19 -07006267// This function should only ever be called for compound modes
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006268#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006269 if (!has_second_ref(mbmi)) {
6270 assert(is_inter_singleref_comp_mode(mbmi->mode));
6271 assert(frame_comp_mv);
6272 }
6273 assert(has_second_ref(mbmi) || is_inter_singleref_comp_mode(mbmi->mode));
clang-format4eafefe2017-09-04 12:51:20 -07006274 const int refs[2] = { mbmi->ref_frame[0],
6275 has_second_ref(mbmi) ? mbmi->ref_frame[1]
6276 : mbmi->ref_frame[0] };
Zoe Liu85b66462017-04-20 14:28:19 -07006277#else
Sarah Parkerb3ebed12017-03-09 10:52:03 -08006278 assert(has_second_ref(mbmi));
Zoe Liu122f3942017-04-25 11:18:38 -07006279 const int refs[2] = { mbmi->ref_frame[0], mbmi->ref_frame[1] };
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006280#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07006281 int_mv ref_mv[2];
6282 int ite, ref;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006283 struct scale_factors sf;
Sarah Parker4c10a3c2017-04-10 19:37:59 -07006284#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
James Zern89a015b2017-08-08 12:39:00 -04006285 // ic and ir are the 4x4 coordinates of the sub8x8 at index "block"
Sarah Parkerb3ebed12017-03-09 10:52:03 -08006286 const int ic = block & 1;
6287 const int ir = (block - ic) >> 1;
Jingning Hancb637672017-06-22 09:14:40 -07006288 struct macroblockd_plane *const pd = &xd->plane[0];
Sarah Parkerb3ebed12017-03-09 10:52:03 -08006289 const int p_col = ((mi_col * MI_SIZE) >> pd->subsampling_x) + 4 * ic;
6290 const int p_row = ((mi_row * MI_SIZE) >> pd->subsampling_y) + 4 * ir;
Sarah Parker4c10a3c2017-04-10 19:37:59 -07006291#if CONFIG_GLOBAL_MOTION
Sarah Parkerb3ebed12017-03-09 10:52:03 -08006292 int is_global[2];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006293#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006294 for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) {
6295#else
Sarah Parkerb3ebed12017-03-09 10:52:03 -08006296 for (ref = 0; ref < 2; ++ref) {
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006297#endif // CONFIG_COMPOUND_SINGLEREF
Sarah Parkerb3ebed12017-03-09 10:52:03 -08006298 WarpedMotionParams *const wm =
6299 &xd->global_motion[xd->mi[0]->mbmi.ref_frame[ref]];
6300 is_global[ref] = is_global_mv_block(xd->mi[0], block, wm->wmtype);
6301 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006302#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006303 if (!has_second_ref(mbmi)) is_global[1] = is_global[0];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006304#endif // CONFIG_COMPOUND_SINGLEREF
Sarah Parkerb3ebed12017-03-09 10:52:03 -08006305#endif // CONFIG_GLOBAL_MOTION
Timothy B. Terriberry5d24b6f2017-06-15 13:39:35 -07006306#else // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
6307 (void)block;
Sarah Parker4c10a3c2017-04-10 19:37:59 -07006308#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -07006309
6310 // Do joint motion search in compound mode to get more accurate mv.
6311 struct buf_2d backup_yv12[2][MAX_MB_PLANE];
6312 int last_besterr[2] = { INT_MAX, INT_MAX };
6313 const YV12_BUFFER_CONFIG *const scaled_ref_frame[2] = {
Zoe Liu122f3942017-04-25 11:18:38 -07006314 av1_get_scaled_ref_frame(cpi, refs[0]),
6315 av1_get_scaled_ref_frame(cpi, refs[1])
Yaowu Xuc27fc142016-08-22 16:08:15 -07006316 };
6317
6318// Prediction buffer from second frame.
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02006319#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07006320 DECLARE_ALIGNED(16, uint16_t, second_pred_alloc_16[MAX_SB_SQUARE]);
6321 uint8_t *second_pred;
6322#else
6323 DECLARE_ALIGNED(16, uint8_t, second_pred[MAX_SB_SQUARE]);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02006324#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07006325
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006326#if CONFIG_CB4X4
Jingning Han61418bb2017-01-23 17:12:48 -08006327 (void)ref_mv_sub8x8;
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006328#endif // CONFIG_CB4X4
Jingning Han61418bb2017-01-23 17:12:48 -08006329
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006330#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006331 for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) {
6332#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07006333 for (ref = 0; ref < 2; ++ref) {
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006334#endif // CONFIG_COMPOUND_SINGLEREF
6335#if !CONFIG_CB4X4
Yaowu Xuc27fc142016-08-22 16:08:15 -07006336 if (bsize < BLOCK_8X8 && ref_mv_sub8x8 != NULL)
6337 ref_mv[ref].as_int = ref_mv_sub8x8[ref]->as_int;
6338 else
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006339#endif // !CONFIG_CB4X4
Yaowu Xuc27fc142016-08-22 16:08:15 -07006340 ref_mv[ref] = x->mbmi_ext->ref_mvs[refs[ref]][0];
6341
6342 if (scaled_ref_frame[ref]) {
6343 int i;
6344 // Swap out the reference frame for a version that's been scaled to
6345 // match the resolution of the current frame, allowing the existing
6346 // motion search code to be used without additional modifications.
6347 for (i = 0; i < MAX_MB_PLANE; i++)
6348 backup_yv12[ref][i] = xd->plane[i].pre[ref];
Yaowu Xuf883b422016-08-30 14:01:10 -07006349 av1_setup_pre_planes(xd, ref, scaled_ref_frame[ref], mi_row, mi_col,
6350 NULL);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006351 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07006352 }
6353
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006354#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006355 if (!has_second_ref(mbmi)) {
6356 assert(is_inter_singleref_comp_mode(mbmi->mode));
6357 // NOTE: For single ref comp mode, set up the 2nd set of ref_mv/pre_planes
6358 // all from the 1st reference frame, i.e. refs[0].
6359 ref_mv[1] = x->mbmi_ext->ref_mvs[refs[0]][0];
6360 if (scaled_ref_frame[0]) {
6361 int i;
6362 // Swap out the reference frame for a version that's been scaled to
6363 // match the resolution of the current frame, allowing the existing
6364 // motion search code to be used without additional modifications.
6365 for (i = 0; i < MAX_MB_PLANE; i++)
6366 backup_yv12[1][i] = xd->plane[i].pre[1];
6367 av1_setup_pre_planes(xd, 1, scaled_ref_frame[0], mi_row, mi_col, NULL);
6368 }
6369 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006370#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006371
Yaowu Xuc27fc142016-08-22 16:08:15 -07006372// Since we have scaled the reference frames to match the size of the current
6373// frame we must use a unit scaling factor during mode selection.
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02006374#if CONFIG_HIGHBITDEPTH
Yaowu Xuf883b422016-08-30 14:01:10 -07006375 av1_setup_scale_factors_for_frame(&sf, cm->width, cm->height, cm->width,
6376 cm->height, cm->use_highbitdepth);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006377#else
Yaowu Xuf883b422016-08-30 14:01:10 -07006378 av1_setup_scale_factors_for_frame(&sf, cm->width, cm->height, cm->width,
6379 cm->height);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02006380#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07006381
Zoe Liu85b66462017-04-20 14:28:19 -07006382// Allow joint search multiple times iteratively for each reference frame
6383// and break out of the search loop if it couldn't find a better mv.
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006384#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006385 const int num_ites =
6386 (has_second_ref(mbmi) || mbmi->mode == SR_NEW_NEWMV) ? 4 : 1;
6387 const int start_ite = has_second_ref(mbmi) ? 0 : 1;
6388 for (ite = start_ite; ite < (start_ite + num_ites); ite++) {
6389#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07006390 for (ite = 0; ite < 4; ite++) {
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006391#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07006392 struct buf_2d ref_yv12[2];
6393 int bestsme = INT_MAX;
6394 int sadpb = x->sadperbit16;
6395 MV *const best_mv = &x->best_mv.as_mv;
6396 int search_range = 3;
6397
Alex Converse0fa0f422017-04-24 12:51:14 -07006398 MvLimits tmp_mv_limits = x->mv_limits;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006399 int id = ite % 2; // Even iterations search in the first reference frame,
6400 // odd iterations search in the second. The predictor
6401 // found for the 'other' reference frame is factored in.
Angie Chiange3a4c1c2017-02-10 16:26:49 -08006402 const int plane = 0;
David Barkere64d51a2017-06-09 14:52:42 +01006403 ConvolveParams conv_params = get_conv_params(!id, 0, plane);
Sarah Parker4c10a3c2017-04-10 19:37:59 -07006404#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
6405 WarpTypesAllowed warp_types;
6406#if CONFIG_GLOBAL_MOTION
6407 warp_types.global_warp_allowed = is_global[!id];
6408#endif // CONFIG_GLOBAL_MOTION
6409#if CONFIG_WARPED_MOTION
6410 warp_types.local_warp_allowed = mbmi->motion_mode == WARPED_CAUSAL;
6411#endif // CONFIG_WARPED_MOTION
6412#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -07006413
6414 // Initialized here because of compiler problem in Visual Studio.
Angie Chiange3a4c1c2017-02-10 16:26:49 -08006415 ref_yv12[0] = xd->plane[plane].pre[0];
6416 ref_yv12[1] = xd->plane[plane].pre[1];
Yaowu Xuc27fc142016-08-22 16:08:15 -07006417
Yaowu Xuc27fc142016-08-22 16:08:15 -07006418// Get the prediction block from the 'other' reference frame.
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006419#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006420 MV *const the_other_mv = (has_second_ref(mbmi) || id)
6421 ? &frame_mv[refs[!id]].as_mv
6422 : &frame_comp_mv[refs[0]].as_mv;
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006423#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006424
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02006425#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07006426 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
6427 second_pred = CONVERT_TO_BYTEPTR(second_pred_alloc_16);
Yaowu Xuf883b422016-08-30 14:01:10 -07006428 av1_highbd_build_inter_predictor(
Yaowu Xuc27fc142016-08-22 16:08:15 -07006429 ref_yv12[!id].buf, ref_yv12[!id].stride, second_pred, pw,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006430#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006431 the_other_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006432#else // !(CONFIG_COMPOUND_SINGLEREF)
Zoe Liu85b66462017-04-20 14:28:19 -07006433 &frame_mv[refs[!id]].as_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006434#endif // CONFIG_COMPOUND_SINGLEREF
Rupert Swarbrick27e90292017-09-28 17:46:50 +01006435 &sf, pw, ph, 0, mbmi->interp_filters,
Sarah Parker4c10a3c2017-04-10 19:37:59 -07006436#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
6437 &warp_types, p_col, p_row,
6438#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
Sarah Parkerb3ebed12017-03-09 10:52:03 -08006439 plane, MV_PRECISION_Q3, mi_col * MI_SIZE, mi_row * MI_SIZE, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006440 } else {
6441 second_pred = (uint8_t *)second_pred_alloc_16;
Zoe Liu76fcff72017-04-24 17:50:53 -07006442#endif // CONFIG_HIGHBITDEPTH
Zoe Liu85b66462017-04-20 14:28:19 -07006443 av1_build_inter_predictor(
6444 ref_yv12[!id].buf, ref_yv12[!id].stride, second_pred, pw,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006445#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006446 the_other_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006447#else // !(CONFIG_COMPOUND_SINGLEREF)
Zoe Liu85b66462017-04-20 14:28:19 -07006448 &frame_mv[refs[!id]].as_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006449#endif // CONFIG_COMPOUND_SINGLEREF
Rupert Swarbrick27e90292017-09-28 17:46:50 +01006450 &sf, pw, ph, &conv_params, mbmi->interp_filters,
Sarah Parker4c10a3c2017-04-10 19:37:59 -07006451#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
Zoe Liu85b66462017-04-20 14:28:19 -07006452 &warp_types, p_col, p_row, plane, !id,
Sarah Parker4c10a3c2017-04-10 19:37:59 -07006453#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
Zoe Liu85b66462017-04-20 14:28:19 -07006454 MV_PRECISION_Q3, mi_col * MI_SIZE, mi_row * MI_SIZE, xd);
Zoe Liu76fcff72017-04-24 17:50:53 -07006455#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07006456 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02006457#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07006458
6459 // Do compound motion search on the current reference frame.
Angie Chiange3a4c1c2017-02-10 16:26:49 -08006460 if (id) xd->plane[plane].pre[0] = ref_yv12[id];
Alex Converse0fa0f422017-04-24 12:51:14 -07006461 av1_set_mv_search_range(&x->mv_limits, &ref_mv[id].as_mv);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006462
Zoe Liu85b66462017-04-20 14:28:19 -07006463// Use the mv result from the single mode as mv predictor.
6464// Use the mv result from the single mode as mv predictor.
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006465#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006466 if (!has_second_ref(mbmi) && id)
6467 *best_mv = frame_comp_mv[refs[0]].as_mv;
6468 else
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006469#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006470 *best_mv = frame_mv[refs[id]].as_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006471
6472 best_mv->col >>= 3;
6473 best_mv->row >>= 3;
6474
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006475#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006476 if (!has_second_ref(mbmi))
6477 av1_set_mvcost(x, refs[0], 0, mbmi->ref_mv_idx);
6478 else
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006479#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006480 av1_set_mvcost(x, refs[id], id, mbmi->ref_mv_idx);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006481
6482 // Small-range full-pixel motion search.
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006483 bestsme = av1_refining_search_8p_c(x, sadpb, search_range,
6484 &cpi->fn_ptr[bsize], mask, mask_stride,
6485 id, &ref_mv[id].as_mv, second_pred);
David Barkerc155e012017-05-11 13:54:54 +01006486 if (bestsme < INT_MAX) {
David Barkerc155e012017-05-11 13:54:54 +01006487 if (mask)
6488 bestsme = av1_get_mvpred_mask_var(x, best_mv, &ref_mv[id].as_mv,
6489 second_pred, mask, mask_stride, id,
6490 &cpi->fn_ptr[bsize], 1);
6491 else
David Barkerc155e012017-05-11 13:54:54 +01006492 bestsme = av1_get_mvpred_av_var(x, best_mv, &ref_mv[id].as_mv,
6493 second_pred, &cpi->fn_ptr[bsize], 1);
6494 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07006495
Alex Converse0fa0f422017-04-24 12:51:14 -07006496 x->mv_limits = tmp_mv_limits;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006497
RogerZhou3b635242017-09-19 10:06:46 -07006498#if CONFIG_AMVR
6499 if (cpi->common.cur_frame_mv_precision_level) {
6500 x->best_mv.as_mv.row *= 8;
6501 x->best_mv.as_mv.col *= 8;
6502 }
6503 if (bestsme < INT_MAX && cpi->common.cur_frame_mv_precision_level == 0) {
6504#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07006505 if (bestsme < INT_MAX) {
RogerZhou3b635242017-09-19 10:06:46 -07006506#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07006507 int dis; /* TODO: use dis in distortion calculation later. */
6508 unsigned int sse;
Timothy B. Terriberry5d24b6f2017-06-15 13:39:35 -07006509 bestsme = cpi->find_fractional_mv_step(
6510 x, &ref_mv[id].as_mv, cpi->common.allow_high_precision_mv,
6511 x->errorperbit, &cpi->fn_ptr[bsize], 0,
6512 cpi->sf.mv.subpel_iters_per_step, NULL, x->nmvjointcost, x->mvcost,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006513 &dis, &sse, second_pred, mask, mask_stride, id, pw, ph,
6514 cpi->sf.use_upsampled_references);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006515 }
6516
6517 // Restore the pointer to the first (possibly scaled) prediction buffer.
Angie Chiange3a4c1c2017-02-10 16:26:49 -08006518 if (id) xd->plane[plane].pre[0] = ref_yv12[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -07006519
6520 if (bestsme < last_besterr[id]) {
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006521#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006522 // NOTE: For single ref comp mode, frame_mv stores the first mv and
6523 // frame_comp_mv stores the second mv.
6524 if (!has_second_ref(mbmi) && id)
6525 frame_comp_mv[refs[0]].as_mv = *best_mv;
6526 else
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006527#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006528 frame_mv[refs[id]].as_mv = *best_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006529 last_besterr[id] = bestsme;
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006530#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006531 if (!has_second_ref(mbmi)) last_besterr[!id] = last_besterr[id];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006532#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07006533 } else {
6534 break;
6535 }
6536 }
6537
6538 *rate_mv = 0;
6539
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006540#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006541 for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) {
6542#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07006543 for (ref = 0; ref < 2; ++ref) {
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006544#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07006545 if (scaled_ref_frame[ref]) {
6546 // Restore the prediction frame pointers to their unscaled versions.
6547 int i;
6548 for (i = 0; i < MAX_MB_PLANE; i++)
6549 xd->plane[i].pre[ref] = backup_yv12[ref][i];
6550 }
Zoe Liu85b66462017-04-20 14:28:19 -07006551
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006552#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006553 if (!has_second_ref(mbmi))
6554 av1_set_mvcost(x, refs[0], 0, mbmi->ref_mv_idx);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006555 else
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006556#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006557 av1_set_mvcost(x, refs[ref], ref, mbmi->ref_mv_idx);
6558
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006559#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006560 if (!has_second_ref(mbmi)) {
6561 // NOTE: For single ref comp mode, i.e. !has_second_ref(mbmi) is true, the
6562 // first mv is stored in frame_mv[] and the second mv is stored in
6563 // frame_comp_mv[].
6564 if (compound_ref0_mode(mbmi->mode) == NEWMV) // SR_NEW_NEWMV
6565 *rate_mv += av1_mv_bit_cost(&frame_mv[refs[0]].as_mv,
6566 &x->mbmi_ext->ref_mvs[refs[0]][0].as_mv,
6567 x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
6568 assert(compound_ref1_mode(mbmi->mode) == NEWMV);
6569 *rate_mv += av1_mv_bit_cost(&frame_comp_mv[refs[0]].as_mv,
6570 &x->mbmi_ext->ref_mvs[refs[0]][0].as_mv,
6571 x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
6572 } else {
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006573#endif // CONFIG_COMPOUND_SINGLEREF
6574#if !CONFIG_CB4X4
Zoe Liu85b66462017-04-20 14:28:19 -07006575 if (bsize >= BLOCK_8X8)
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006576#endif // !CONFIG_CB4X4
Zoe Liu85b66462017-04-20 14:28:19 -07006577 *rate_mv += av1_mv_bit_cost(&frame_mv[refs[ref]].as_mv,
6578 &x->mbmi_ext->ref_mvs[refs[ref]][0].as_mv,
6579 x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006580#if !CONFIG_CB4X4
Zoe Liu85b66462017-04-20 14:28:19 -07006581 else
6582 *rate_mv += av1_mv_bit_cost(&frame_mv[refs[ref]].as_mv,
6583 &ref_mv_sub8x8[ref]->as_mv, x->nmvjointcost,
6584 x->mvcost, MV_COST_WEIGHT);
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006585#endif // !CONFIG_CB4X4
6586#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006587 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006588#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07006589 }
Zoe Liu85b66462017-04-20 14:28:19 -07006590
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006591#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006592 if (!has_second_ref(mbmi)) {
6593 if (scaled_ref_frame[0]) {
6594 // Restore the prediction frame pointers to their unscaled versions.
6595 int i;
6596 for (i = 0; i < MAX_MB_PLANE; i++)
6597 xd->plane[i].pre[1] = backup_yv12[1][i];
6598 }
6599 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006600#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07006601}
6602
Zoe Liuc082bbc2017-05-17 13:31:37 -07006603static void estimate_ref_frame_costs(
6604 const AV1_COMMON *cm, const MACROBLOCKD *xd, int segment_id,
6605 unsigned int *ref_costs_single,
6606#if CONFIG_EXT_COMP_REFS
6607 unsigned int (*ref_costs_comp)[TOTAL_REFS_PER_FRAME],
6608#else
6609 unsigned int *ref_costs_comp,
6610#endif // CONFIG_EXT_COMP_REFS
6611 aom_prob *comp_mode_p) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006612 int seg_ref_active =
6613 segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME);
6614 if (seg_ref_active) {
6615 memset(ref_costs_single, 0,
6616 TOTAL_REFS_PER_FRAME * sizeof(*ref_costs_single));
Zoe Liuc082bbc2017-05-17 13:31:37 -07006617#if CONFIG_EXT_COMP_REFS
6618 int ref_frame;
6619 for (ref_frame = 0; ref_frame < TOTAL_REFS_PER_FRAME; ++ref_frame)
6620 memset(ref_costs_comp[ref_frame], 0,
6621 TOTAL_REFS_PER_FRAME * sizeof((*ref_costs_comp)[0]));
6622#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07006623 memset(ref_costs_comp, 0, TOTAL_REFS_PER_FRAME * sizeof(*ref_costs_comp));
Zoe Liuc082bbc2017-05-17 13:31:37 -07006624#endif // CONFIG_EXT_COMP_REFS
6625
Yaowu Xuc27fc142016-08-22 16:08:15 -07006626 *comp_mode_p = 128;
6627 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -07006628 aom_prob intra_inter_p = av1_get_intra_inter_prob(cm, xd);
6629 aom_prob comp_inter_p = 128;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006630
6631 if (cm->reference_mode == REFERENCE_MODE_SELECT) {
Yaowu Xuf883b422016-08-30 14:01:10 -07006632 comp_inter_p = av1_get_reference_mode_prob(cm, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006633 *comp_mode_p = comp_inter_p;
6634 } else {
6635 *comp_mode_p = 128;
6636 }
6637
Yaowu Xuf883b422016-08-30 14:01:10 -07006638 ref_costs_single[INTRA_FRAME] = av1_cost_bit(intra_inter_p, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006639
6640 if (cm->reference_mode != COMPOUND_REFERENCE) {
Yaowu Xuf883b422016-08-30 14:01:10 -07006641 aom_prob ref_single_p1 = av1_get_pred_prob_single_ref_p1(cm, xd);
6642 aom_prob ref_single_p2 = av1_get_pred_prob_single_ref_p2(cm, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006643#if CONFIG_EXT_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -07006644 aom_prob ref_single_p3 = av1_get_pred_prob_single_ref_p3(cm, xd);
6645 aom_prob ref_single_p4 = av1_get_pred_prob_single_ref_p4(cm, xd);
6646 aom_prob ref_single_p5 = av1_get_pred_prob_single_ref_p5(cm, xd);
Zoe Liue9b15e22017-07-19 15:53:01 -07006647 aom_prob ref_single_p6 = av1_get_pred_prob_single_ref_p6(cm, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006648#endif // CONFIG_EXT_REFS
6649
Yaowu Xuf883b422016-08-30 14:01:10 -07006650 unsigned int base_cost = av1_cost_bit(intra_inter_p, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006651
6652 ref_costs_single[LAST_FRAME] =
6653#if CONFIG_EXT_REFS
6654 ref_costs_single[LAST2_FRAME] = ref_costs_single[LAST3_FRAME] =
Zoe Liu3ac20932017-08-30 16:35:55 -07006655 ref_costs_single[BWDREF_FRAME] = ref_costs_single[ALTREF2_FRAME] =
Yaowu Xuc27fc142016-08-22 16:08:15 -07006656#endif // CONFIG_EXT_REFS
Zoe Liu3ac20932017-08-30 16:35:55 -07006657 ref_costs_single[GOLDEN_FRAME] =
6658 ref_costs_single[ALTREF_FRAME] = base_cost;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006659
6660#if CONFIG_EXT_REFS
Zoe Liufcf5fa22017-06-26 16:00:38 -07006661 ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p1, 0);
6662 ref_costs_single[LAST2_FRAME] += av1_cost_bit(ref_single_p1, 0);
6663 ref_costs_single[LAST3_FRAME] += av1_cost_bit(ref_single_p1, 0);
6664 ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p1, 0);
6665 ref_costs_single[BWDREF_FRAME] += av1_cost_bit(ref_single_p1, 1);
Zoe Liue9b15e22017-07-19 15:53:01 -07006666 ref_costs_single[ALTREF2_FRAME] += av1_cost_bit(ref_single_p1, 1);
Zoe Liufcf5fa22017-06-26 16:00:38 -07006667 ref_costs_single[ALTREF_FRAME] += av1_cost_bit(ref_single_p1, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006668
Zoe Liufcf5fa22017-06-26 16:00:38 -07006669 ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p3, 0);
6670 ref_costs_single[LAST2_FRAME] += av1_cost_bit(ref_single_p3, 0);
6671 ref_costs_single[LAST3_FRAME] += av1_cost_bit(ref_single_p3, 1);
6672 ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p3, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006673
Zoe Liufcf5fa22017-06-26 16:00:38 -07006674 ref_costs_single[BWDREF_FRAME] += av1_cost_bit(ref_single_p2, 0);
Zoe Liue9b15e22017-07-19 15:53:01 -07006675 ref_costs_single[ALTREF2_FRAME] += av1_cost_bit(ref_single_p2, 0);
Zoe Liufcf5fa22017-06-26 16:00:38 -07006676 ref_costs_single[ALTREF_FRAME] += av1_cost_bit(ref_single_p2, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006677
Zoe Liufcf5fa22017-06-26 16:00:38 -07006678 ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p4, 0);
6679 ref_costs_single[LAST2_FRAME] += av1_cost_bit(ref_single_p4, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006680
Zoe Liufcf5fa22017-06-26 16:00:38 -07006681 ref_costs_single[LAST3_FRAME] += av1_cost_bit(ref_single_p5, 0);
6682 ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p5, 1);
Zoe Liue9b15e22017-07-19 15:53:01 -07006683
Zoe Liue9b15e22017-07-19 15:53:01 -07006684 ref_costs_single[BWDREF_FRAME] += av1_cost_bit(ref_single_p6, 0);
6685 ref_costs_single[ALTREF2_FRAME] += av1_cost_bit(ref_single_p6, 1);
Zoe Liu7b1ec7a2017-05-24 22:28:24 -07006686#else // !CONFIG_EXT_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -07006687 ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p1, 0);
6688 ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p1, 1);
6689 ref_costs_single[ALTREF_FRAME] += av1_cost_bit(ref_single_p1, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006690
Yaowu Xuf883b422016-08-30 14:01:10 -07006691 ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p2, 0);
6692 ref_costs_single[ALTREF_FRAME] += av1_cost_bit(ref_single_p2, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006693#endif // CONFIG_EXT_REFS
6694 } else {
6695 ref_costs_single[LAST_FRAME] = 512;
6696#if CONFIG_EXT_REFS
6697 ref_costs_single[LAST2_FRAME] = 512;
6698 ref_costs_single[LAST3_FRAME] = 512;
6699 ref_costs_single[BWDREF_FRAME] = 512;
Zoe Liue9b15e22017-07-19 15:53:01 -07006700 ref_costs_single[ALTREF2_FRAME] = 512;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006701#endif // CONFIG_EXT_REFS
6702 ref_costs_single[GOLDEN_FRAME] = 512;
6703 ref_costs_single[ALTREF_FRAME] = 512;
6704 }
6705
6706 if (cm->reference_mode != SINGLE_REFERENCE) {
Yaowu Xuf883b422016-08-30 14:01:10 -07006707 aom_prob ref_comp_p = av1_get_pred_prob_comp_ref_p(cm, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006708#if CONFIG_EXT_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -07006709 aom_prob ref_comp_p1 = av1_get_pred_prob_comp_ref_p1(cm, xd);
6710 aom_prob ref_comp_p2 = av1_get_pred_prob_comp_ref_p2(cm, xd);
6711 aom_prob bwdref_comp_p = av1_get_pred_prob_comp_bwdref_p(cm, xd);
Zoe Liue9b15e22017-07-19 15:53:01 -07006712 aom_prob bwdref_comp_p1 = av1_get_pred_prob_comp_bwdref_p1(cm, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006713#endif // CONFIG_EXT_REFS
6714
Yaowu Xuf883b422016-08-30 14:01:10 -07006715 unsigned int base_cost = av1_cost_bit(intra_inter_p, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006716
Zoe Liuc082bbc2017-05-17 13:31:37 -07006717#if CONFIG_EXT_COMP_REFS
6718 aom_prob comp_ref_type_p = av1_get_comp_reference_type_prob(cm, xd);
6719 unsigned int ref_bicomp_costs[TOTAL_REFS_PER_FRAME] = { 0 };
6720
6721 ref_bicomp_costs[LAST_FRAME] = ref_bicomp_costs[LAST2_FRAME] =
6722 ref_bicomp_costs[LAST3_FRAME] = ref_bicomp_costs[GOLDEN_FRAME] =
6723#if USE_UNI_COMP_REFS
6724 base_cost + av1_cost_bit(comp_ref_type_p, 1);
6725#else
6726 base_cost;
6727#endif // USE_UNI_COMP_REFS
Zoe Liu3ac20932017-08-30 16:35:55 -07006728 ref_bicomp_costs[BWDREF_FRAME] = ref_bicomp_costs[ALTREF2_FRAME] = 0;
Zoe Liuac889702017-08-23 14:22:58 -07006729 ref_bicomp_costs[ALTREF_FRAME] = 0;
Zoe Liuc082bbc2017-05-17 13:31:37 -07006730
6731 ref_bicomp_costs[LAST_FRAME] += av1_cost_bit(ref_comp_p, 0);
6732 ref_bicomp_costs[LAST2_FRAME] += av1_cost_bit(ref_comp_p, 0);
6733 ref_bicomp_costs[LAST3_FRAME] += av1_cost_bit(ref_comp_p, 1);
6734 ref_bicomp_costs[GOLDEN_FRAME] += av1_cost_bit(ref_comp_p, 1);
6735
6736 ref_bicomp_costs[LAST_FRAME] += av1_cost_bit(ref_comp_p1, 1);
6737 ref_bicomp_costs[LAST2_FRAME] += av1_cost_bit(ref_comp_p1, 0);
6738
6739 ref_bicomp_costs[LAST3_FRAME] += av1_cost_bit(ref_comp_p2, 0);
6740 ref_bicomp_costs[GOLDEN_FRAME] += av1_cost_bit(ref_comp_p2, 1);
6741
6742 ref_bicomp_costs[BWDREF_FRAME] += av1_cost_bit(bwdref_comp_p, 0);
Zoe Liuac889702017-08-23 14:22:58 -07006743 ref_bicomp_costs[ALTREF2_FRAME] += av1_cost_bit(bwdref_comp_p, 0);
Zoe Liuc082bbc2017-05-17 13:31:37 -07006744 ref_bicomp_costs[ALTREF_FRAME] += av1_cost_bit(bwdref_comp_p, 1);
6745
Zoe Liuac889702017-08-23 14:22:58 -07006746 ref_bicomp_costs[BWDREF_FRAME] += av1_cost_bit(bwdref_comp_p1, 0);
6747 ref_bicomp_costs[ALTREF2_FRAME] += av1_cost_bit(bwdref_comp_p1, 1);
Zoe Liuac889702017-08-23 14:22:58 -07006748
6749 int ref0, ref1;
Zoe Liuc082bbc2017-05-17 13:31:37 -07006750 for (ref0 = LAST_FRAME; ref0 <= GOLDEN_FRAME; ++ref0) {
Zoe Liuac889702017-08-23 14:22:58 -07006751 for (ref1 = BWDREF_FRAME; ref1 <= ALTREF_FRAME; ++ref1) {
6752 ref_costs_comp[ref0][ref1] =
6753 ref_bicomp_costs[ref0] + ref_bicomp_costs[ref1];
6754 }
Zoe Liuc082bbc2017-05-17 13:31:37 -07006755 }
6756
6757 aom_prob uni_comp_ref_p = av1_get_pred_prob_uni_comp_ref_p(cm, xd);
6758 aom_prob uni_comp_ref_p1 = av1_get_pred_prob_uni_comp_ref_p1(cm, xd);
Zoe Liufcf5fa22017-06-26 16:00:38 -07006759 aom_prob uni_comp_ref_p2 = av1_get_pred_prob_uni_comp_ref_p2(cm, xd);
Zoe Liuc082bbc2017-05-17 13:31:37 -07006760
6761 ref_costs_comp[LAST_FRAME][LAST2_FRAME] =
6762 base_cost + av1_cost_bit(comp_ref_type_p, 0) +
6763 av1_cost_bit(uni_comp_ref_p, 0) + av1_cost_bit(uni_comp_ref_p1, 0);
Zoe Liufcf5fa22017-06-26 16:00:38 -07006764 ref_costs_comp[LAST_FRAME][LAST3_FRAME] =
6765 base_cost + av1_cost_bit(comp_ref_type_p, 0) +
6766 av1_cost_bit(uni_comp_ref_p, 0) + av1_cost_bit(uni_comp_ref_p1, 1) +
6767 av1_cost_bit(uni_comp_ref_p2, 0);
Zoe Liuc082bbc2017-05-17 13:31:37 -07006768 ref_costs_comp[LAST_FRAME][GOLDEN_FRAME] =
6769 base_cost + av1_cost_bit(comp_ref_type_p, 0) +
Zoe Liufcf5fa22017-06-26 16:00:38 -07006770 av1_cost_bit(uni_comp_ref_p, 0) + av1_cost_bit(uni_comp_ref_p1, 1) +
6771 av1_cost_bit(uni_comp_ref_p2, 1);
Zoe Liuc082bbc2017-05-17 13:31:37 -07006772
6773 ref_costs_comp[BWDREF_FRAME][ALTREF_FRAME] =
6774 base_cost + av1_cost_bit(comp_ref_type_p, 0) +
6775 av1_cost_bit(uni_comp_ref_p, 1);
6776
6777#else // !CONFIG_EXT_COMP_REFS
6778
Yaowu Xuc27fc142016-08-22 16:08:15 -07006779 ref_costs_comp[LAST_FRAME] =
6780#if CONFIG_EXT_REFS
6781 ref_costs_comp[LAST2_FRAME] = ref_costs_comp[LAST3_FRAME] =
6782#endif // CONFIG_EXT_REFS
6783 ref_costs_comp[GOLDEN_FRAME] = base_cost;
6784
6785#if CONFIG_EXT_REFS
Zoe Liu3ac20932017-08-30 16:35:55 -07006786 ref_costs_comp[BWDREF_FRAME] = ref_costs_comp[ALTREF2_FRAME] =
6787 ref_costs_comp[ALTREF_FRAME] = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006788#endif // CONFIG_EXT_REFS
6789
6790#if CONFIG_EXT_REFS
Zoe Liufcf5fa22017-06-26 16:00:38 -07006791 ref_costs_comp[LAST_FRAME] += av1_cost_bit(ref_comp_p, 0);
6792 ref_costs_comp[LAST2_FRAME] += av1_cost_bit(ref_comp_p, 0);
6793 ref_costs_comp[LAST3_FRAME] += av1_cost_bit(ref_comp_p, 1);
6794 ref_costs_comp[GOLDEN_FRAME] += av1_cost_bit(ref_comp_p, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006795
Zoe Liufcf5fa22017-06-26 16:00:38 -07006796 ref_costs_comp[LAST_FRAME] += av1_cost_bit(ref_comp_p1, 1);
6797 ref_costs_comp[LAST2_FRAME] += av1_cost_bit(ref_comp_p1, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006798
Zoe Liufcf5fa22017-06-26 16:00:38 -07006799 ref_costs_comp[LAST3_FRAME] += av1_cost_bit(ref_comp_p2, 0);
6800 ref_costs_comp[GOLDEN_FRAME] += av1_cost_bit(ref_comp_p2, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006801
Zoe Liufcf5fa22017-06-26 16:00:38 -07006802 // NOTE(zoeliu): BWDREF and ALTREF each add an extra cost by coding 1
6803 // more bit.
6804 ref_costs_comp[BWDREF_FRAME] += av1_cost_bit(bwdref_comp_p, 0);
Zoe Liue9b15e22017-07-19 15:53:01 -07006805 ref_costs_comp[ALTREF2_FRAME] += av1_cost_bit(bwdref_comp_p, 0);
Zoe Liufcf5fa22017-06-26 16:00:38 -07006806 ref_costs_comp[ALTREF_FRAME] += av1_cost_bit(bwdref_comp_p, 1);
Zoe Liue9b15e22017-07-19 15:53:01 -07006807
Zoe Liue9b15e22017-07-19 15:53:01 -07006808 ref_costs_comp[BWDREF_FRAME] += av1_cost_bit(bwdref_comp_p1, 0);
6809 ref_costs_comp[ALTREF2_FRAME] += av1_cost_bit(bwdref_comp_p1, 1);
Zoe Liu7b1ec7a2017-05-24 22:28:24 -07006810#else // !CONFIG_EXT_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -07006811 ref_costs_comp[LAST_FRAME] += av1_cost_bit(ref_comp_p, 0);
6812 ref_costs_comp[GOLDEN_FRAME] += av1_cost_bit(ref_comp_p, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006813#endif // CONFIG_EXT_REFS
Zoe Liuc082bbc2017-05-17 13:31:37 -07006814#endif // CONFIG_EXT_COMP_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -07006815 } else {
Zoe Liuc082bbc2017-05-17 13:31:37 -07006816#if CONFIG_EXT_COMP_REFS
Zoe Liuac889702017-08-23 14:22:58 -07006817 int ref0, ref1;
Zoe Liuc082bbc2017-05-17 13:31:37 -07006818 for (ref0 = LAST_FRAME; ref0 <= GOLDEN_FRAME; ++ref0) {
Zoe Liuac889702017-08-23 14:22:58 -07006819 for (ref1 = BWDREF_FRAME; ref1 <= ALTREF_FRAME; ++ref1)
6820 ref_costs_comp[ref0][ref1] = 512;
Zoe Liuc082bbc2017-05-17 13:31:37 -07006821 }
6822 ref_costs_comp[LAST_FRAME][LAST2_FRAME] = 512;
Zoe Liufcf5fa22017-06-26 16:00:38 -07006823 ref_costs_comp[LAST_FRAME][LAST3_FRAME] = 512;
Zoe Liuc082bbc2017-05-17 13:31:37 -07006824 ref_costs_comp[LAST_FRAME][GOLDEN_FRAME] = 512;
6825 ref_costs_comp[BWDREF_FRAME][ALTREF_FRAME] = 512;
6826#else // !CONFIG_EXT_COMP_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -07006827 ref_costs_comp[LAST_FRAME] = 512;
6828#if CONFIG_EXT_REFS
6829 ref_costs_comp[LAST2_FRAME] = 512;
6830 ref_costs_comp[LAST3_FRAME] = 512;
6831 ref_costs_comp[BWDREF_FRAME] = 512;
Zoe Liue9b15e22017-07-19 15:53:01 -07006832 ref_costs_comp[ALTREF2_FRAME] = 512;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006833 ref_costs_comp[ALTREF_FRAME] = 512;
6834#endif // CONFIG_EXT_REFS
6835 ref_costs_comp[GOLDEN_FRAME] = 512;
Zoe Liuc082bbc2017-05-17 13:31:37 -07006836#endif // CONFIG_EXT_COMP_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -07006837 }
6838 }
6839}
6840
6841static void store_coding_context(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx,
6842 int mode_index,
6843 int64_t comp_pred_diff[REFERENCE_MODES],
6844 int skippable) {
6845 MACROBLOCKD *const xd = &x->e_mbd;
6846
6847 // Take a snapshot of the coding context so it can be
6848 // restored if we decide to encode this way
6849 ctx->skip = x->skip;
6850 ctx->skippable = skippable;
6851 ctx->best_mode_index = mode_index;
6852 ctx->mic = *xd->mi[0];
6853 ctx->mbmi_ext = *x->mbmi_ext;
6854 ctx->single_pred_diff = (int)comp_pred_diff[SINGLE_REFERENCE];
6855 ctx->comp_pred_diff = (int)comp_pred_diff[COMPOUND_REFERENCE];
6856 ctx->hybrid_pred_diff = (int)comp_pred_diff[REFERENCE_MODE_SELECT];
6857}
6858
clang-format55ce9e02017-02-15 22:27:12 -08006859static void setup_buffer_inter(
6860 const AV1_COMP *const cpi, MACROBLOCK *x, MV_REFERENCE_FRAME ref_frame,
6861 BLOCK_SIZE block_size, int mi_row, int mi_col,
6862 int_mv frame_nearest_mv[TOTAL_REFS_PER_FRAME],
6863 int_mv frame_near_mv[TOTAL_REFS_PER_FRAME],
6864 struct buf_2d yv12_mb[TOTAL_REFS_PER_FRAME][MAX_MB_PLANE]) {
Yaowu Xuf883b422016-08-30 14:01:10 -07006865 const AV1_COMMON *cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006866 const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, ref_frame);
6867 MACROBLOCKD *const xd = &x->e_mbd;
6868 MODE_INFO *const mi = xd->mi[0];
6869 int_mv *const candidates = x->mbmi_ext->ref_mvs[ref_frame];
6870 const struct scale_factors *const sf = &cm->frame_refs[ref_frame - 1].sf;
6871 MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
6872
6873 assert(yv12 != NULL);
6874
6875 // TODO(jkoleszar): Is the UV buffer ever used here? If so, need to make this
6876 // use the UV scaling factors.
Yaowu Xuf883b422016-08-30 14:01:10 -07006877 av1_setup_pred_block(xd, yv12_mb[ref_frame], yv12, mi_row, mi_col, sf, sf);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006878
6879 // Gets an initial list of candidate vectors from neighbours and orders them
Sebastien Alaiwane140c502017-04-27 09:52:34 +02006880 av1_find_mv_refs(cm, xd, mi, ref_frame, &mbmi_ext->ref_mv_count[ref_frame],
6881 mbmi_ext->ref_mv_stack[ref_frame],
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006882 mbmi_ext->compound_mode_context, candidates, mi_row, mi_col,
6883 NULL, NULL, mbmi_ext->mode_context);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006884
RogerZhou3b635242017-09-19 10:06:46 -07006885// Candidate refinement carried out at encoder and decoder
6886#if CONFIG_AMVR
6887 av1_find_best_ref_mvs(cm->allow_high_precision_mv, candidates,
6888 &frame_nearest_mv[ref_frame], &frame_near_mv[ref_frame],
6889 cm->cur_frame_mv_precision_level);
6890#else
Yaowu Xuf883b422016-08-30 14:01:10 -07006891 av1_find_best_ref_mvs(cm->allow_high_precision_mv, candidates,
6892 &frame_nearest_mv[ref_frame],
6893 &frame_near_mv[ref_frame]);
RogerZhou3b635242017-09-19 10:06:46 -07006894#endif
Jingning Han271bb2c2016-12-14 12:34:46 -08006895// Further refinement that is encode side only to test the top few candidates
6896// in full and choose the best as the centre point for subsequent searches.
6897// The current implementation doesn't support scaling.
6898#if CONFIG_CB4X4
6899 av1_mv_pred(cpi, x, yv12_mb[ref_frame][0].buf, yv12->y_stride, ref_frame,
6900 block_size);
6901#else
Yaowu Xuf883b422016-08-30 14:01:10 -07006902 if (!av1_is_scaled(sf) && block_size >= BLOCK_8X8)
6903 av1_mv_pred(cpi, x, yv12_mb[ref_frame][0].buf, yv12->y_stride, ref_frame,
6904 block_size);
Fergus Simpson4063a682017-02-28 16:52:22 -08006905#endif // CONFIG_CB4X4
Yaowu Xuc27fc142016-08-22 16:08:15 -07006906}
6907
Urvang Joshi52648442016-10-13 17:27:51 -07006908static void single_motion_search(const AV1_COMP *const cpi, MACROBLOCK *x,
6909 BLOCK_SIZE bsize, int mi_row, int mi_col,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006910 int ref_idx, int *rate_mv) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006911 MACROBLOCKD *xd = &x->e_mbd;
Yaowu Xuf883b422016-08-30 14:01:10 -07006912 const AV1_COMMON *cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006913 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
6914 struct buf_2d backup_yv12[MAX_MB_PLANE] = { { 0, 0, 0, 0, 0 } };
6915 int bestsme = INT_MAX;
6916 int step_param;
6917 int sadpb = x->sadperbit16;
6918 MV mvp_full;
Zoe Liu85b66462017-04-20 14:28:19 -07006919#if CONFIG_COMPOUND_SINGLEREF
6920 int ref =
6921 has_second_ref(mbmi) ? mbmi->ref_frame[ref_idx] : mbmi->ref_frame[0];
6922#else // !CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07006923 int ref = mbmi->ref_frame[ref_idx];
Zoe Liu85b66462017-04-20 14:28:19 -07006924#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu7f24e1b2017-03-17 17:42:05 -07006925 MV ref_mv = x->mbmi_ext->ref_mvs[ref][0].as_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006926
Alex Converse0fa0f422017-04-24 12:51:14 -07006927 MvLimits tmp_mv_limits = x->mv_limits;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006928 int cost_list[5];
6929
6930 const YV12_BUFFER_CONFIG *scaled_ref_frame =
Yaowu Xuf883b422016-08-30 14:01:10 -07006931 av1_get_scaled_ref_frame(cpi, ref);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006932
6933 MV pred_mv[3];
6934 pred_mv[0] = x->mbmi_ext->ref_mvs[ref][0].as_mv;
6935 pred_mv[1] = x->mbmi_ext->ref_mvs[ref][1].as_mv;
6936 pred_mv[2] = x->pred_mv[ref];
6937
Yaowu Xuc27fc142016-08-22 16:08:15 -07006938 if (scaled_ref_frame) {
6939 int i;
6940 // Swap out the reference frame for a version that's been scaled to
6941 // match the resolution of the current frame, allowing the existing
6942 // motion search code to be used without additional modifications.
6943 for (i = 0; i < MAX_MB_PLANE; i++)
6944 backup_yv12[i] = xd->plane[i].pre[ref_idx];
6945
Yaowu Xuf883b422016-08-30 14:01:10 -07006946 av1_setup_pre_planes(xd, ref_idx, scaled_ref_frame, mi_row, mi_col, NULL);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006947 }
6948
Alex Converse0fa0f422017-04-24 12:51:14 -07006949 av1_set_mv_search_range(&x->mv_limits, &ref_mv);
Yaowu Xu4306b6e2016-09-27 12:55:32 -07006950
Yaowu Xu4306b6e2016-09-27 12:55:32 -07006951 av1_set_mvcost(x, ref, ref_idx, mbmi->ref_mv_idx);
Yaowu Xu4306b6e2016-09-27 12:55:32 -07006952
Yaowu Xuc27fc142016-08-22 16:08:15 -07006953 // Work out the size of the first step in the mv step search.
Yaowu Xuf883b422016-08-30 14:01:10 -07006954 // 0 here is maximum length first step. 1 is AOMMAX >> 1 etc.
Yaowu Xuc27fc142016-08-22 16:08:15 -07006955 if (cpi->sf.mv.auto_mv_step_size && cm->show_frame) {
James Zern89a015b2017-08-08 12:39:00 -04006956 // Take the weighted average of the step_params based on the last frame's
Yaowu Xuc27fc142016-08-22 16:08:15 -07006957 // max mv magnitude and that based on the best ref mvs of the current
6958 // block for the given reference.
6959 step_param =
Yaowu Xuf883b422016-08-30 14:01:10 -07006960 (av1_init_search_range(x->max_mv_context[ref]) + cpi->mv_step_param) /
Yaowu Xuc27fc142016-08-22 16:08:15 -07006961 2;
6962 } else {
6963 step_param = cpi->mv_step_param;
6964 }
6965
6966 if (cpi->sf.adaptive_motion_search && bsize < cm->sb_size) {
6967 int boffset =
6968 2 * (b_width_log2_lookup[cm->sb_size] -
Yaowu Xuf883b422016-08-30 14:01:10 -07006969 AOMMIN(b_height_log2_lookup[bsize], b_width_log2_lookup[bsize]));
6970 step_param = AOMMAX(step_param, boffset);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006971 }
6972
6973 if (cpi->sf.adaptive_motion_search) {
6974 int bwl = b_width_log2_lookup[bsize];
6975 int bhl = b_height_log2_lookup[bsize];
6976 int tlevel = x->pred_mv_sad[ref] >> (bwl + bhl + 4);
6977
6978 if (tlevel < 5) step_param += 2;
6979
6980 // prev_mv_sad is not setup for dynamically scaled frames.
Debargha Mukherjee7166f222017-09-05 21:32:42 -07006981 if (cpi->oxcf.resize_mode != RESIZE_RANDOM) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006982 int i;
6983 for (i = LAST_FRAME; i <= ALTREF_FRAME && cm->show_frame; ++i) {
6984 if ((x->pred_mv_sad[ref] >> 3) > x->pred_mv_sad[i]) {
6985 x->pred_mv[ref].row = 0;
6986 x->pred_mv[ref].col = 0;
6987 x->best_mv.as_int = INVALID_MV;
6988
6989 if (scaled_ref_frame) {
Urvang Joshi454280d2016-10-14 16:51:44 -07006990 int j;
6991 for (j = 0; j < MAX_MB_PLANE; ++j)
6992 xd->plane[j].pre[ref_idx] = backup_yv12[j];
Yaowu Xuc27fc142016-08-22 16:08:15 -07006993 }
6994 return;
6995 }
6996 }
6997 }
6998 }
6999
Alex Converse0fa0f422017-04-24 12:51:14 -07007000 av1_set_mv_search_range(&x->mv_limits, &ref_mv);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007001
Yue Chene9638cc2016-10-10 12:37:54 -07007002#if CONFIG_MOTION_VAR
7003 if (mbmi->motion_mode != SIMPLE_TRANSLATION)
7004 mvp_full = mbmi->mv[0].as_mv;
7005 else
7006#endif // CONFIG_MOTION_VAR
7007 mvp_full = pred_mv[x->mv_best_ref_index[ref]];
Yaowu Xuc27fc142016-08-22 16:08:15 -07007008
7009 mvp_full.col >>= 3;
7010 mvp_full.row >>= 3;
7011
7012 x->best_mv.as_int = x->second_best_mv.as_int = INVALID_MV;
7013
Yue Chene9638cc2016-10-10 12:37:54 -07007014#if CONFIG_MOTION_VAR
7015 switch (mbmi->motion_mode) {
7016 case SIMPLE_TRANSLATION:
7017#endif // CONFIG_MOTION_VAR
RogerZhoucc5d35d2017-08-07 22:20:15 -07007018#if CONFIG_HASH_ME
Yue Chene9638cc2016-10-10 12:37:54 -07007019 bestsme = av1_full_pixel_search(cpi, x, bsize, &mvp_full, step_param,
7020 sadpb, cond_cost_list(cpi, cost_list),
RogerZhoucc5d35d2017-08-07 22:20:15 -07007021 &ref_mv, INT_MAX, 1, (MI_SIZE * mi_col),
RogerZhoud15e7c12017-09-26 08:49:28 -07007022 (MI_SIZE * mi_row), 0);
RogerZhoucc5d35d2017-08-07 22:20:15 -07007023#else
7024 bestsme = av1_full_pixel_search(cpi, x, bsize, &mvp_full, step_param, sadpb,
7025 cond_cost_list(cpi, cost_list), &ref_mv,
7026 INT_MAX, 1);
7027#endif
Yue Chene9638cc2016-10-10 12:37:54 -07007028#if CONFIG_MOTION_VAR
7029 break;
7030 case OBMC_CAUSAL:
7031 bestsme = av1_obmc_full_pixel_diamond(
7032 cpi, x, &mvp_full, step_param, sadpb,
7033 MAX_MVSEARCH_STEPS - 1 - step_param, 1, &cpi->fn_ptr[bsize], &ref_mv,
7034 &(x->best_mv.as_mv), 0);
7035 break;
James Zern88896732017-06-23 15:55:09 -07007036 default: assert(0 && "Invalid motion mode!\n");
Yue Chene9638cc2016-10-10 12:37:54 -07007037 }
7038#endif // CONFIG_MOTION_VAR
Yaowu Xuc27fc142016-08-22 16:08:15 -07007039
Alex Converse0fa0f422017-04-24 12:51:14 -07007040 x->mv_limits = tmp_mv_limits;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007041
RogerZhou3b635242017-09-19 10:06:46 -07007042#if CONFIG_AMVR
7043 if (cpi->common.cur_frame_mv_precision_level) {
7044 x->best_mv.as_mv.row *= 8;
7045 x->best_mv.as_mv.col *= 8;
7046 }
7047 if (bestsme < INT_MAX && cpi->common.cur_frame_mv_precision_level == 0) {
7048#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07007049 if (bestsme < INT_MAX) {
RogerZhou3b635242017-09-19 10:06:46 -07007050#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07007051 int dis; /* TODO: use dis in distortion calculation later. */
Yue Chene9638cc2016-10-10 12:37:54 -07007052#if CONFIG_MOTION_VAR
7053 switch (mbmi->motion_mode) {
7054 case SIMPLE_TRANSLATION:
7055#endif // CONFIG_MOTION_VAR
7056 if (cpi->sf.use_upsampled_references) {
7057 int best_mv_var;
7058 const int try_second = x->second_best_mv.as_int != INVALID_MV &&
7059 x->second_best_mv.as_int != x->best_mv.as_int;
Jingning Hanae5cfde2016-11-30 12:01:44 -08007060 const int pw = block_size_wide[bsize];
7061 const int ph = block_size_high[bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -07007062
Yue Chene9638cc2016-10-10 12:37:54 -07007063 best_mv_var = cpi->find_fractional_mv_step(
Yaowu Xuc27fc142016-08-22 16:08:15 -07007064 x, &ref_mv, cm->allow_high_precision_mv, x->errorperbit,
7065 &cpi->fn_ptr[bsize], cpi->sf.mv.subpel_force_stop,
7066 cpi->sf.mv.subpel_iters_per_step, cond_cost_list(cpi, cost_list),
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02007067 x->nmvjointcost, x->mvcost, &dis, &x->pred_sse[ref], NULL, NULL,
7068 0, 0, pw, ph, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007069
Yue Chene9638cc2016-10-10 12:37:54 -07007070 if (try_second) {
Alex Converse0fa0f422017-04-24 12:51:14 -07007071 const int minc =
7072 AOMMAX(x->mv_limits.col_min * 8, ref_mv.col - MV_MAX);
7073 const int maxc =
7074 AOMMIN(x->mv_limits.col_max * 8, ref_mv.col + MV_MAX);
7075 const int minr =
7076 AOMMAX(x->mv_limits.row_min * 8, ref_mv.row - MV_MAX);
7077 const int maxr =
7078 AOMMIN(x->mv_limits.row_max * 8, ref_mv.row + MV_MAX);
Yue Chene9638cc2016-10-10 12:37:54 -07007079 int this_var;
7080 MV best_mv = x->best_mv.as_mv;
7081
7082 x->best_mv = x->second_best_mv;
7083 if (x->best_mv.as_mv.row * 8 <= maxr &&
7084 x->best_mv.as_mv.row * 8 >= minr &&
7085 x->best_mv.as_mv.col * 8 <= maxc &&
7086 x->best_mv.as_mv.col * 8 >= minc) {
7087 this_var = cpi->find_fractional_mv_step(
7088 x, &ref_mv, cm->allow_high_precision_mv, x->errorperbit,
7089 &cpi->fn_ptr[bsize], cpi->sf.mv.subpel_force_stop,
7090 cpi->sf.mv.subpel_iters_per_step,
7091 cond_cost_list(cpi, cost_list), x->nmvjointcost, x->mvcost,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02007092 &dis, &x->pred_sse[ref], NULL, NULL, 0, 0, pw, ph, 1);
Yue Chene9638cc2016-10-10 12:37:54 -07007093 if (this_var < best_mv_var) best_mv = x->best_mv.as_mv;
7094 x->best_mv.as_mv = best_mv;
7095 }
7096 }
Yue Chene9638cc2016-10-10 12:37:54 -07007097 } else {
7098 cpi->find_fractional_mv_step(
7099 x, &ref_mv, cm->allow_high_precision_mv, x->errorperbit,
7100 &cpi->fn_ptr[bsize], cpi->sf.mv.subpel_force_stop,
7101 cpi->sf.mv.subpel_iters_per_step, cond_cost_list(cpi, cost_list),
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02007102 x->nmvjointcost, x->mvcost, &dis, &x->pred_sse[ref], NULL, NULL,
7103 0, 0, 0, 0, 0);
Yue Chene9638cc2016-10-10 12:37:54 -07007104 }
7105#if CONFIG_MOTION_VAR
7106 break;
7107 case OBMC_CAUSAL:
7108 av1_find_best_obmc_sub_pixel_tree_up(
Timothy B. Terriberry5d24b6f2017-06-15 13:39:35 -07007109 x, &x->best_mv.as_mv, &ref_mv, cm->allow_high_precision_mv,
7110 x->errorperbit, &cpi->fn_ptr[bsize], cpi->sf.mv.subpel_force_stop,
7111 cpi->sf.mv.subpel_iters_per_step, x->nmvjointcost, x->mvcost, &dis,
7112 &x->pred_sse[ref], 0, cpi->sf.use_upsampled_references);
Yue Chene9638cc2016-10-10 12:37:54 -07007113 break;
James Zern88896732017-06-23 15:55:09 -07007114 default: assert(0 && "Invalid motion mode!\n");
Yaowu Xuc27fc142016-08-22 16:08:15 -07007115 }
Yue Chene9638cc2016-10-10 12:37:54 -07007116#endif // CONFIG_MOTION_VAR
Yaowu Xuc27fc142016-08-22 16:08:15 -07007117 }
Yaowu Xuf883b422016-08-30 14:01:10 -07007118 *rate_mv = av1_mv_bit_cost(&x->best_mv.as_mv, &ref_mv, x->nmvjointcost,
7119 x->mvcost, MV_COST_WEIGHT);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007120
Yue Chene9638cc2016-10-10 12:37:54 -07007121#if CONFIG_MOTION_VAR
7122 if (cpi->sf.adaptive_motion_search && mbmi->motion_mode == SIMPLE_TRANSLATION)
7123#else
7124 if (cpi->sf.adaptive_motion_search)
7125#endif // CONFIG_MOTION_VAR
7126 x->pred_mv[ref] = x->best_mv.as_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007127
7128 if (scaled_ref_frame) {
7129 int i;
7130 for (i = 0; i < MAX_MB_PLANE; i++)
7131 xd->plane[i].pre[ref_idx] = backup_yv12[i];
7132 }
7133}
7134
David Barkerac37fa32016-12-02 12:30:21 +00007135static INLINE void restore_dst_buf(MACROBLOCKD *xd, BUFFER_SET dst) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07007136 int i;
7137 for (i = 0; i < MAX_MB_PLANE; i++) {
David Barkerac37fa32016-12-02 12:30:21 +00007138 xd->plane[i].dst.buf = dst.plane[i];
7139 xd->plane[i].dst.stride = dst.stride[i];
Yaowu Xuc27fc142016-08-22 16:08:15 -07007140 }
7141}
7142
David Barker8dd9b572017-05-12 16:31:38 +01007143static void build_second_inter_pred(const AV1_COMP *cpi, MACROBLOCK *x,
David Barkerf19f35f2017-05-22 16:33:22 +01007144 BLOCK_SIZE bsize, const MV *other_mv,
David Barker8dd9b572017-05-12 16:31:38 +01007145 int mi_row, int mi_col, const int block,
7146 int ref_idx, uint8_t *second_pred) {
7147 const AV1_COMMON *const cm = &cpi->common;
7148 const int pw = block_size_wide[bsize];
7149 const int ph = block_size_high[bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -07007150 MACROBLOCKD *xd = &x->e_mbd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007151 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Zoe Liu85b66462017-04-20 14:28:19 -07007152#if CONFIG_COMPOUND_SINGLEREF
7153 const int other_ref =
7154 has_second_ref(mbmi) ? mbmi->ref_frame[!ref_idx] : mbmi->ref_frame[0];
7155#else // !CONFIG_COMPOUND_SINGLEREF
David Barker8dd9b572017-05-12 16:31:38 +01007156 const int other_ref = mbmi->ref_frame[!ref_idx];
Zoe Liu85b66462017-04-20 14:28:19 -07007157#endif // CONFIG_COMPOUND_SINGLEREF
David Barker8dd9b572017-05-12 16:31:38 +01007158 struct scale_factors sf;
7159#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
7160 struct macroblockd_plane *const pd = &xd->plane[0];
James Zern89a015b2017-08-08 12:39:00 -04007161 // ic and ir are the 4x4 coordinates of the sub8x8 at index "block"
David Barker8dd9b572017-05-12 16:31:38 +01007162 const int ic = block & 1;
7163 const int ir = (block - ic) >> 1;
7164 const int p_col = ((mi_col * MI_SIZE) >> pd->subsampling_x) + 4 * ic;
7165 const int p_row = ((mi_row * MI_SIZE) >> pd->subsampling_y) + 4 * ir;
7166#if CONFIG_GLOBAL_MOTION
7167 WarpedMotionParams *const wm = &xd->global_motion[other_ref];
7168 int is_global = is_global_mv_block(xd->mi[0], block, wm->wmtype);
7169#endif // CONFIG_GLOBAL_MOTION
7170#else
7171 (void)block;
7172#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -07007173
Zoe Liu85b66462017-04-20 14:28:19 -07007174// This function should only ever be called for compound modes
7175#if CONFIG_COMPOUND_SINGLEREF
7176 assert(has_second_ref(mbmi) || is_inter_singleref_comp_mode(mbmi->mode));
7177#else // !CONFIG_COMPOUND_SINGLEREF
David Barker8dd9b572017-05-12 16:31:38 +01007178 assert(has_second_ref(mbmi));
Zoe Liu85b66462017-04-20 14:28:19 -07007179#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07007180
David Barker8dd9b572017-05-12 16:31:38 +01007181 struct buf_2d backup_yv12[MAX_MB_PLANE];
7182 const YV12_BUFFER_CONFIG *const scaled_ref_frame =
7183 av1_get_scaled_ref_frame(cpi, other_ref);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007184
7185 if (scaled_ref_frame) {
David Barker8dd9b572017-05-12 16:31:38 +01007186 int i;
7187 // Swap out the reference frame for a version that's been scaled to
7188 // match the resolution of the current frame, allowing the existing
7189 // motion search code to be used without additional modifications.
7190 for (i = 0; i < MAX_MB_PLANE; i++)
7191 backup_yv12[i] = xd->plane[i].pre[!ref_idx];
7192 av1_setup_pre_planes(xd, !ref_idx, scaled_ref_frame, mi_row, mi_col, NULL);
7193 }
7194
7195// Since we have scaled the reference frames to match the size of the current
7196// frame we must use a unit scaling factor during mode selection.
7197#if CONFIG_HIGHBITDEPTH
7198 av1_setup_scale_factors_for_frame(&sf, cm->width, cm->height, cm->width,
7199 cm->height, cm->use_highbitdepth);
7200#else
7201 av1_setup_scale_factors_for_frame(&sf, cm->width, cm->height, cm->width,
7202 cm->height);
7203#endif // CONFIG_HIGHBITDEPTH
7204
7205 struct buf_2d ref_yv12;
7206
7207 const int plane = 0;
David Barkere64d51a2017-06-09 14:52:42 +01007208 ConvolveParams conv_params = get_conv_params(!ref_idx, 0, plane);
David Barker8dd9b572017-05-12 16:31:38 +01007209#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
7210 WarpTypesAllowed warp_types;
7211#if CONFIG_GLOBAL_MOTION
7212 warp_types.global_warp_allowed = is_global;
7213#endif // CONFIG_GLOBAL_MOTION
7214#if CONFIG_WARPED_MOTION
7215 warp_types.local_warp_allowed = mbmi->motion_mode == WARPED_CAUSAL;
7216#endif // CONFIG_WARPED_MOTION
7217#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
7218
7219 // Initialized here because of compiler problem in Visual Studio.
7220 ref_yv12 = xd->plane[plane].pre[!ref_idx];
7221
7222// Get the prediction block from the 'other' reference frame.
7223#if CONFIG_HIGHBITDEPTH
7224 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
7225 av1_highbd_build_inter_predictor(
David Barkerf19f35f2017-05-22 16:33:22 +01007226 ref_yv12.buf, ref_yv12.stride, second_pred, pw, other_mv, &sf, pw, ph,
Rupert Swarbrick27e90292017-09-28 17:46:50 +01007227 0, mbmi->interp_filters,
David Barker8dd9b572017-05-12 16:31:38 +01007228#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
7229 &warp_types, p_col, p_row,
7230#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
7231 plane, MV_PRECISION_Q3, mi_col * MI_SIZE, mi_row * MI_SIZE, xd);
7232 } else {
7233#endif // CONFIG_HIGHBITDEPTH
7234 av1_build_inter_predictor(
David Barkerf19f35f2017-05-22 16:33:22 +01007235 ref_yv12.buf, ref_yv12.stride, second_pred, pw, other_mv, &sf, pw, ph,
Rupert Swarbrick27e90292017-09-28 17:46:50 +01007236 &conv_params, mbmi->interp_filters,
David Barker8dd9b572017-05-12 16:31:38 +01007237#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
7238 &warp_types, p_col, p_row, plane, !ref_idx,
7239#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
7240 MV_PRECISION_Q3, mi_col * MI_SIZE, mi_row * MI_SIZE, xd);
7241#if CONFIG_HIGHBITDEPTH
7242 }
7243#endif // CONFIG_HIGHBITDEPTH
7244
7245 if (scaled_ref_frame) {
7246 // Restore the prediction frame pointers to their unscaled versions.
7247 int i;
7248 for (i = 0; i < MAX_MB_PLANE; i++)
7249 xd->plane[i].pre[!ref_idx] = backup_yv12[i];
7250 }
7251}
7252
7253// Search for the best mv for one component of a compound,
7254// given that the other component is fixed.
Timothy B. Terriberry5d24b6f2017-06-15 13:39:35 -07007255static void compound_single_motion_search(const AV1_COMP *cpi, MACROBLOCK *x,
7256 BLOCK_SIZE bsize, MV *this_mv,
7257 int mi_row, int mi_col,
7258 const uint8_t *second_pred,
7259 const uint8_t *mask, int mask_stride,
7260 int *rate_mv, int ref_idx) {
David Barker8dd9b572017-05-12 16:31:38 +01007261 const int pw = block_size_wide[bsize];
7262 const int ph = block_size_high[bsize];
7263 MACROBLOCKD *xd = &x->e_mbd;
7264 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Zoe Liu85b66462017-04-20 14:28:19 -07007265#if CONFIG_COMPOUND_SINGLEREF
7266 const int ref =
7267 has_second_ref(mbmi) ? mbmi->ref_frame[ref_idx] : mbmi->ref_frame[0];
7268#else
David Barker8dd9b572017-05-12 16:31:38 +01007269 const int ref = mbmi->ref_frame[ref_idx];
Zoe Liu85b66462017-04-20 14:28:19 -07007270#endif // CONFIG_COMPOUND_SINGLEREF
David Barkerf19f35f2017-05-22 16:33:22 +01007271 int_mv ref_mv = x->mbmi_ext->ref_mvs[ref][0];
David Barker8dd9b572017-05-12 16:31:38 +01007272 struct macroblockd_plane *const pd = &xd->plane[0];
7273
7274 struct buf_2d backup_yv12[MAX_MB_PLANE];
David Barker8dd9b572017-05-12 16:31:38 +01007275 const YV12_BUFFER_CONFIG *const scaled_ref_frame =
7276 av1_get_scaled_ref_frame(cpi, ref);
7277
Ryan Lei1d1df182017-06-15 11:38:59 -07007278// Check that this is either an interinter or an interintra block
Zoe Liu85b66462017-04-20 14:28:19 -07007279#if CONFIG_COMPOUND_SINGLEREF
Ryan Lei1d1df182017-06-15 11:38:59 -07007280 assert(has_second_ref(mbmi) ||
Zoe Liu85b66462017-04-20 14:28:19 -07007281 // or a single ref comp pred mode
7282 is_inter_singleref_comp_mode(mbmi->mode) ||
David Barker8dd9b572017-05-12 16:31:38 +01007283 (ref_idx == 0 && mbmi->ref_frame[1] == INTRA_FRAME));
Ryan Lei1d1df182017-06-15 11:38:59 -07007284#else
7285 assert(has_second_ref(mbmi) ||
7286 (ref_idx == 0 && mbmi->ref_frame[1] == INTRA_FRAME));
7287#endif // CONFIG_COMPOUND_SINGLEREF
David Barker8dd9b572017-05-12 16:31:38 +01007288
David Barker8dd9b572017-05-12 16:31:38 +01007289 if (scaled_ref_frame) {
7290 int i;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007291 // Swap out the reference frame for a version that's been scaled to
7292 // match the resolution of the current frame, allowing the existing
7293 // motion search code to be used without additional modifications.
7294 for (i = 0; i < MAX_MB_PLANE; i++)
7295 backup_yv12[i] = xd->plane[i].pre[ref_idx];
Yaowu Xuf883b422016-08-30 14:01:10 -07007296 av1_setup_pre_planes(xd, ref_idx, scaled_ref_frame, mi_row, mi_col, NULL);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007297 }
7298
David Barker8dd9b572017-05-12 16:31:38 +01007299 struct buf_2d orig_yv12;
7300 int bestsme = INT_MAX;
7301 int sadpb = x->sadperbit16;
7302 MV *const best_mv = &x->best_mv.as_mv;
7303 int search_range = 3;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007304
David Barker8dd9b572017-05-12 16:31:38 +01007305 MvLimits tmp_mv_limits = x->mv_limits;
David Barker8dd9b572017-05-12 16:31:38 +01007306
7307 // Initialized here because of compiler problem in Visual Studio.
7308 if (ref_idx) {
David Barkerf19f35f2017-05-22 16:33:22 +01007309 orig_yv12 = pd->pre[0];
7310 pd->pre[0] = pd->pre[ref_idx];
Yaowu Xuc27fc142016-08-22 16:08:15 -07007311 }
7312
David Barker8dd9b572017-05-12 16:31:38 +01007313 // Do compound motion search on the current reference frame.
7314 av1_set_mv_search_range(&x->mv_limits, &ref_mv.as_mv);
7315
7316 // Use the mv result from the single mode as mv predictor.
David Barkerf19f35f2017-05-22 16:33:22 +01007317 *best_mv = *this_mv;
David Barker8dd9b572017-05-12 16:31:38 +01007318
7319 best_mv->col >>= 3;
7320 best_mv->row >>= 3;
7321
Zoe Liu85b66462017-04-20 14:28:19 -07007322#if CONFIG_COMPOUND_SINGLEREF
7323 if (!has_second_ref(mbmi))
7324 av1_set_mvcost(x, ref, 0, mbmi->ref_mv_idx);
7325 else
7326#endif // CONFIG_COMPOUND_SINGLEREF
7327 av1_set_mvcost(x, ref, ref_idx, mbmi->ref_mv_idx);
David Barker8dd9b572017-05-12 16:31:38 +01007328
7329 // Small-range full-pixel motion search.
7330 bestsme = av1_refining_search_8p_c(x, sadpb, search_range,
7331 &cpi->fn_ptr[bsize], mask, mask_stride,
7332 ref_idx, &ref_mv.as_mv, second_pred);
7333 if (bestsme < INT_MAX) {
7334 if (mask)
7335 bestsme =
7336 av1_get_mvpred_mask_var(x, best_mv, &ref_mv.as_mv, second_pred, mask,
7337 mask_stride, ref_idx, &cpi->fn_ptr[bsize], 1);
7338 else
7339 bestsme = av1_get_mvpred_av_var(x, best_mv, &ref_mv.as_mv, second_pred,
7340 &cpi->fn_ptr[bsize], 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007341 }
7342
Alex Converse0fa0f422017-04-24 12:51:14 -07007343 x->mv_limits = tmp_mv_limits;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007344
RogerZhou3b635242017-09-19 10:06:46 -07007345#if CONFIG_AMVR
7346 if (cpi->common.cur_frame_mv_precision_level) {
7347 x->best_mv.as_mv.row *= 8;
7348 x->best_mv.as_mv.col *= 8;
7349 }
7350 if (bestsme < INT_MAX && cpi->common.cur_frame_mv_precision_level == 0) {
7351#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07007352 if (bestsme < INT_MAX) {
RogerZhou3b635242017-09-19 10:06:46 -07007353#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07007354 int dis; /* TODO: use dis in distortion calculation later. */
David Barker8dd9b572017-05-12 16:31:38 +01007355 unsigned int sse;
Timothy B. Terriberry5d24b6f2017-06-15 13:39:35 -07007356 bestsme = cpi->find_fractional_mv_step(
7357 x, &ref_mv.as_mv, cpi->common.allow_high_precision_mv, x->errorperbit,
7358 &cpi->fn_ptr[bsize], 0, cpi->sf.mv.subpel_iters_per_step, NULL,
7359 x->nmvjointcost, x->mvcost, &dis, &sse, second_pred, mask, mask_stride,
7360 ref_idx, pw, ph, cpi->sf.use_upsampled_references);
David Barker8dd9b572017-05-12 16:31:38 +01007361 }
7362
7363 // Restore the pointer to the first (possibly scaled) prediction buffer.
David Barkerf19f35f2017-05-22 16:33:22 +01007364 if (ref_idx) pd->pre[0] = orig_yv12;
David Barker8dd9b572017-05-12 16:31:38 +01007365
Yue Chenf03907a2017-05-31 12:04:04 -07007366 if (bestsme < INT_MAX) *this_mv = *best_mv;
David Barker8dd9b572017-05-12 16:31:38 +01007367
7368 *rate_mv = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007369
7370 if (scaled_ref_frame) {
David Barker8dd9b572017-05-12 16:31:38 +01007371 // Restore the prediction frame pointers to their unscaled versions.
7372 int i;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007373 for (i = 0; i < MAX_MB_PLANE; i++)
7374 xd->plane[i].pre[ref_idx] = backup_yv12[i];
7375 }
David Barker8dd9b572017-05-12 16:31:38 +01007376
Zoe Liu85b66462017-04-20 14:28:19 -07007377#if CONFIG_COMPOUND_SINGLEREF
7378 if (!has_second_ref(mbmi))
7379 av1_set_mvcost(x, ref, 0, mbmi->ref_mv_idx);
7380 else
7381#endif // CONFIG_COMPOUND_SINGLEREF
7382 av1_set_mvcost(x, ref, ref_idx, mbmi->ref_mv_idx);
David Barkerf19f35f2017-05-22 16:33:22 +01007383 *rate_mv += av1_mv_bit_cost(this_mv, &ref_mv.as_mv, x->nmvjointcost,
7384 x->mvcost, MV_COST_WEIGHT);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007385}
7386
David Barker8dd9b572017-05-12 16:31:38 +01007387// Wrapper for compound_single_motion_search, for the common case
7388// where the second prediction is also an inter mode.
7389static void compound_single_motion_search_interinter(
7390 const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize, int_mv *frame_mv,
Zoe Liu85b66462017-04-20 14:28:19 -07007391#if CONFIG_COMPOUND_SINGLEREF
7392 int_mv *frame_comp_mv,
7393#endif // CONFIG_COMPOUND_SINGLEREF
David Barkerf19f35f2017-05-22 16:33:22 +01007394 int mi_row, int mi_col, const uint8_t *mask, int mask_stride, int *rate_mv,
7395 const int block, int ref_idx) {
7396 MACROBLOCKD *xd = &x->e_mbd;
7397 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
7398
Zoe Liu85b66462017-04-20 14:28:19 -07007399// This function should only ever be called for compound modes
7400#if CONFIG_COMPOUND_SINGLEREF
7401 int is_singleref_comp_mode =
7402 !has_second_ref(mbmi) && is_inter_singleref_comp_mode(mbmi->mode);
7403 assert(has_second_ref(mbmi) || is_singleref_comp_mode);
7404 if (is_singleref_comp_mode && ref_idx) assert(frame_comp_mv);
7405#else // !CONFIG_COMPOUND_SINGLEREF
David Barkerf19f35f2017-05-22 16:33:22 +01007406 assert(has_second_ref(mbmi));
Zoe Liu85b66462017-04-20 14:28:19 -07007407#endif // CONFIG_COMPOUND_SINGLEREF
David Barker8dd9b572017-05-12 16:31:38 +01007408
7409// Prediction buffer from second frame.
7410#if CONFIG_HIGHBITDEPTH
David Barker8dd9b572017-05-12 16:31:38 +01007411 DECLARE_ALIGNED(16, uint16_t, second_pred_alloc_16[MAX_SB_SQUARE]);
7412 uint8_t *second_pred;
7413 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
7414 second_pred = CONVERT_TO_BYTEPTR(second_pred_alloc_16);
7415 else
7416 second_pred = (uint8_t *)second_pred_alloc_16;
7417#else
7418 DECLARE_ALIGNED(16, uint8_t, second_pred[MAX_SB_SQUARE]);
7419#endif // CONFIG_HIGHBITDEPTH
7420
Zoe Liu85b66462017-04-20 14:28:19 -07007421#if CONFIG_COMPOUND_SINGLEREF
7422 MV *this_mv = has_second_ref(mbmi)
7423 ? &frame_mv[mbmi->ref_frame[ref_idx]].as_mv
7424 : (ref_idx ? &frame_comp_mv[mbmi->ref_frame[0]].as_mv
7425 : &frame_mv[mbmi->ref_frame[0]].as_mv);
7426 const MV *other_mv =
7427 has_second_ref(mbmi)
7428 ? &frame_mv[mbmi->ref_frame[!ref_idx]].as_mv
7429 : (ref_idx ? &frame_mv[mbmi->ref_frame[0]].as_mv
7430 : &frame_comp_mv[mbmi->ref_frame[0]].as_mv);
7431#else // !CONFIG_COMPOUND_SINGLEREF
David Barkerf19f35f2017-05-22 16:33:22 +01007432 MV *this_mv = &frame_mv[mbmi->ref_frame[ref_idx]].as_mv;
7433 const MV *other_mv = &frame_mv[mbmi->ref_frame[!ref_idx]].as_mv;
Zoe Liu85b66462017-04-20 14:28:19 -07007434#endif // CONFIG_COMPOUND_SINGLEREF
David Barkerf19f35f2017-05-22 16:33:22 +01007435
7436 build_second_inter_pred(cpi, x, bsize, other_mv, mi_row, mi_col, block,
David Barker8dd9b572017-05-12 16:31:38 +01007437 ref_idx, second_pred);
7438
David Barkerf19f35f2017-05-22 16:33:22 +01007439 compound_single_motion_search(cpi, x, bsize, this_mv, mi_row, mi_col,
Timothy B. Terriberry5d24b6f2017-06-15 13:39:35 -07007440 second_pred, mask, mask_stride, rate_mv,
David Barkerf19f35f2017-05-22 16:33:22 +01007441 ref_idx);
David Barker8dd9b572017-05-12 16:31:38 +01007442}
7443
7444#if CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
Sarah Parker6fdc8532016-11-16 17:47:13 -08007445static void do_masked_motion_search_indexed(
David Barkerc155e012017-05-11 13:54:54 +01007446 const AV1_COMP *const cpi, MACROBLOCK *x, const int_mv *const cur_mv,
Sarah Parkerb9f757c2017-01-06 17:12:24 -08007447 const INTERINTER_COMPOUND_DATA *const comp_data, BLOCK_SIZE bsize,
Zoe Liu7f24e1b2017-03-17 17:42:05 -07007448 int mi_row, int mi_col, int_mv *tmp_mv, int *rate_mv, int which) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07007449 // NOTE: which values: 0 - 0 only, 1 - 1 only, 2 - both
7450 MACROBLOCKD *xd = &x->e_mbd;
7451 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
7452 BLOCK_SIZE sb_type = mbmi->sb_type;
7453 const uint8_t *mask;
Jingning Hanae5cfde2016-11-30 12:01:44 -08007454 const int mask_stride = block_size_wide[bsize];
Sarah Parker569edda2016-12-14 14:57:38 -08007455
Sarah Parkerb9f757c2017-01-06 17:12:24 -08007456 mask = av1_get_compound_type_mask(comp_data, sb_type);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007457
David Barker8dd9b572017-05-12 16:31:38 +01007458 int_mv frame_mv[TOTAL_REFS_PER_FRAME];
Zoe Liu85b66462017-04-20 14:28:19 -07007459#if CONFIG_COMPOUND_SINGLEREF
7460 int_mv frame_comp_mv[TOTAL_REFS_PER_FRAME];
7461#endif // CONFIG_COMPOUND_SINGLEREF
David Barker8dd9b572017-05-12 16:31:38 +01007462 MV_REFERENCE_FRAME rf[2] = { mbmi->ref_frame[0], mbmi->ref_frame[1] };
7463 assert(bsize >= BLOCK_8X8 || CONFIG_CB4X4);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007464
David Barker8dd9b572017-05-12 16:31:38 +01007465 frame_mv[rf[0]].as_int = cur_mv[0].as_int;
Zoe Liu85b66462017-04-20 14:28:19 -07007466#if CONFIG_COMPOUND_SINGLEREF
7467 if (!has_second_ref(mbmi))
7468 frame_comp_mv[rf[0]].as_int = cur_mv[1].as_int;
7469 else
7470#endif // CONFIG_COMPOUND_SINGLEREF
7471 frame_mv[rf[1]].as_int = cur_mv[1].as_int;
David Barkerf19f35f2017-05-22 16:33:22 +01007472 if (which == 0 || which == 1) {
Zoe Liu85b66462017-04-20 14:28:19 -07007473 compound_single_motion_search_interinter(
7474 cpi, x, bsize, frame_mv,
7475#if CONFIG_COMPOUND_SINGLEREF
7476 has_second_ref(mbmi) ? NULL : frame_comp_mv,
7477#endif // CONFIG_COMPOUND_SINGLEREF
7478 mi_row, mi_col, mask, mask_stride, rate_mv, 0, which);
David Barkerf19f35f2017-05-22 16:33:22 +01007479 } else if (which == 2) {
Zoe Liu85b66462017-04-20 14:28:19 -07007480 joint_motion_search(cpi, x, bsize, frame_mv,
7481#if CONFIG_COMPOUND_SINGLEREF
7482 has_second_ref(mbmi) ? NULL : frame_comp_mv,
7483#endif // CONFIG_COMPOUND_SINGLEREF
7484 mi_row, mi_col, NULL, mask, mask_stride, rate_mv, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007485 }
David Barker8dd9b572017-05-12 16:31:38 +01007486 tmp_mv[0].as_int = frame_mv[rf[0]].as_int;
Zoe Liu85b66462017-04-20 14:28:19 -07007487#if CONFIG_COMPOUND_SINGLEREF
7488 if (!has_second_ref(mbmi))
7489 tmp_mv[1].as_int = frame_comp_mv[rf[0]].as_int;
7490 else // comp ref
7491#endif // CONFIG_COMPOUND_SINGLEREF
7492 tmp_mv[1].as_int = frame_mv[rf[1]].as_int;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007493}
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00007494#endif // CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
Yaowu Xuc27fc142016-08-22 16:08:15 -07007495
James Zern89a015b2017-08-08 12:39:00 -04007496// In some situations we want to discount the apparent cost of a new motion
Yaowu Xuc27fc142016-08-22 16:08:15 -07007497// vector. Where there is a subtle motion field and especially where there is
7498// low spatial complexity then it can be hard to cover the cost of a new motion
7499// vector in a single block, even if that motion vector reduces distortion.
7500// However, once established that vector may be usable through the nearest and
7501// near mv modes to reduce distortion in subsequent blocks and also improve
7502// visual quality.
Urvang Joshi52648442016-10-13 17:27:51 -07007503static int discount_newmv_test(const AV1_COMP *const cpi, int this_mode,
Yaowu Xuc27fc142016-08-22 16:08:15 -07007504 int_mv this_mv,
7505 int_mv (*mode_mv)[TOTAL_REFS_PER_FRAME],
7506 int ref_frame) {
7507 return (!cpi->rc.is_src_frame_alt_ref && (this_mode == NEWMV) &&
7508 (this_mv.as_int != 0) &&
7509 ((mode_mv[NEARESTMV][ref_frame].as_int == 0) ||
7510 (mode_mv[NEARESTMV][ref_frame].as_int == INVALID_MV)) &&
7511 ((mode_mv[NEARMV][ref_frame].as_int == 0) ||
7512 (mode_mv[NEARMV][ref_frame].as_int == INVALID_MV)));
7513}
7514
Yaowu Xu671f2bd2016-09-30 15:07:57 -07007515#define LEFT_TOP_MARGIN ((AOM_BORDER_IN_PIXELS - AOM_INTERP_EXTEND) << 3)
7516#define RIGHT_BOTTOM_MARGIN ((AOM_BORDER_IN_PIXELS - AOM_INTERP_EXTEND) << 3)
Yaowu Xuc27fc142016-08-22 16:08:15 -07007517
7518// TODO(jingning): this mv clamping function should be block size dependent.
7519static INLINE void clamp_mv2(MV *mv, const MACROBLOCKD *xd) {
7520 clamp_mv(mv, xd->mb_to_left_edge - LEFT_TOP_MARGIN,
7521 xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
7522 xd->mb_to_top_edge - LEFT_TOP_MARGIN,
7523 xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN);
7524}
7525
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00007526#if CONFIG_WEDGE
Yaowu Xuf883b422016-08-30 14:01:10 -07007527static int estimate_wedge_sign(const AV1_COMP *cpi, const MACROBLOCK *x,
Yaowu Xuc27fc142016-08-22 16:08:15 -07007528 const BLOCK_SIZE bsize, const uint8_t *pred0,
7529 int stride0, const uint8_t *pred1, int stride1) {
7530 const struct macroblock_plane *const p = &x->plane[0];
7531 const uint8_t *src = p->src.buf;
7532 int src_stride = p->src.stride;
7533 const int f_index = bsize - BLOCK_8X8;
Jingning Han61418bb2017-01-23 17:12:48 -08007534 const int bw = block_size_wide[bsize];
7535 const int bh = block_size_high[bsize];
Yue Chenf03907a2017-05-31 12:04:04 -07007536 uint32_t esq[2][4];
Yaowu Xuc27fc142016-08-22 16:08:15 -07007537 int64_t tl, br;
7538
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007539#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07007540 if (x->e_mbd.cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
7541 pred0 = CONVERT_TO_BYTEPTR(pred0);
7542 pred1 = CONVERT_TO_BYTEPTR(pred1);
7543 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007544#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07007545
Yue Chenf03907a2017-05-31 12:04:04 -07007546 cpi->fn_ptr[f_index].vf(src, src_stride, pred0, stride0, &esq[0][0]);
7547 cpi->fn_ptr[f_index].vf(src + bw / 2, src_stride, pred0 + bw / 2, stride0,
7548 &esq[0][1]);
7549 cpi->fn_ptr[f_index].vf(src + bh / 2 * src_stride, src_stride,
7550 pred0 + bh / 2 * stride0, stride0, &esq[0][2]);
7551 cpi->fn_ptr[f_index].vf(src + bh / 2 * src_stride + bw / 2, src_stride,
7552 pred0 + bh / 2 * stride0 + bw / 2, stride0,
7553 &esq[0][3]);
7554 cpi->fn_ptr[f_index].vf(src, src_stride, pred1, stride1, &esq[1][0]);
7555 cpi->fn_ptr[f_index].vf(src + bw / 2, src_stride, pred1 + bw / 2, stride1,
7556 &esq[1][1]);
7557 cpi->fn_ptr[f_index].vf(src + bh / 2 * src_stride, src_stride,
7558 pred1 + bh / 2 * stride1, stride0, &esq[1][2]);
7559 cpi->fn_ptr[f_index].vf(src + bh / 2 * src_stride + bw / 2, src_stride,
7560 pred1 + bh / 2 * stride1 + bw / 2, stride0,
7561 &esq[1][3]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007562
7563 tl = (int64_t)(esq[0][0] + esq[0][1] + esq[0][2]) -
7564 (int64_t)(esq[1][0] + esq[1][1] + esq[1][2]);
7565 br = (int64_t)(esq[1][3] + esq[1][1] + esq[1][2]) -
7566 (int64_t)(esq[0][3] + esq[0][1] + esq[0][2]);
7567 return (tl + br > 0);
7568}
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00007569#endif // CONFIG_WEDGE
Yaowu Xuc27fc142016-08-22 16:08:15 -07007570
7571#if !CONFIG_DUAL_FILTER
James Zern7b9407a2016-05-18 23:48:05 -07007572static InterpFilter predict_interp_filter(
Yaowu Xuf883b422016-08-30 14:01:10 -07007573 const AV1_COMP *cpi, const MACROBLOCK *x, const BLOCK_SIZE bsize,
Yaowu Xuc27fc142016-08-22 16:08:15 -07007574 const int mi_row, const int mi_col,
James Zern7b9407a2016-05-18 23:48:05 -07007575 InterpFilter (*single_filter)[TOTAL_REFS_PER_FRAME]) {
7576 InterpFilter best_filter = SWITCHABLE;
Yaowu Xuf883b422016-08-30 14:01:10 -07007577 const AV1_COMMON *cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007578 const MACROBLOCKD *xd = &x->e_mbd;
7579 int bsl = mi_width_log2_lookup[bsize];
7580 int pred_filter_search =
7581 cpi->sf.cb_pred_filter_search
7582 ? (((mi_row + mi_col) >> bsl) +
7583 get_chessboard_index(cm->current_video_frame)) &
7584 0x1
7585 : 0;
7586 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
7587 const int is_comp_pred = has_second_ref(mbmi);
7588 const int this_mode = mbmi->mode;
7589 int refs[2] = { mbmi->ref_frame[0],
7590 (mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]) };
Yaowu Xuc27fc142016-08-22 16:08:15 -07007591 if (pred_filter_search) {
James Zern7b9407a2016-05-18 23:48:05 -07007592 InterpFilter af = SWITCHABLE, lf = SWITCHABLE;
Rupert Swarbrick27e90292017-09-28 17:46:50 +01007593 if (xd->up_available)
7594 af = av1_extract_interp_filter(
7595 xd->mi[-xd->mi_stride]->mbmi.interp_filters, 0);
7596 if (xd->left_available)
7597 lf = av1_extract_interp_filter(xd->mi[-1]->mbmi.interp_filters, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007598
Zoe Liu7f24e1b2017-03-17 17:42:05 -07007599 if ((this_mode != NEWMV && this_mode != NEW_NEWMV) || (af == lf))
Yaowu Xuc27fc142016-08-22 16:08:15 -07007600 best_filter = af;
7601 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07007602 if (is_comp_pred) {
7603 if (cpi->sf.adaptive_mode_search) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07007604 switch (this_mode) {
7605 case NEAREST_NEARESTMV:
7606 if (single_filter[NEARESTMV][refs[0]] ==
7607 single_filter[NEARESTMV][refs[1]])
7608 best_filter = single_filter[NEARESTMV][refs[0]];
7609 break;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007610 case NEAR_NEARMV:
7611 if (single_filter[NEARMV][refs[0]] == single_filter[NEARMV][refs[1]])
7612 best_filter = single_filter[NEARMV][refs[0]];
7613 break;
7614 case ZERO_ZEROMV:
7615 if (single_filter[ZEROMV][refs[0]] == single_filter[ZEROMV][refs[1]])
7616 best_filter = single_filter[ZEROMV][refs[0]];
7617 break;
7618 case NEW_NEWMV:
7619 if (single_filter[NEWMV][refs[0]] == single_filter[NEWMV][refs[1]])
7620 best_filter = single_filter[NEWMV][refs[0]];
7621 break;
7622 case NEAREST_NEWMV:
7623 if (single_filter[NEARESTMV][refs[0]] ==
7624 single_filter[NEWMV][refs[1]])
7625 best_filter = single_filter[NEARESTMV][refs[0]];
7626 break;
7627 case NEAR_NEWMV:
7628 if (single_filter[NEARMV][refs[0]] == single_filter[NEWMV][refs[1]])
7629 best_filter = single_filter[NEARMV][refs[0]];
7630 break;
7631 case NEW_NEARESTMV:
7632 if (single_filter[NEWMV][refs[0]] ==
7633 single_filter[NEARESTMV][refs[1]])
7634 best_filter = single_filter[NEWMV][refs[0]];
7635 break;
7636 case NEW_NEARMV:
7637 if (single_filter[NEWMV][refs[0]] == single_filter[NEARMV][refs[1]])
7638 best_filter = single_filter[NEWMV][refs[0]];
7639 break;
7640 default:
7641 if (single_filter[this_mode][refs[0]] ==
7642 single_filter[this_mode][refs[1]])
7643 best_filter = single_filter[this_mode][refs[0]];
7644 break;
7645 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07007646 }
7647 }
Angie Chiang75c22092016-10-25 12:19:16 -07007648 if (x->source_variance < cpi->sf.disable_filter_search_var_thresh) {
7649 best_filter = EIGHTTAP_REGULAR;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007650 }
7651 return best_filter;
7652}
Fergus Simpson4063a682017-02-28 16:52:22 -08007653#endif // !CONFIG_DUAL_FILTER
Yaowu Xuc27fc142016-08-22 16:08:15 -07007654
Yaowu Xuc27fc142016-08-22 16:08:15 -07007655// Choose the best wedge index and sign
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00007656#if CONFIG_WEDGE
Yaowu Xuf883b422016-08-30 14:01:10 -07007657static int64_t pick_wedge(const AV1_COMP *const cpi, const MACROBLOCK *const x,
Yaowu Xuc27fc142016-08-22 16:08:15 -07007658 const BLOCK_SIZE bsize, const uint8_t *const p0,
7659 const uint8_t *const p1, int *const best_wedge_sign,
7660 int *const best_wedge_index) {
7661 const MACROBLOCKD *const xd = &x->e_mbd;
7662 const struct buf_2d *const src = &x->plane[0].src;
Jingning Hanae5cfde2016-11-30 12:01:44 -08007663 const int bw = block_size_wide[bsize];
7664 const int bh = block_size_high[bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -07007665 const int N = bw * bh;
7666 int rate;
7667 int64_t dist;
7668 int64_t rd, best_rd = INT64_MAX;
7669 int wedge_index;
7670 int wedge_sign;
7671 int wedge_types = (1 << get_wedge_bits_lookup(bsize));
7672 const uint8_t *mask;
7673 uint64_t sse;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007674#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07007675 const int hbd = xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH;
7676 const int bd_round = hbd ? (xd->bd - 8) * 2 : 0;
7677#else
7678 const int bd_round = 0;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007679#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07007680
7681 DECLARE_ALIGNED(32, int16_t, r0[MAX_SB_SQUARE]);
7682 DECLARE_ALIGNED(32, int16_t, r1[MAX_SB_SQUARE]);
7683 DECLARE_ALIGNED(32, int16_t, d10[MAX_SB_SQUARE]);
7684 DECLARE_ALIGNED(32, int16_t, ds[MAX_SB_SQUARE]);
7685
7686 int64_t sign_limit;
7687
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007688#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07007689 if (hbd) {
Yaowu Xuf883b422016-08-30 14:01:10 -07007690 aom_highbd_subtract_block(bh, bw, r0, bw, src->buf, src->stride,
Yaowu Xuc27fc142016-08-22 16:08:15 -07007691 CONVERT_TO_BYTEPTR(p0), bw, xd->bd);
Yaowu Xuf883b422016-08-30 14:01:10 -07007692 aom_highbd_subtract_block(bh, bw, r1, bw, src->buf, src->stride,
Yaowu Xuc27fc142016-08-22 16:08:15 -07007693 CONVERT_TO_BYTEPTR(p1), bw, xd->bd);
Yaowu Xuf883b422016-08-30 14:01:10 -07007694 aom_highbd_subtract_block(bh, bw, d10, bw, CONVERT_TO_BYTEPTR(p1), bw,
Yaowu Xuc27fc142016-08-22 16:08:15 -07007695 CONVERT_TO_BYTEPTR(p0), bw, xd->bd);
7696 } else // NOLINT
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007697#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07007698 {
Yaowu Xuf883b422016-08-30 14:01:10 -07007699 aom_subtract_block(bh, bw, r0, bw, src->buf, src->stride, p0, bw);
7700 aom_subtract_block(bh, bw, r1, bw, src->buf, src->stride, p1, bw);
7701 aom_subtract_block(bh, bw, d10, bw, p1, bw, p0, bw);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007702 }
7703
Yaowu Xuf883b422016-08-30 14:01:10 -07007704 sign_limit = ((int64_t)aom_sum_squares_i16(r0, N) -
7705 (int64_t)aom_sum_squares_i16(r1, N)) *
Yaowu Xuc27fc142016-08-22 16:08:15 -07007706 (1 << WEDGE_WEIGHT_BITS) / 2;
7707
Jingning Han61418bb2017-01-23 17:12:48 -08007708 if (N < 64)
7709 av1_wedge_compute_delta_squares_c(ds, r0, r1, N);
7710 else
7711 av1_wedge_compute_delta_squares(ds, r0, r1, N);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007712
7713 for (wedge_index = 0; wedge_index < wedge_types; ++wedge_index) {
Yaowu Xuf883b422016-08-30 14:01:10 -07007714 mask = av1_get_contiguous_soft_mask(wedge_index, 0, bsize);
Jingning Han61418bb2017-01-23 17:12:48 -08007715
7716 // TODO(jingning): Make sse2 functions support N = 16 case
7717 if (N < 64)
7718 wedge_sign = av1_wedge_sign_from_residuals_c(ds, mask, N, sign_limit);
7719 else
7720 wedge_sign = av1_wedge_sign_from_residuals(ds, mask, N, sign_limit);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007721
Yaowu Xuf883b422016-08-30 14:01:10 -07007722 mask = av1_get_contiguous_soft_mask(wedge_index, wedge_sign, bsize);
Jingning Han61418bb2017-01-23 17:12:48 -08007723 if (N < 64)
7724 sse = av1_wedge_sse_from_residuals_c(r1, d10, mask, N);
7725 else
7726 sse = av1_wedge_sse_from_residuals(r1, d10, mask, N);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007727 sse = ROUND_POWER_OF_TWO(sse, bd_round);
7728
7729 model_rd_from_sse(cpi, xd, bsize, 0, sse, &rate, &dist);
Urvang Joshi70006e42017-06-14 16:08:55 -07007730 rd = RDCOST(x->rdmult, rate, dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007731
7732 if (rd < best_rd) {
7733 *best_wedge_index = wedge_index;
7734 *best_wedge_sign = wedge_sign;
7735 best_rd = rd;
7736 }
7737 }
7738
7739 return best_rd;
7740}
7741
7742// Choose the best wedge index the specified sign
7743static int64_t pick_wedge_fixed_sign(
Yaowu Xuf883b422016-08-30 14:01:10 -07007744 const AV1_COMP *const cpi, const MACROBLOCK *const x,
Yaowu Xuc27fc142016-08-22 16:08:15 -07007745 const BLOCK_SIZE bsize, const uint8_t *const p0, const uint8_t *const p1,
7746 const int wedge_sign, int *const best_wedge_index) {
7747 const MACROBLOCKD *const xd = &x->e_mbd;
7748 const struct buf_2d *const src = &x->plane[0].src;
Jingning Hanae5cfde2016-11-30 12:01:44 -08007749 const int bw = block_size_wide[bsize];
7750 const int bh = block_size_high[bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -07007751 const int N = bw * bh;
7752 int rate;
7753 int64_t dist;
7754 int64_t rd, best_rd = INT64_MAX;
7755 int wedge_index;
7756 int wedge_types = (1 << get_wedge_bits_lookup(bsize));
7757 const uint8_t *mask;
7758 uint64_t sse;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007759#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07007760 const int hbd = xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH;
7761 const int bd_round = hbd ? (xd->bd - 8) * 2 : 0;
7762#else
7763 const int bd_round = 0;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007764#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07007765
7766 DECLARE_ALIGNED(32, int16_t, r1[MAX_SB_SQUARE]);
7767 DECLARE_ALIGNED(32, int16_t, d10[MAX_SB_SQUARE]);
7768
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007769#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07007770 if (hbd) {
Yaowu Xuf883b422016-08-30 14:01:10 -07007771 aom_highbd_subtract_block(bh, bw, r1, bw, src->buf, src->stride,
Yaowu Xuc27fc142016-08-22 16:08:15 -07007772 CONVERT_TO_BYTEPTR(p1), bw, xd->bd);
Yaowu Xuf883b422016-08-30 14:01:10 -07007773 aom_highbd_subtract_block(bh, bw, d10, bw, CONVERT_TO_BYTEPTR(p1), bw,
Yaowu Xuc27fc142016-08-22 16:08:15 -07007774 CONVERT_TO_BYTEPTR(p0), bw, xd->bd);
7775 } else // NOLINT
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007776#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07007777 {
Yaowu Xuf883b422016-08-30 14:01:10 -07007778 aom_subtract_block(bh, bw, r1, bw, src->buf, src->stride, p1, bw);
7779 aom_subtract_block(bh, bw, d10, bw, p1, bw, p0, bw);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007780 }
7781
7782 for (wedge_index = 0; wedge_index < wedge_types; ++wedge_index) {
Yaowu Xuf883b422016-08-30 14:01:10 -07007783 mask = av1_get_contiguous_soft_mask(wedge_index, wedge_sign, bsize);
Jingning Han61418bb2017-01-23 17:12:48 -08007784 if (N < 64)
7785 sse = av1_wedge_sse_from_residuals_c(r1, d10, mask, N);
7786 else
7787 sse = av1_wedge_sse_from_residuals(r1, d10, mask, N);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007788 sse = ROUND_POWER_OF_TWO(sse, bd_round);
7789
7790 model_rd_from_sse(cpi, xd, bsize, 0, sse, &rate, &dist);
Urvang Joshi70006e42017-06-14 16:08:55 -07007791 rd = RDCOST(x->rdmult, rate, dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007792
7793 if (rd < best_rd) {
7794 *best_wedge_index = wedge_index;
7795 best_rd = rd;
7796 }
7797 }
7798
7799 return best_rd;
7800}
7801
Yaowu Xuf883b422016-08-30 14:01:10 -07007802static int64_t pick_interinter_wedge(const AV1_COMP *const cpi,
Sarah Parker2d0e9b72017-05-04 01:34:16 +00007803 MACROBLOCK *const x,
Yaowu Xuc27fc142016-08-22 16:08:15 -07007804 const BLOCK_SIZE bsize,
7805 const uint8_t *const p0,
7806 const uint8_t *const p1) {
Sarah Parker2d0e9b72017-05-04 01:34:16 +00007807 MACROBLOCKD *const xd = &x->e_mbd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007808 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Jingning Hanae5cfde2016-11-30 12:01:44 -08007809 const int bw = block_size_wide[bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -07007810
7811 int64_t rd;
7812 int wedge_index = -1;
7813 int wedge_sign = 0;
7814
Sarah Parker42d96102017-01-31 21:05:27 -08007815 assert(is_interinter_compound_used(COMPOUND_WEDGE, bsize));
Debargha Mukherjee9e2c7a62017-05-23 21:18:42 -07007816 assert(cpi->common.allow_masked_compound);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007817
7818 if (cpi->sf.fast_wedge_sign_estimate) {
7819 wedge_sign = estimate_wedge_sign(cpi, x, bsize, p0, bw, p1, bw);
7820 rd = pick_wedge_fixed_sign(cpi, x, bsize, p0, p1, wedge_sign, &wedge_index);
7821 } else {
7822 rd = pick_wedge(cpi, x, bsize, p0, p1, &wedge_sign, &wedge_index);
7823 }
7824
Sarah Parker2d0e9b72017-05-04 01:34:16 +00007825 mbmi->wedge_sign = wedge_sign;
7826 mbmi->wedge_index = wedge_index;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007827 return rd;
7828}
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00007829#endif // CONFIG_WEDGE
Yaowu Xuc27fc142016-08-22 16:08:15 -07007830
Sarah Parker569edda2016-12-14 14:57:38 -08007831#if CONFIG_COMPOUND_SEGMENT
Sarah Parkerddcea392017-04-25 15:57:22 -07007832static int64_t pick_interinter_seg(const AV1_COMP *const cpi,
Sarah Parker2d0e9b72017-05-04 01:34:16 +00007833 MACROBLOCK *const x, const BLOCK_SIZE bsize,
Sarah Parkerddcea392017-04-25 15:57:22 -07007834 const uint8_t *const p0,
7835 const uint8_t *const p1) {
Sarah Parker2d0e9b72017-05-04 01:34:16 +00007836 MACROBLOCKD *const xd = &x->e_mbd;
Sarah Parker569edda2016-12-14 14:57:38 -08007837 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
7838 const struct buf_2d *const src = &x->plane[0].src;
7839 const int bw = block_size_wide[bsize];
7840 const int bh = block_size_high[bsize];
7841 const int N = bw * bh;
7842 int rate;
7843 uint64_t sse;
7844 int64_t dist;
Debargha Mukherjeec30934b2017-04-25 01:23:51 -07007845 int64_t rd0;
Sarah Parkerb9f757c2017-01-06 17:12:24 -08007846 SEG_MASK_TYPE cur_mask_type;
7847 int64_t best_rd = INT64_MAX;
7848 SEG_MASK_TYPE best_mask_type = 0;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007849#if CONFIG_HIGHBITDEPTH
Sarah Parker569edda2016-12-14 14:57:38 -08007850 const int hbd = xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH;
7851 const int bd_round = hbd ? (xd->bd - 8) * 2 : 0;
7852#else
7853 const int bd_round = 0;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007854#endif // CONFIG_HIGHBITDEPTH
Sarah Parker569edda2016-12-14 14:57:38 -08007855 DECLARE_ALIGNED(32, int16_t, r0[MAX_SB_SQUARE]);
7856 DECLARE_ALIGNED(32, int16_t, r1[MAX_SB_SQUARE]);
7857 DECLARE_ALIGNED(32, int16_t, d10[MAX_SB_SQUARE]);
7858
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007859#if CONFIG_HIGHBITDEPTH
Sarah Parker569edda2016-12-14 14:57:38 -08007860 if (hbd) {
7861 aom_highbd_subtract_block(bh, bw, r0, bw, src->buf, src->stride,
7862 CONVERT_TO_BYTEPTR(p0), bw, xd->bd);
7863 aom_highbd_subtract_block(bh, bw, r1, bw, src->buf, src->stride,
7864 CONVERT_TO_BYTEPTR(p1), bw, xd->bd);
7865 aom_highbd_subtract_block(bh, bw, d10, bw, CONVERT_TO_BYTEPTR(p1), bw,
7866 CONVERT_TO_BYTEPTR(p0), bw, xd->bd);
7867 } else // NOLINT
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007868#endif // CONFIG_HIGHBITDEPTH
Sarah Parker569edda2016-12-14 14:57:38 -08007869 {
7870 aom_subtract_block(bh, bw, r0, bw, src->buf, src->stride, p0, bw);
7871 aom_subtract_block(bh, bw, r1, bw, src->buf, src->stride, p1, bw);
7872 aom_subtract_block(bh, bw, d10, bw, p1, bw, p0, bw);
7873 }
7874
Sarah Parkerb9f757c2017-01-06 17:12:24 -08007875 // try each mask type and its inverse
7876 for (cur_mask_type = 0; cur_mask_type < SEG_MASK_TYPES; cur_mask_type++) {
Debargha Mukherjee1edf9a32017-01-07 18:54:20 -08007877// build mask and inverse
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007878#if CONFIG_HIGHBITDEPTH
Debargha Mukherjee1edf9a32017-01-07 18:54:20 -08007879 if (hbd)
7880 build_compound_seg_mask_highbd(
Sarah Parker2d0e9b72017-05-04 01:34:16 +00007881 xd->seg_mask, cur_mask_type, CONVERT_TO_BYTEPTR(p0), bw,
Debargha Mukherjee1edf9a32017-01-07 18:54:20 -08007882 CONVERT_TO_BYTEPTR(p1), bw, bsize, bh, bw, xd->bd);
7883 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007884#endif // CONFIG_HIGHBITDEPTH
Sarah Parker2d0e9b72017-05-04 01:34:16 +00007885 build_compound_seg_mask(xd->seg_mask, cur_mask_type, p0, bw, p1, bw,
7886 bsize, bh, bw);
Sarah Parker569edda2016-12-14 14:57:38 -08007887
Sarah Parkerb9f757c2017-01-06 17:12:24 -08007888 // compute rd for mask
Sarah Parker2d0e9b72017-05-04 01:34:16 +00007889 sse = av1_wedge_sse_from_residuals(r1, d10, xd->seg_mask, N);
Sarah Parkerb9f757c2017-01-06 17:12:24 -08007890 sse = ROUND_POWER_OF_TWO(sse, bd_round);
Sarah Parker569edda2016-12-14 14:57:38 -08007891
Sarah Parkerb9f757c2017-01-06 17:12:24 -08007892 model_rd_from_sse(cpi, xd, bsize, 0, sse, &rate, &dist);
Urvang Joshi70006e42017-06-14 16:08:55 -07007893 rd0 = RDCOST(x->rdmult, rate, dist);
Sarah Parker569edda2016-12-14 14:57:38 -08007894
Sarah Parkerb9f757c2017-01-06 17:12:24 -08007895 if (rd0 < best_rd) {
7896 best_mask_type = cur_mask_type;
7897 best_rd = rd0;
7898 }
7899 }
Sarah Parker569edda2016-12-14 14:57:38 -08007900
Sarah Parkerb9f757c2017-01-06 17:12:24 -08007901 // make final mask
Sarah Parker2d0e9b72017-05-04 01:34:16 +00007902 mbmi->mask_type = best_mask_type;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007903#if CONFIG_HIGHBITDEPTH
Debargha Mukherjee1edf9a32017-01-07 18:54:20 -08007904 if (hbd)
7905 build_compound_seg_mask_highbd(
Sarah Parker2d0e9b72017-05-04 01:34:16 +00007906 xd->seg_mask, mbmi->mask_type, CONVERT_TO_BYTEPTR(p0), bw,
Debargha Mukherjee1edf9a32017-01-07 18:54:20 -08007907 CONVERT_TO_BYTEPTR(p1), bw, bsize, bh, bw, xd->bd);
7908 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007909#endif // CONFIG_HIGHBITDEPTH
Sarah Parker2d0e9b72017-05-04 01:34:16 +00007910 build_compound_seg_mask(xd->seg_mask, mbmi->mask_type, p0, bw, p1, bw,
7911 bsize, bh, bw);
Sarah Parker569edda2016-12-14 14:57:38 -08007912
Sarah Parkerb9f757c2017-01-06 17:12:24 -08007913 return best_rd;
Sarah Parker569edda2016-12-14 14:57:38 -08007914}
7915#endif // CONFIG_COMPOUND_SEGMENT
7916
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00007917#if CONFIG_WEDGE && CONFIG_INTERINTRA
Yaowu Xuf883b422016-08-30 14:01:10 -07007918static int64_t pick_interintra_wedge(const AV1_COMP *const cpi,
Yaowu Xuc27fc142016-08-22 16:08:15 -07007919 const MACROBLOCK *const x,
7920 const BLOCK_SIZE bsize,
7921 const uint8_t *const p0,
7922 const uint8_t *const p1) {
7923 const MACROBLOCKD *const xd = &x->e_mbd;
7924 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
7925
7926 int64_t rd;
7927 int wedge_index = -1;
7928
7929 assert(is_interintra_wedge_used(bsize));
Debargha Mukherjee9e2c7a62017-05-23 21:18:42 -07007930 assert(cpi->common.allow_interintra_compound);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007931
7932 rd = pick_wedge_fixed_sign(cpi, x, bsize, p0, p1, 0, &wedge_index);
7933
7934 mbmi->interintra_wedge_sign = 0;
7935 mbmi->interintra_wedge_index = wedge_index;
7936 return rd;
7937}
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00007938#endif // CONFIG_WEDGE && CONFIG_INTERINTRA
Sarah Parker6fdc8532016-11-16 17:47:13 -08007939
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00007940#if CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
Sarah Parker2d0e9b72017-05-04 01:34:16 +00007941static int64_t pick_interinter_mask(const AV1_COMP *const cpi, MACROBLOCK *x,
Sarah Parkerddcea392017-04-25 15:57:22 -07007942 const BLOCK_SIZE bsize,
7943 const uint8_t *const p0,
7944 const uint8_t *const p1) {
7945 const COMPOUND_TYPE compound_type =
Sarah Parker2d0e9b72017-05-04 01:34:16 +00007946 x->e_mbd.mi[0]->mbmi.interinter_compound_type;
Sarah Parkerddcea392017-04-25 15:57:22 -07007947 switch (compound_type) {
7948#if CONFIG_WEDGE
7949 case COMPOUND_WEDGE: return pick_interinter_wedge(cpi, x, bsize, p0, p1);
7950#endif // CONFIG_WEDGE
7951#if CONFIG_COMPOUND_SEGMENT
7952 case COMPOUND_SEG: return pick_interinter_seg(cpi, x, bsize, p0, p1);
7953#endif // CONFIG_COMPOUND_SEGMENT
7954 default: assert(0); return 0;
7955 }
7956}
7957
David Barkerc155e012017-05-11 13:54:54 +01007958static int interinter_compound_motion_search(
7959 const AV1_COMP *const cpi, MACROBLOCK *x, const int_mv *const cur_mv,
7960 const BLOCK_SIZE bsize, const int this_mode, int mi_row, int mi_col) {
Sarah Parker2d0e9b72017-05-04 01:34:16 +00007961 MACROBLOCKD *const xd = &x->e_mbd;
Sarah Parker6fdc8532016-11-16 17:47:13 -08007962 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
7963 int_mv tmp_mv[2];
David Barkerc155e012017-05-11 13:54:54 +01007964 int tmp_rate_mv = 0;
Sarah Parker2d0e9b72017-05-04 01:34:16 +00007965 const INTERINTER_COMPOUND_DATA compound_data = {
7966#if CONFIG_WEDGE
7967 mbmi->wedge_index,
7968 mbmi->wedge_sign,
7969#endif // CONFIG_WEDGE
7970#if CONFIG_COMPOUND_SEGMENT
7971 mbmi->mask_type,
7972 xd->seg_mask,
7973#endif // CONFIG_COMPOUND_SEGMENT
7974 mbmi->interinter_compound_type
7975 };
Zoe Liu85b66462017-04-20 14:28:19 -07007976#if CONFIG_COMPOUND_SINGLEREF
7977 // NOTE: Mode is needed to identify the compound mode prediction, regardless
7978 // of comp refs or single ref.
7979 mbmi->mode = this_mode;
7980#endif // CONFIG_COMPOUND_SINGLEREF
7981
7982 if (this_mode == NEW_NEWMV
7983#if CONFIG_COMPOUND_SINGLEREF
7984 || this_mode == SR_NEW_NEWMV
7985#endif // CONFIG_COMPOUND_SINGLEREF
7986 ) {
David Barkerc155e012017-05-11 13:54:54 +01007987 do_masked_motion_search_indexed(cpi, x, cur_mv, &compound_data, bsize,
7988 mi_row, mi_col, tmp_mv, &tmp_rate_mv, 2);
Sarah Parker6fdc8532016-11-16 17:47:13 -08007989 mbmi->mv[0].as_int = tmp_mv[0].as_int;
7990 mbmi->mv[1].as_int = tmp_mv[1].as_int;
7991 } else if (this_mode == NEW_NEARESTMV || this_mode == NEW_NEARMV) {
David Barkerc155e012017-05-11 13:54:54 +01007992 do_masked_motion_search_indexed(cpi, x, cur_mv, &compound_data, bsize,
7993 mi_row, mi_col, tmp_mv, &tmp_rate_mv, 0);
Sarah Parker6fdc8532016-11-16 17:47:13 -08007994 mbmi->mv[0].as_int = tmp_mv[0].as_int;
Zoe Liu85b66462017-04-20 14:28:19 -07007995 } else if (this_mode == NEAREST_NEWMV || this_mode == NEAR_NEWMV
7996#if CONFIG_COMPOUND_SINGLEREF
7997 // || this_mode == SR_NEAREST_NEWMV
7998 || this_mode == SR_NEAR_NEWMV || this_mode == SR_ZERO_NEWMV
7999#endif // CONFIG_COMPOUND_SINGLEREF
8000 ) {
David Barkerc155e012017-05-11 13:54:54 +01008001 do_masked_motion_search_indexed(cpi, x, cur_mv, &compound_data, bsize,
8002 mi_row, mi_col, tmp_mv, &tmp_rate_mv, 1);
Sarah Parker6fdc8532016-11-16 17:47:13 -08008003 mbmi->mv[1].as_int = tmp_mv[1].as_int;
8004 }
8005 return tmp_rate_mv;
8006}
8007
Sarah Parkerddcea392017-04-25 15:57:22 -07008008static int64_t build_and_cost_compound_type(
Sarah Parker569edda2016-12-14 14:57:38 -08008009 const AV1_COMP *const cpi, MACROBLOCK *x, const int_mv *const cur_mv,
8010 const BLOCK_SIZE bsize, const int this_mode, int rs2, int rate_mv,
8011 BUFFER_SET *ctx, int *out_rate_mv, uint8_t **preds0, uint8_t **preds1,
8012 int *strides, int mi_row, int mi_col) {
Debargha Mukherjeead8be032017-05-09 15:28:45 -07008013 const AV1_COMMON *const cm = &cpi->common;
Sarah Parker569edda2016-12-14 14:57:38 -08008014 MACROBLOCKD *xd = &x->e_mbd;
8015 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
8016 int rate_sum;
8017 int64_t dist_sum;
8018 int64_t best_rd_cur = INT64_MAX;
8019 int64_t rd = INT64_MAX;
8020 int tmp_skip_txfm_sb;
8021 int64_t tmp_skip_sse_sb;
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008022 const COMPOUND_TYPE compound_type = mbmi->interinter_compound_type;
Sarah Parker569edda2016-12-14 14:57:38 -08008023
Sarah Parkerddcea392017-04-25 15:57:22 -07008024 best_rd_cur = pick_interinter_mask(cpi, x, bsize, *preds0, *preds1);
Urvang Joshi70006e42017-06-14 16:08:55 -07008025 best_rd_cur += RDCOST(x->rdmult, rs2 + rate_mv, 0);
Sarah Parker569edda2016-12-14 14:57:38 -08008026
Sarah Parker2e604882017-01-17 17:31:25 -08008027 if (have_newmv_in_inter_mode(this_mode) &&
Sarah Parkerddcea392017-04-25 15:57:22 -07008028 use_masked_motion_search(compound_type)) {
David Barkerc155e012017-05-11 13:54:54 +01008029 *out_rate_mv = interinter_compound_motion_search(cpi, x, cur_mv, bsize,
8030 this_mode, mi_row, mi_col);
Debargha Mukherjeead8be032017-05-09 15:28:45 -07008031 av1_build_inter_predictors_sby(cm, xd, mi_row, mi_col, ctx, bsize);
Sarah Parker6fdc8532016-11-16 17:47:13 -08008032 model_rd_for_sb(cpi, bsize, x, xd, 0, 0, &rate_sum, &dist_sum,
8033 &tmp_skip_txfm_sb, &tmp_skip_sse_sb);
Urvang Joshi70006e42017-06-14 16:08:55 -07008034 rd = RDCOST(x->rdmult, rs2 + *out_rate_mv + rate_sum, dist_sum);
Zoe Liu4d44f5a2016-12-14 17:46:19 -08008035 if (rd >= best_rd_cur) {
Sarah Parker6fdc8532016-11-16 17:47:13 -08008036 mbmi->mv[0].as_int = cur_mv[0].as_int;
8037 mbmi->mv[1].as_int = cur_mv[1].as_int;
8038 *out_rate_mv = rate_mv;
David Barker426a9972017-01-27 11:03:11 +00008039 av1_build_wedge_inter_predictor_from_buf(xd, bsize, 0, 0,
8040#if CONFIG_SUPERTX
8041 0, 0,
8042#endif // CONFIG_SUPERTX
8043 preds0, strides, preds1,
8044 strides);
Sarah Parker6fdc8532016-11-16 17:47:13 -08008045 }
8046 av1_subtract_plane(x, bsize, 0);
8047 rd = estimate_yrd_for_sb(cpi, bsize, x, &rate_sum, &dist_sum,
8048 &tmp_skip_txfm_sb, &tmp_skip_sse_sb, INT64_MAX);
8049 if (rd != INT64_MAX)
Urvang Joshi70006e42017-06-14 16:08:55 -07008050 rd = RDCOST(x->rdmult, rs2 + *out_rate_mv + rate_sum, dist_sum);
Sarah Parker6fdc8532016-11-16 17:47:13 -08008051 best_rd_cur = rd;
8052
8053 } else {
David Barker426a9972017-01-27 11:03:11 +00008054 av1_build_wedge_inter_predictor_from_buf(xd, bsize, 0, 0,
8055#if CONFIG_SUPERTX
8056 0, 0,
8057#endif // CONFIG_SUPERTX
8058 preds0, strides, preds1, strides);
Sarah Parker6fdc8532016-11-16 17:47:13 -08008059 av1_subtract_plane(x, bsize, 0);
8060 rd = estimate_yrd_for_sb(cpi, bsize, x, &rate_sum, &dist_sum,
8061 &tmp_skip_txfm_sb, &tmp_skip_sse_sb, INT64_MAX);
8062 if (rd != INT64_MAX)
Urvang Joshi70006e42017-06-14 16:08:55 -07008063 rd = RDCOST(x->rdmult, rs2 + rate_mv + rate_sum, dist_sum);
Sarah Parker6fdc8532016-11-16 17:47:13 -08008064 best_rd_cur = rd;
8065 }
8066 return best_rd_cur;
8067}
Sarah Parkerddcea392017-04-25 15:57:22 -07008068#endif // CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
Yaowu Xuc27fc142016-08-22 16:08:15 -07008069
Fergus Simpson073c6f32017-02-17 12:13:48 -08008070typedef struct {
8071#if CONFIG_MOTION_VAR
8072 // Inter prediction buffers and respective strides
8073 uint8_t *above_pred_buf[MAX_MB_PLANE];
8074 int above_pred_stride[MAX_MB_PLANE];
8075 uint8_t *left_pred_buf[MAX_MB_PLANE];
8076 int left_pred_stride[MAX_MB_PLANE];
8077#endif // CONFIG_MOTION_VAR
Zoe Liu7f24e1b2017-03-17 17:42:05 -07008078 int_mv *single_newmv;
Fergus Simpson073c6f32017-02-17 12:13:48 -08008079 // Pointer to array of motion vectors to use for each ref and their rates
8080 // Should point to first of 2 arrays in 2D array
Zoe Liu7f24e1b2017-03-17 17:42:05 -07008081 int *single_newmv_rate;
Fergus Simpson073c6f32017-02-17 12:13:48 -08008082 // Pointer to array of predicted rate-distortion
8083 // Should point to first of 2 arrays in 2D array
8084 int64_t (*modelled_rd)[TOTAL_REFS_PER_FRAME];
Fergus Simpson3424c2d2017-03-09 11:48:15 -08008085 InterpFilter single_filter[MB_MODE_COUNT][TOTAL_REFS_PER_FRAME];
Fergus Simpson073c6f32017-02-17 12:13:48 -08008086} HandleInterModeArgs;
8087
Fergus Simpson45509632017-02-22 15:30:50 -08008088static int64_t handle_newmv(const AV1_COMP *const cpi, MACROBLOCK *const x,
8089 const BLOCK_SIZE bsize,
8090 int_mv (*const mode_mv)[TOTAL_REFS_PER_FRAME],
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008091#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008092 int_mv (*const mode_comp_mv)[TOTAL_REFS_PER_FRAME],
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008093#endif // CONFIG_COMPOUND_SINGLEREF
Fergus Simpson45509632017-02-22 15:30:50 -08008094 const int mi_row, const int mi_col,
8095 int *const rate_mv, int_mv *const single_newmv,
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -08008096 HandleInterModeArgs *const args) {
Fergus Simpson45509632017-02-22 15:30:50 -08008097 const MACROBLOCKD *const xd = &x->e_mbd;
8098 const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
8099 const MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
8100 const int is_comp_pred = has_second_ref(mbmi);
8101 const PREDICTION_MODE this_mode = mbmi->mode;
Fergus Simpson45509632017-02-22 15:30:50 -08008102 const int is_comp_interintra_pred = (mbmi->ref_frame[1] == INTRA_FRAME);
Fergus Simpson45509632017-02-22 15:30:50 -08008103 int_mv *const frame_mv = mode_mv[this_mode];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008104#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008105 int_mv *const frame_comp_mv = mode_comp_mv[this_mode];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008106#endif // CONFIG_COMPOUND_SINGLEREF
Fergus Simpson45509632017-02-22 15:30:50 -08008107 const int refs[2] = { mbmi->ref_frame[0],
8108 mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1] };
8109 int i;
8110
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -08008111 (void)args;
Fergus Simpson45509632017-02-22 15:30:50 -08008112
8113 if (is_comp_pred) {
Fergus Simpson45509632017-02-22 15:30:50 -08008114 for (i = 0; i < 2; ++i) {
Zoe Liu7f24e1b2017-03-17 17:42:05 -07008115 single_newmv[refs[i]].as_int = args->single_newmv[refs[i]].as_int;
Fergus Simpson45509632017-02-22 15:30:50 -08008116 }
8117
8118 if (this_mode == NEW_NEWMV) {
8119 frame_mv[refs[0]].as_int = single_newmv[refs[0]].as_int;
8120 frame_mv[refs[1]].as_int = single_newmv[refs[1]].as_int;
8121
8122 if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
Zoe Liu85b66462017-04-20 14:28:19 -07008123 joint_motion_search(cpi, x, bsize, frame_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008124#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008125 NULL, // int_mv *frame_comp_mv
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008126#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008127 mi_row, mi_col, NULL, NULL, 0, rate_mv, 0);
Fergus Simpson45509632017-02-22 15:30:50 -08008128 } else {
8129 *rate_mv = 0;
8130 for (i = 0; i < 2; ++i) {
Zoe Liu122f3942017-04-25 11:18:38 -07008131 av1_set_mvcost(x, refs[i], i, mbmi->ref_mv_idx);
Fergus Simpson45509632017-02-22 15:30:50 -08008132 *rate_mv += av1_mv_bit_cost(
8133 &frame_mv[refs[i]].as_mv, &mbmi_ext->ref_mvs[refs[i]][0].as_mv,
8134 x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
8135 }
8136 }
8137 } else if (this_mode == NEAREST_NEWMV || this_mode == NEAR_NEWMV) {
8138 frame_mv[refs[1]].as_int = single_newmv[refs[1]].as_int;
David Barker8dd9b572017-05-12 16:31:38 +01008139 if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
8140 frame_mv[refs[0]].as_int =
8141 mode_mv[compound_ref0_mode(this_mode)][refs[0]].as_int;
Zoe Liu85b66462017-04-20 14:28:19 -07008142 compound_single_motion_search_interinter(cpi, x, bsize, frame_mv,
8143#if CONFIG_COMPOUND_SINGLEREF
8144 NULL,
8145#endif // CONFIG_COMPOUND_SINGLEREF
8146 mi_row, mi_col, NULL, 0,
8147 rate_mv, 0, 1);
David Barker8dd9b572017-05-12 16:31:38 +01008148 } else {
8149 av1_set_mvcost(x, refs[1], 1, mbmi->ref_mv_idx);
8150 *rate_mv = av1_mv_bit_cost(&frame_mv[refs[1]].as_mv,
8151 &mbmi_ext->ref_mvs[refs[1]][0].as_mv,
8152 x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
8153 }
Fergus Simpson45509632017-02-22 15:30:50 -08008154 } else {
David Barkercb03dc32017-04-07 13:05:09 +01008155 assert(this_mode == NEW_NEARESTMV || this_mode == NEW_NEARMV);
Fergus Simpson45509632017-02-22 15:30:50 -08008156 frame_mv[refs[0]].as_int = single_newmv[refs[0]].as_int;
David Barker8dd9b572017-05-12 16:31:38 +01008157 if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
8158 frame_mv[refs[1]].as_int =
8159 mode_mv[compound_ref1_mode(this_mode)][refs[1]].as_int;
Zoe Liu85b66462017-04-20 14:28:19 -07008160 compound_single_motion_search_interinter(cpi, x, bsize, frame_mv,
8161#if CONFIG_COMPOUND_SINGLEREF
8162 NULL,
8163#endif // CONFIG_COMPOUND_SINGLEREF
8164 mi_row, mi_col, NULL, 0,
8165 rate_mv, 0, 0);
David Barker8dd9b572017-05-12 16:31:38 +01008166 } else {
8167 av1_set_mvcost(x, refs[0], 0, mbmi->ref_mv_idx);
8168 *rate_mv = av1_mv_bit_cost(&frame_mv[refs[0]].as_mv,
8169 &mbmi_ext->ref_mvs[refs[0]][0].as_mv,
8170 x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
8171 }
Fergus Simpson45509632017-02-22 15:30:50 -08008172 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008173#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008174 } else if (is_inter_singleref_comp_mode(this_mode)) {
8175 // Single ref comp mode
8176 const int mode0 = compound_ref0_mode(this_mode);
8177
8178 single_newmv[refs[0]].as_int = args->single_newmv[refs[0]].as_int;
8179 frame_mv[refs[0]].as_int = (mode0 == NEWMV)
8180 ? single_newmv[refs[0]].as_int
8181 : mode_mv[mode0][refs[0]].as_int;
8182 assert(compound_ref1_mode(this_mode) == NEWMV);
8183 frame_comp_mv[refs[0]].as_int = single_newmv[refs[0]].as_int;
8184
8185 if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
8186 if (this_mode == SR_NEW_NEWMV) {
8187 joint_motion_search(cpi, x, bsize, frame_mv, frame_comp_mv, mi_row,
8188 mi_col, NULL, NULL, 0, rate_mv, 0);
8189 } else {
8190 assert( // this_mode == SR_NEAREST_NEWMV ||
8191 this_mode == SR_NEAR_NEWMV || this_mode == SR_ZERO_NEWMV);
8192 compound_single_motion_search_interinter(cpi, x, bsize, frame_mv,
8193 frame_comp_mv, mi_row, mi_col,
8194 NULL, 0, rate_mv, 0, 1);
8195 }
8196 } else {
8197 *rate_mv = 0;
8198 av1_set_mvcost(x, refs[0], 0, mbmi->ref_mv_idx);
8199 if (mode0 == NEWMV)
8200 *rate_mv += av1_mv_bit_cost(&frame_mv[refs[0]].as_mv,
8201 &mbmi_ext->ref_mvs[refs[0]][0].as_mv,
8202 x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
8203 *rate_mv += av1_mv_bit_cost(&frame_comp_mv[refs[0]].as_mv,
8204 &mbmi_ext->ref_mvs[refs[0]][0].as_mv,
8205 x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
8206 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008207#endif // CONFIG_COMPOUND_SINGLEREF
Fergus Simpson45509632017-02-22 15:30:50 -08008208 } else {
Fergus Simpson45509632017-02-22 15:30:50 -08008209 if (is_comp_interintra_pred) {
Zoe Liu7f24e1b2017-03-17 17:42:05 -07008210 x->best_mv = args->single_newmv[refs[0]];
8211 *rate_mv = args->single_newmv_rate[refs[0]];
Fergus Simpson45509632017-02-22 15:30:50 -08008212 } else {
Zoe Liu7f24e1b2017-03-17 17:42:05 -07008213 single_motion_search(cpi, x, bsize, mi_row, mi_col, 0, rate_mv);
8214 args->single_newmv[refs[0]] = x->best_mv;
8215 args->single_newmv_rate[refs[0]] = *rate_mv;
Fergus Simpson45509632017-02-22 15:30:50 -08008216 }
Fergus Simpson45509632017-02-22 15:30:50 -08008217
8218 if (x->best_mv.as_int == INVALID_MV) return INT64_MAX;
8219
8220 frame_mv[refs[0]] = x->best_mv;
8221 xd->mi[0]->bmi[0].as_mv[0] = x->best_mv;
8222
8223 // Estimate the rate implications of a new mv but discount this
8224 // under certain circumstances where we want to help initiate a weak
8225 // motion field, where the distortion gain for a single block may not
8226 // be enough to overcome the cost of a new mv.
8227 if (discount_newmv_test(cpi, this_mode, x->best_mv, mode_mv, refs[0])) {
8228 *rate_mv = AOMMAX(*rate_mv / NEW_MV_DISCOUNT_FACTOR, 1);
8229 }
8230 }
8231
8232 return 0;
8233}
8234
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008235int64_t interpolation_filter_search(
8236 MACROBLOCK *const x, const AV1_COMP *const cpi, BLOCK_SIZE bsize,
8237 int mi_row, int mi_col, const BUFFER_SET *const tmp_dst,
8238 BUFFER_SET *const orig_dst,
8239 InterpFilter (*const single_filter)[TOTAL_REFS_PER_FRAME],
8240 int64_t *const rd, int *const switchable_rate, int *const skip_txfm_sb,
8241 int64_t *const skip_sse_sb) {
8242 const AV1_COMMON *cm = &cpi->common;
8243 MACROBLOCKD *const xd = &x->e_mbd;
8244 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
8245 int i;
8246 int tmp_rate;
8247 int64_t tmp_dist;
8248
8249 (void)single_filter;
8250
8251 InterpFilter assign_filter = SWITCHABLE;
8252
8253 if (cm->interp_filter == SWITCHABLE) {
8254#if !CONFIG_DUAL_FILTER
Debargha Mukherjee0df711f2017-05-02 16:00:20 -07008255 assign_filter = av1_is_interp_needed(xd)
8256 ? predict_interp_filter(cpi, x, bsize, mi_row, mi_col,
8257 single_filter)
8258 : cm->interp_filter;
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008259#endif // !CONFIG_DUAL_FILTER
8260 } else {
8261 assign_filter = cm->interp_filter;
8262 }
8263
Debargha Mukherjee0df711f2017-05-02 16:00:20 -07008264 set_default_interp_filters(mbmi, assign_filter);
8265
Yue Chenb23d00a2017-07-28 17:01:21 -07008266 *switchable_rate = av1_get_switchable_rate(cm, x, xd);
Jingning Hanc44009c2017-05-06 11:36:49 -07008267 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, orig_dst, bsize);
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008268 model_rd_for_sb(cpi, bsize, x, xd, 0, MAX_MB_PLANE - 1, &tmp_rate, &tmp_dist,
8269 skip_txfm_sb, skip_sse_sb);
Urvang Joshi70006e42017-06-14 16:08:55 -07008270 *rd = RDCOST(x->rdmult, *switchable_rate + tmp_rate, tmp_dist);
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008271
8272 if (assign_filter == SWITCHABLE) {
8273 // do interp_filter search
Debargha Mukherjee0df711f2017-05-02 16:00:20 -07008274 if (av1_is_interp_needed(xd) && av1_is_interp_search_needed(xd)) {
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008275#if CONFIG_DUAL_FILTER
8276 const int filter_set_size = DUAL_FILTER_SET_SIZE;
8277#else
8278 const int filter_set_size = SWITCHABLE_FILTERS;
8279#endif // CONFIG_DUAL_FILTER
8280 int best_in_temp = 0;
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008281 InterpFilters best_filters = mbmi->interp_filters;
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008282 restore_dst_buf(xd, *tmp_dst);
8283 // EIGHTTAP_REGULAR mode is calculated beforehand
8284 for (i = 1; i < filter_set_size; ++i) {
8285 int tmp_skip_sb = 0;
8286 int64_t tmp_skip_sse = INT64_MAX;
8287 int tmp_rs;
8288 int64_t tmp_rd;
8289#if CONFIG_DUAL_FILTER
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008290 mbmi->interp_filters =
8291 av1_make_interp_filters(filter_sets[i][0], filter_sets[i][1]);
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008292#else
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008293 mbmi->interp_filters = av1_broadcast_interp_filter((InterpFilter)i);
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008294#endif // CONFIG_DUAL_FILTER
Yue Chenb23d00a2017-07-28 17:01:21 -07008295 tmp_rs = av1_get_switchable_rate(cm, x, xd);
Jingning Hanc44009c2017-05-06 11:36:49 -07008296 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, orig_dst, bsize);
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008297 model_rd_for_sb(cpi, bsize, x, xd, 0, MAX_MB_PLANE - 1, &tmp_rate,
8298 &tmp_dist, &tmp_skip_sb, &tmp_skip_sse);
Urvang Joshi70006e42017-06-14 16:08:55 -07008299 tmp_rd = RDCOST(x->rdmult, tmp_rs + tmp_rate, tmp_dist);
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008300
8301 if (tmp_rd < *rd) {
8302 *rd = tmp_rd;
Yue Chenb23d00a2017-07-28 17:01:21 -07008303 *switchable_rate = av1_get_switchable_rate(cm, x, xd);
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008304 best_filters = mbmi->interp_filters;
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008305 *skip_txfm_sb = tmp_skip_sb;
8306 *skip_sse_sb = tmp_skip_sse;
8307 best_in_temp = !best_in_temp;
8308 if (best_in_temp) {
8309 restore_dst_buf(xd, *orig_dst);
8310 } else {
8311 restore_dst_buf(xd, *tmp_dst);
8312 }
8313 }
8314 }
8315 if (best_in_temp) {
8316 restore_dst_buf(xd, *tmp_dst);
8317 } else {
8318 restore_dst_buf(xd, *orig_dst);
8319 }
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008320 mbmi->interp_filters = best_filters;
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008321 } else {
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008322 assert(mbmi->interp_filters ==
8323 av1_broadcast_interp_filter(EIGHTTAP_REGULAR));
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008324 }
8325 }
8326
8327 return 0;
8328}
8329
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008330#if CONFIG_DUAL_FILTER
8331static InterpFilters condition_interp_filters_on_mv(
8332 InterpFilters interp_filters, const MACROBLOCKD *xd) {
8333 InterpFilter filters[2];
8334 for (int i = 0; i < 2; ++i)
8335 filters[i] = (has_subpel_mv_component(xd->mi[0], xd, i))
8336 ? av1_extract_interp_filter(interp_filters, i)
8337 : EIGHTTAP_REGULAR;
8338
8339 return av1_make_interp_filters(filters[0], filters[1]);
8340}
8341#endif
8342
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008343// TODO(afergs): Refactor the MBMI references in here - there's four
8344// TODO(afergs): Refactor optional args - add them to a struct or remove
8345static int64_t motion_mode_rd(
8346 const AV1_COMP *const cpi, MACROBLOCK *const x, BLOCK_SIZE bsize,
8347 RD_STATS *rd_stats, RD_STATS *rd_stats_y, RD_STATS *rd_stats_uv,
8348 int *disable_skip, int_mv (*mode_mv)[TOTAL_REFS_PER_FRAME], int mi_row,
8349 int mi_col, HandleInterModeArgs *const args, const int64_t ref_best_rd,
8350 const int *refs, int rate_mv,
8351#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Wei-Ting Lin85a8f702017-06-22 13:55:15 -07008352 // only used when WARPED_MOTION is on?
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008353 int_mv *const single_newmv, int rate2_bmc_nocoeff,
8354 MB_MODE_INFO *best_bmc_mbmi, int rate_mv_bmc,
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008355#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8356 int rs, int *skip_txfm_sb, int64_t *skip_sse_sb, BUFFER_SET *orig_dst) {
8357 const AV1_COMMON *const cm = &cpi->common;
8358 MACROBLOCKD *xd = &x->e_mbd;
8359 MODE_INFO *mi = xd->mi[0];
8360 MB_MODE_INFO *mbmi = &mi->mbmi;
8361 const int is_comp_pred = has_second_ref(mbmi);
8362 const PREDICTION_MODE this_mode = mbmi->mode;
8363
8364 (void)mode_mv;
8365 (void)mi_row;
8366 (void)mi_col;
8367 (void)args;
8368 (void)refs;
8369 (void)rate_mv;
8370 (void)is_comp_pred;
8371 (void)this_mode;
Angie Chiangcf85d5c2017-08-20 12:56:19 -07008372#if !CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR
Cheng Chen811bba72017-08-21 17:39:31 -07008373 (void)single_newmv;
8374#endif
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008375
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008376#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8377 MOTION_MODE motion_mode, last_motion_mode_allowed;
8378 int rate2_nocoeff = 0, best_xskip, best_disable_skip = 0;
8379 RD_STATS best_rd_stats, best_rd_stats_y, best_rd_stats_uv;
8380 MB_MODE_INFO base_mbmi, best_mbmi;
8381#if CONFIG_VAR_TX
8382 uint8_t best_blk_skip[MAX_MB_PLANE][MAX_MIB_SIZE * MAX_MIB_SIZE * 4];
8383#endif // CONFIG_VAR_TX
8384#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8385
8386#if CONFIG_WARPED_MOTION
Yunqing Wang1bc82862017-06-28 15:49:48 -07008387#if WARPED_MOTION_SORT_SAMPLES
8388 int pts0[SAMPLES_ARRAY_SIZE], pts_inref0[SAMPLES_ARRAY_SIZE];
8389 int pts_mv0[SAMPLES_ARRAY_SIZE];
8390 int total_samples;
8391#else
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008392 int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
Yunqing Wang1bc82862017-06-28 15:49:48 -07008393#endif // WARPED_MOTION_SORT_SAMPLES
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008394#endif // CONFIG_WARPED_MOTION
8395
8396#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8397 av1_invalid_rd_stats(&best_rd_stats);
8398#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8399
8400 if (cm->interp_filter == SWITCHABLE) rd_stats->rate += rs;
8401#if CONFIG_WARPED_MOTION
8402 aom_clear_system_state();
Yunqing Wang1bc82862017-06-28 15:49:48 -07008403#if WARPED_MOTION_SORT_SAMPLES
8404 mbmi->num_proj_ref[0] =
8405 findSamples(cm, xd, mi_row, mi_col, pts0, pts_inref0, pts_mv0);
8406 total_samples = mbmi->num_proj_ref[0];
8407#else
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008408 mbmi->num_proj_ref[0] = findSamples(cm, xd, mi_row, mi_col, pts, pts_inref);
Yunqing Wang1bc82862017-06-28 15:49:48 -07008409#endif // WARPED_MOTION_SORT_SAMPLES
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008410 best_bmc_mbmi->num_proj_ref[0] = mbmi->num_proj_ref[0];
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008411#endif // CONFIG_WARPED_MOTION
8412#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8413 rate2_nocoeff = rd_stats->rate;
8414 last_motion_mode_allowed = motion_mode_allowed(
Sarah Parker0eea89f2017-07-11 11:56:36 -07008415#if CONFIG_GLOBAL_MOTION
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008416 0, xd->global_motion,
Sarah Parker0eea89f2017-07-11 11:56:36 -07008417#endif // CONFIG_GLOBAL_MOTION
Yue Chen52c51732017-07-11 15:08:30 -07008418#if CONFIG_WARPED_MOTION
8419 xd,
8420#endif
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008421 mi);
8422 base_mbmi = *mbmi;
8423#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8424
8425#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8426 int64_t best_rd = INT64_MAX;
8427 for (motion_mode = SIMPLE_TRANSLATION;
8428 motion_mode <= last_motion_mode_allowed; motion_mode++) {
8429 int64_t tmp_rd = INT64_MAX;
8430 int tmp_rate;
8431 int64_t tmp_dist;
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008432 int tmp_rate2 =
8433 motion_mode != SIMPLE_TRANSLATION ? rate2_bmc_nocoeff : rate2_nocoeff;
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008434
Wei-Ting Lin20885282017-08-28 17:18:18 -07008435#if CONFIG_NCOBMC_ADAPT_WEIGHT
8436 // We cannot estimate the rd cost for the motion mode NCOBMC_ADAPT_WEIGHT
8437 // right now since it requires mvs from all neighboring blocks. We will
8438 // check if this mode is beneficial after all the mv's in the current
8439 // superblock are selected.
8440 if (motion_mode == NCOBMC_ADAPT_WEIGHT) continue;
8441#endif
8442
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008443 *mbmi = base_mbmi;
8444 mbmi->motion_mode = motion_mode;
8445#if CONFIG_MOTION_VAR
8446 if (mbmi->motion_mode == OBMC_CAUSAL) {
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008447 *mbmi = *best_bmc_mbmi;
8448 mbmi->motion_mode = OBMC_CAUSAL;
Zoe Liu85b66462017-04-20 14:28:19 -07008449 if (!is_comp_pred &&
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008450#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008451 !is_inter_singleref_comp_mode(this_mode) &&
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008452#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008453 have_newmv_in_inter_mode(this_mode)) {
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008454 int tmp_rate_mv = 0;
8455
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008456 single_motion_search(cpi, x, bsize, mi_row, mi_col, 0, &tmp_rate_mv);
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008457 mbmi->mv[0].as_int = x->best_mv.as_int;
8458 if (discount_newmv_test(cpi, this_mode, mbmi->mv[0], mode_mv,
8459 refs[0])) {
8460 tmp_rate_mv = AOMMAX((tmp_rate_mv / NEW_MV_DISCOUNT_FACTOR), 1);
8461 }
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008462 tmp_rate2 = rate2_bmc_nocoeff - rate_mv_bmc + tmp_rate_mv;
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008463#if CONFIG_DUAL_FILTER
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008464 mbmi->interp_filters =
8465 condition_interp_filters_on_mv(mbmi->interp_filters, xd);
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008466#endif // CONFIG_DUAL_FILTER
Jingning Hanc44009c2017-05-06 11:36:49 -07008467 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, orig_dst, bsize);
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008468 } else {
Jingning Hanc44009c2017-05-06 11:36:49 -07008469 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, orig_dst, bsize);
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008470 }
8471 av1_build_obmc_inter_prediction(
8472 cm, xd, mi_row, mi_col, args->above_pred_buf, args->above_pred_stride,
8473 args->left_pred_buf, args->left_pred_stride);
8474 model_rd_for_sb(cpi, bsize, x, xd, 0, MAX_MB_PLANE - 1, &tmp_rate,
8475 &tmp_dist, skip_txfm_sb, skip_sse_sb);
8476 }
8477#endif // CONFIG_MOTION_VAR
8478
8479#if CONFIG_WARPED_MOTION
8480 if (mbmi->motion_mode == WARPED_CAUSAL) {
Yunqing Wang1bc82862017-06-28 15:49:48 -07008481#if WARPED_MOTION_SORT_SAMPLES
8482 int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
8483#endif // WARPED_MOTION_SORT_SAMPLES
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008484 *mbmi = *best_bmc_mbmi;
8485 mbmi->motion_mode = WARPED_CAUSAL;
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008486 mbmi->wm_params[0].wmtype = DEFAULT_WMTYPE;
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008487 mbmi->interp_filters = av1_broadcast_interp_filter(
8488 av1_unswitchable_filter(cm->interp_filter));
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008489
Yunqing Wang1bc82862017-06-28 15:49:48 -07008490#if WARPED_MOTION_SORT_SAMPLES
8491 memcpy(pts, pts0, total_samples * 2 * sizeof(*pts0));
8492 memcpy(pts_inref, pts_inref0, total_samples * 2 * sizeof(*pts_inref0));
8493 // Rank the samples by motion vector difference
8494 if (mbmi->num_proj_ref[0] > 1) {
8495 mbmi->num_proj_ref[0] = sortSamples(pts_mv0, &mbmi->mv[0].as_mv, pts,
8496 pts_inref, mbmi->num_proj_ref[0]);
Yunqing Wang1bc82862017-06-28 15:49:48 -07008497 best_bmc_mbmi->num_proj_ref[0] = mbmi->num_proj_ref[0];
Yunqing Wang1bc82862017-06-28 15:49:48 -07008498 }
8499#endif // WARPED_MOTION_SORT_SAMPLES
8500
Yunqing Wang68f3ccd2017-05-23 14:43:54 -07008501 if (!find_projection(mbmi->num_proj_ref[0], pts, pts_inref, bsize,
8502 mbmi->mv[0].as_mv.row, mbmi->mv[0].as_mv.col,
8503 &mbmi->wm_params[0], mi_row, mi_col)) {
8504 // Refine MV for NEWMV mode
8505 if (!is_comp_pred && have_newmv_in_inter_mode(this_mode)) {
8506 int tmp_rate_mv = 0;
8507 const int_mv mv0 = mbmi->mv[0];
8508 WarpedMotionParams wm_params0 = mbmi->wm_params[0];
Yunqing Wang1bc82862017-06-28 15:49:48 -07008509#if WARPED_MOTION_SORT_SAMPLES
8510 int num_proj_ref0 = mbmi->num_proj_ref[0];
Yunqing Wang68f3ccd2017-05-23 14:43:54 -07008511
8512 // Refine MV in a small range.
Yunqing Wang1bc82862017-06-28 15:49:48 -07008513 av1_refine_warped_mv(cpi, x, bsize, mi_row, mi_col, pts0, pts_inref0,
8514 pts_mv0, total_samples);
8515#else
8516 // Refine MV in a small range.
Yunqing Wang68f3ccd2017-05-23 14:43:54 -07008517 av1_refine_warped_mv(cpi, x, bsize, mi_row, mi_col, pts, pts_inref);
Yunqing Wang1bc82862017-06-28 15:49:48 -07008518#endif // WARPED_MOTION_SORT_SAMPLES
Yunqing Wang68f3ccd2017-05-23 14:43:54 -07008519
8520 // Keep the refined MV and WM parameters.
8521 if (mv0.as_int != mbmi->mv[0].as_int) {
8522 const int ref = refs[0];
8523 const MV ref_mv = x->mbmi_ext->ref_mvs[ref][0].as_mv;
8524
8525 tmp_rate_mv =
8526 av1_mv_bit_cost(&mbmi->mv[0].as_mv, &ref_mv, x->nmvjointcost,
8527 x->mvcost, MV_COST_WEIGHT);
8528
8529 if (cpi->sf.adaptive_motion_search)
8530 x->pred_mv[ref] = mbmi->mv[0].as_mv;
8531
8532 single_newmv[ref] = mbmi->mv[0];
8533
8534 if (discount_newmv_test(cpi, this_mode, mbmi->mv[0], mode_mv,
8535 refs[0])) {
8536 tmp_rate_mv = AOMMAX((tmp_rate_mv / NEW_MV_DISCOUNT_FACTOR), 1);
8537 }
Yunqing Wang1bc82862017-06-28 15:49:48 -07008538#if WARPED_MOTION_SORT_SAMPLES
8539 best_bmc_mbmi->num_proj_ref[0] = mbmi->num_proj_ref[0];
8540#endif // WARPED_MOTION_SORT_SAMPLES
Yunqing Wang68f3ccd2017-05-23 14:43:54 -07008541 tmp_rate2 = rate2_bmc_nocoeff - rate_mv_bmc + tmp_rate_mv;
Yunqing Wang68f3ccd2017-05-23 14:43:54 -07008542#if CONFIG_DUAL_FILTER
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008543 mbmi->interp_filters =
8544 condition_interp_filters_on_mv(mbmi->interp_filters, xd);
Yunqing Wang68f3ccd2017-05-23 14:43:54 -07008545#endif // CONFIG_DUAL_FILTER
8546 } else {
8547 // Restore the old MV and WM parameters.
8548 mbmi->mv[0] = mv0;
8549 mbmi->wm_params[0] = wm_params0;
Yunqing Wang1bc82862017-06-28 15:49:48 -07008550#if WARPED_MOTION_SORT_SAMPLES
8551 mbmi->num_proj_ref[0] = num_proj_ref0;
8552#endif // WARPED_MOTION_SORT_SAMPLES
Yunqing Wang68f3ccd2017-05-23 14:43:54 -07008553 }
8554 }
8555
Jingning Hanc44009c2017-05-06 11:36:49 -07008556 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, NULL, bsize);
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008557 model_rd_for_sb(cpi, bsize, x, xd, 0, MAX_MB_PLANE - 1, &tmp_rate,
8558 &tmp_dist, skip_txfm_sb, skip_sse_sb);
8559 } else {
8560 continue;
8561 }
8562 }
8563#endif // CONFIG_WARPED_MOTION
8564 x->skip = 0;
8565
8566 rd_stats->dist = 0;
8567 rd_stats->sse = 0;
8568 rd_stats->skip = 1;
8569 rd_stats->rate = tmp_rate2;
8570 if (last_motion_mode_allowed > SIMPLE_TRANSLATION) {
8571#if CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR
8572 if (last_motion_mode_allowed == WARPED_CAUSAL)
8573#endif // CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR
Yue Chenbdc8dab2017-07-26 12:05:47 -07008574 rd_stats->rate += x->motion_mode_cost[bsize][mbmi->motion_mode];
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008575#if CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR
8576 else
Yue Chenb23d00a2017-07-28 17:01:21 -07008577 rd_stats->rate += x->motion_mode_cost1[bsize][mbmi->motion_mode];
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008578#endif // CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR
8579 }
8580#if CONFIG_WARPED_MOTION
8581 if (mbmi->motion_mode == WARPED_CAUSAL) {
8582 rd_stats->rate -= rs;
8583 }
8584#endif // CONFIG_WARPED_MOTION
8585#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8586 if (!*skip_txfm_sb) {
8587 int64_t rdcosty = INT64_MAX;
8588 int is_cost_valid_uv = 0;
8589
8590 // cost and distortion
8591 av1_subtract_plane(x, bsize, 0);
8592#if CONFIG_VAR_TX
8593 if (cm->tx_mode == TX_MODE_SELECT && !xd->lossless[mbmi->segment_id]) {
8594 select_tx_type_yrd(cpi, x, rd_stats_y, bsize, ref_best_rd);
8595 } else {
8596 int idx, idy;
8597 super_block_yrd(cpi, x, rd_stats_y, bsize, ref_best_rd);
8598 for (idy = 0; idy < xd->n8_h; ++idy)
8599 for (idx = 0; idx < xd->n8_w; ++idx)
8600 mbmi->inter_tx_size[idy][idx] = mbmi->tx_size;
8601 memset(x->blk_skip[0], rd_stats_y->skip,
8602 sizeof(uint8_t) * xd->n8_h * xd->n8_w * 4);
8603 }
8604#else
8605 /* clang-format off */
8606 super_block_yrd(cpi, x, rd_stats_y, bsize, ref_best_rd);
8607/* clang-format on */
8608#endif // CONFIG_VAR_TX
8609
8610 if (rd_stats_y->rate == INT_MAX) {
8611 av1_invalid_rd_stats(rd_stats);
8612#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8613 if (mbmi->motion_mode != SIMPLE_TRANSLATION) {
8614 continue;
8615 } else {
8616#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8617 restore_dst_buf(xd, *orig_dst);
8618 return INT64_MAX;
8619#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8620 }
8621#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8622 }
8623
8624 av1_merge_rd_stats(rd_stats, rd_stats_y);
8625
Urvang Joshi70006e42017-06-14 16:08:55 -07008626 rdcosty = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
8627 rdcosty = AOMMIN(rdcosty, RDCOST(x->rdmult, 0, rd_stats->sse));
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008628/* clang-format off */
8629#if CONFIG_VAR_TX
8630 is_cost_valid_uv =
8631 inter_block_uvrd(cpi, x, rd_stats_uv, bsize, ref_best_rd - rdcosty);
8632#else
8633 is_cost_valid_uv =
8634 super_block_uvrd(cpi, x, rd_stats_uv, bsize, ref_best_rd - rdcosty);
8635#endif // CONFIG_VAR_TX
8636 if (!is_cost_valid_uv) {
8637#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8638 continue;
8639#else
8640 restore_dst_buf(xd, *orig_dst);
8641 return INT64_MAX;
8642#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8643 }
8644 /* clang-format on */
8645 av1_merge_rd_stats(rd_stats, rd_stats_uv);
8646#if CONFIG_RD_DEBUG
8647 // record transform block coefficient cost
8648 // TODO(angiebird): So far rd_debug tool only detects discrepancy of
8649 // coefficient cost. Therefore, it is fine to copy rd_stats into mbmi
8650 // here because we already collect the coefficient cost. Move this part to
8651 // other place when we need to compare non-coefficient cost.
8652 mbmi->rd_stats = *rd_stats;
8653#endif // CONFIG_RD_DEBUG
8654#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8655 if (rd_stats->skip) {
8656 rd_stats->rate -= rd_stats_uv->rate + rd_stats_y->rate;
8657 rd_stats_y->rate = 0;
8658 rd_stats_uv->rate = 0;
8659 rd_stats->rate += av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
8660 mbmi->skip = 0;
8661 // here mbmi->skip temporarily plays a role as what this_skip2 does
8662 } else if (!xd->lossless[mbmi->segment_id] &&
Urvang Joshi70006e42017-06-14 16:08:55 -07008663 (RDCOST(x->rdmult,
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008664 rd_stats_y->rate + rd_stats_uv->rate +
8665 av1_cost_bit(av1_get_skip_prob(cm, xd), 0),
8666 rd_stats->dist) >=
Urvang Joshi70006e42017-06-14 16:08:55 -07008667 RDCOST(x->rdmult, av1_cost_bit(av1_get_skip_prob(cm, xd), 1),
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008668 rd_stats->sse))) {
8669 rd_stats->rate -= rd_stats_uv->rate + rd_stats_y->rate;
8670 rd_stats->rate += av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
8671 rd_stats->dist = rd_stats->sse;
8672 rd_stats_y->rate = 0;
8673 rd_stats_uv->rate = 0;
8674 mbmi->skip = 1;
8675 } else {
8676 rd_stats->rate += av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
8677 mbmi->skip = 0;
8678 }
8679 *disable_skip = 0;
8680#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8681 } else {
8682 x->skip = 1;
8683 *disable_skip = 1;
8684 mbmi->tx_size = tx_size_from_tx_mode(bsize, cm->tx_mode, 1);
8685
8686// The cost of skip bit needs to be added.
8687#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8688 mbmi->skip = 0;
8689#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8690 rd_stats->rate += av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
8691
8692 rd_stats->dist = *skip_sse_sb;
8693 rd_stats->sse = *skip_sse_sb;
8694 rd_stats_y->rate = 0;
8695 rd_stats_uv->rate = 0;
8696 rd_stats->skip = 1;
8697 }
8698
8699#if CONFIG_GLOBAL_MOTION
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008700 if (this_mode == ZEROMV || this_mode == ZERO_ZEROMV) {
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008701 if (is_nontrans_global_motion(xd)) {
8702 rd_stats->rate -= rs;
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008703 mbmi->interp_filters = av1_broadcast_interp_filter(
8704 av1_unswitchable_filter(cm->interp_filter));
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008705 }
8706 }
8707#endif // CONFIG_GLOBAL_MOTION
8708
8709#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Urvang Joshi70006e42017-06-14 16:08:55 -07008710 tmp_rd = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008711 if (mbmi->motion_mode == SIMPLE_TRANSLATION || (tmp_rd < best_rd)) {
8712 best_mbmi = *mbmi;
8713 best_rd = tmp_rd;
8714 best_rd_stats = *rd_stats;
8715 best_rd_stats_y = *rd_stats_y;
8716 best_rd_stats_uv = *rd_stats_uv;
8717#if CONFIG_VAR_TX
8718 for (int i = 0; i < MAX_MB_PLANE; ++i)
8719 memcpy(best_blk_skip[i], x->blk_skip[i],
8720 sizeof(uint8_t) * xd->n8_h * xd->n8_w * 4);
8721#endif // CONFIG_VAR_TX
8722 best_xskip = x->skip;
8723 best_disable_skip = *disable_skip;
8724 }
8725 }
8726
8727 if (best_rd == INT64_MAX) {
8728 av1_invalid_rd_stats(rd_stats);
8729 restore_dst_buf(xd, *orig_dst);
8730 return INT64_MAX;
8731 }
8732 *mbmi = best_mbmi;
8733 *rd_stats = best_rd_stats;
8734 *rd_stats_y = best_rd_stats_y;
8735 *rd_stats_uv = best_rd_stats_uv;
8736#if CONFIG_VAR_TX
8737 for (int i = 0; i < MAX_MB_PLANE; ++i)
8738 memcpy(x->blk_skip[i], best_blk_skip[i],
8739 sizeof(uint8_t) * xd->n8_h * xd->n8_w * 4);
8740#endif // CONFIG_VAR_TX
8741 x->skip = best_xskip;
8742 *disable_skip = best_disable_skip;
8743#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8744
8745 restore_dst_buf(xd, *orig_dst);
8746 return 0;
8747}
8748
Zoe Liu85b66462017-04-20 14:28:19 -07008749static int64_t handle_inter_mode(const AV1_COMP *const cpi, MACROBLOCK *x,
8750 BLOCK_SIZE bsize, RD_STATS *rd_stats,
8751 RD_STATS *rd_stats_y, RD_STATS *rd_stats_uv,
8752 int *disable_skip,
8753 int_mv (*mode_mv)[TOTAL_REFS_PER_FRAME],
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008754#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008755 int_mv (*mode_comp_mv)[TOTAL_REFS_PER_FRAME],
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008756#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008757 int mi_row, int mi_col,
8758 HandleInterModeArgs *args,
8759 const int64_t ref_best_rd) {
Urvang Joshi52648442016-10-13 17:27:51 -07008760 const AV1_COMMON *cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008761 MACROBLOCKD *xd = &x->e_mbd;
Sarah Parker19234cc2017-03-10 16:43:25 -08008762 MODE_INFO *mi = xd->mi[0];
8763 MB_MODE_INFO *mbmi = &mi->mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008764 MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
8765 const int is_comp_pred = has_second_ref(mbmi);
8766 const int this_mode = mbmi->mode;
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008767#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008768 const int is_singleref_comp_mode = is_inter_singleref_comp_mode(this_mode);
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008769#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07008770 int_mv *frame_mv = mode_mv[this_mode];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008771#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008772 // The comp mv for the compound mode in single ref
8773 int_mv *frame_comp_mv = mode_comp_mv[this_mode];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008774#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07008775 int i;
8776 int refs[2] = { mbmi->ref_frame[0],
8777 (mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]) };
8778 int_mv cur_mv[2];
8779 int rate_mv = 0;
Angie Chiang75c22092016-10-25 12:19:16 -07008780 int pred_exists = 1;
Angie Chiang64a2fb82017-07-06 10:15:16 -07008781#if CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT || CONFIG_INTERINTRA
Jingning Hanae5cfde2016-11-30 12:01:44 -08008782 const int bw = block_size_wide[bsize];
James Zern89a015b2017-08-08 12:39:00 -04008783#endif // CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT
Yaowu Xuc27fc142016-08-22 16:08:15 -07008784 int_mv single_newmv[TOTAL_REFS_PER_FRAME];
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00008785#if CONFIG_INTERINTRA
Yue Chenb23d00a2017-07-28 17:01:21 -07008786 const int *const interintra_mode_cost =
8787 x->interintra_mode_cost[size_group_lookup[bsize]];
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00008788#endif // CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07008789 const int is_comp_interintra_pred = (mbmi->ref_frame[1] == INTRA_FRAME);
Yaowu Xuf883b422016-08-30 14:01:10 -07008790 uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008791#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07008792 DECLARE_ALIGNED(16, uint8_t, tmp_buf_[2 * MAX_MB_PLANE * MAX_SB_SQUARE]);
8793#else
8794 DECLARE_ALIGNED(16, uint8_t, tmp_buf_[MAX_MB_PLANE * MAX_SB_SQUARE]);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008795#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07008796 uint8_t *tmp_buf;
8797
Yue Chencb60b182016-10-13 15:18:22 -07008798#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -07008799 int rate2_bmc_nocoeff;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008800 MB_MODE_INFO best_bmc_mbmi;
Yue Chen69f18e12016-09-08 14:48:15 -07008801 int rate_mv_bmc;
Yue Chencb60b182016-10-13 15:18:22 -07008802#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Angie Chiang75c22092016-10-25 12:19:16 -07008803 int64_t rd = INT64_MAX;
David Barkerac37fa32016-12-02 12:30:21 +00008804 BUFFER_SET orig_dst, tmp_dst;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008805 int rs = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008806
8807 int skip_txfm_sb = 0;
8808 int64_t skip_sse_sb = INT64_MAX;
Yaowu Xub0d0d002016-11-22 09:26:43 -08008809 int16_t mode_ctx;
Wei-Ting Lin85a8f702017-06-22 13:55:15 -07008810#if CONFIG_NCOBMC_ADAPT_WEIGHT && CONFIG_MOTION_VAR
8811 // dummy fillers
8812 mbmi->ncobmc_mode[0] = NO_OVERLAP;
8813 mbmi->ncobmc_mode[1] = NO_OVERLAP;
8814#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07008815
Yue Chen5e606542017-05-24 17:03:17 -07008816#if CONFIG_INTERINTRA
8817 int compmode_interintra_cost = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008818 mbmi->use_wedge_interintra = 0;
Yue Chen5e606542017-05-24 17:03:17 -07008819#endif
8820#if CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT
8821 int compmode_interinter_cost = 0;
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008822 mbmi->interinter_compound_type = COMPOUND_AVERAGE;
Yue Chen5e606542017-05-24 17:03:17 -07008823#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07008824
Debargha Mukherjee9e2c7a62017-05-23 21:18:42 -07008825#if CONFIG_INTERINTRA
8826 if (!cm->allow_interintra_compound && is_comp_interintra_pred)
8827 return INT64_MAX;
8828#endif // CONFIG_INTERINTRA
8829
Yaowu Xuc27fc142016-08-22 16:08:15 -07008830 // is_comp_interintra_pred implies !is_comp_pred
8831 assert(!is_comp_interintra_pred || (!is_comp_pred));
8832 // is_comp_interintra_pred implies is_interintra_allowed(mbmi->sb_type)
8833 assert(!is_comp_interintra_pred || is_interintra_allowed(mbmi));
Yaowu Xuc27fc142016-08-22 16:08:15 -07008834
Zoe Liu85b66462017-04-20 14:28:19 -07008835#if CONFIG_COMPOUND_SINGLEREF
8836 if (is_comp_pred || is_singleref_comp_mode)
8837#else // !CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07008838 if (is_comp_pred)
Zoe Liu85b66462017-04-20 14:28:19 -07008839#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07008840 mode_ctx = mbmi_ext->compound_mode_context[refs[0]];
8841 else
Yaowu Xuf883b422016-08-30 14:01:10 -07008842 mode_ctx = av1_mode_context_analyzer(mbmi_ext->mode_context,
8843 mbmi->ref_frame, bsize, -1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07008844
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008845#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07008846 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
8847 tmp_buf = CONVERT_TO_BYTEPTR(tmp_buf_);
8848 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008849#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07008850 tmp_buf = tmp_buf_;
David Barkerb8069f92016-11-18 14:49:56 +00008851 // Make sure that we didn't leave the plane destination buffers set
8852 // to tmp_buf at the end of the last iteration
8853 assert(xd->plane[0].dst.buf != tmp_buf);
Yaowu Xuc27fc142016-08-22 16:08:15 -07008854
Yue Chen69f18e12016-09-08 14:48:15 -07008855#if CONFIG_WARPED_MOTION
8856 mbmi->num_proj_ref[0] = 0;
8857 mbmi->num_proj_ref[1] = 0;
8858#endif // CONFIG_WARPED_MOTION
8859
Yaowu Xuc27fc142016-08-22 16:08:15 -07008860 if (is_comp_pred) {
8861 if (frame_mv[refs[0]].as_int == INVALID_MV ||
8862 frame_mv[refs[1]].as_int == INVALID_MV)
8863 return INT64_MAX;
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008864#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008865 } else if (is_singleref_comp_mode) {
8866 if (frame_mv[refs[0]].as_int == INVALID_MV ||
8867 frame_comp_mv[refs[0]].as_int == INVALID_MV)
8868 return INT64_MAX;
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008869#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07008870 }
8871
Yue Chene9638cc2016-10-10 12:37:54 -07008872 mbmi->motion_mode = SIMPLE_TRANSLATION;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008873 if (have_newmv_in_inter_mode(this_mode)) {
Zoe Liu85b66462017-04-20 14:28:19 -07008874 const int64_t ret_val =
8875 handle_newmv(cpi, x, bsize, mode_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008876#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008877 mode_comp_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008878#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008879 mi_row, mi_col, &rate_mv, single_newmv, args);
Fergus Simpson45509632017-02-22 15:30:50 -08008880 if (ret_val != 0)
8881 return ret_val;
8882 else
8883 rd_stats->rate += rate_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008884 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07008885 for (i = 0; i < is_comp_pred + 1; ++i) {
8886 cur_mv[i] = frame_mv[refs[i]];
Zoe Liued29ea22017-04-20 16:48:15 -07008887 // Clip "next_nearest" so that it does not extend to far out of image
8888 if (this_mode != NEWMV) clamp_mv2(&cur_mv[i].as_mv, xd);
Alex Converse0fa0f422017-04-24 12:51:14 -07008889 if (mv_check_bounds(&x->mv_limits, &cur_mv[i].as_mv)) return INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008890 mbmi->mv[i].as_int = cur_mv[i].as_int;
8891 }
8892
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008893#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008894 if (!is_comp_pred && is_singleref_comp_mode) {
8895 cur_mv[1] = frame_comp_mv[refs[0]];
8896 // Clip "next_nearest" so that it does not extend to far out of image
8897 if (this_mode != NEWMV) clamp_mv2(&cur_mv[1].as_mv, xd);
8898 if (mv_check_bounds(&x->mv_limits, &cur_mv[1].as_mv)) return INT64_MAX;
8899 mbmi->mv[1].as_int = cur_mv[1].as_int;
8900 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008901#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008902
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008903 if (this_mode == NEAREST_NEARESTMV) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07008904 if (mbmi_ext->ref_mv_count[ref_frame_type] > 0) {
8905 cur_mv[0] = mbmi_ext->ref_mv_stack[ref_frame_type][0].this_mv;
8906 cur_mv[1] = mbmi_ext->ref_mv_stack[ref_frame_type][0].comp_mv;
8907
8908 for (i = 0; i < 2; ++i) {
8909 clamp_mv2(&cur_mv[i].as_mv, xd);
Alex Converse0fa0f422017-04-24 12:51:14 -07008910 if (mv_check_bounds(&x->mv_limits, &cur_mv[i].as_mv)) return INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008911 mbmi->mv[i].as_int = cur_mv[i].as_int;
8912 }
8913 }
8914 }
8915
Yaowu Xuc27fc142016-08-22 16:08:15 -07008916 if (mbmi_ext->ref_mv_count[ref_frame_type] > 0) {
Zoe Liu85b66462017-04-20 14:28:19 -07008917#if CONFIG_COMPOUND_SINGLEREF
8918 if (this_mode == NEAREST_NEWMV || // this_mode == SR_NEAREST_NEWMV ||
Yushin Cho67dda512017-07-25 14:58:22 -07008919 this_mode == SR_NEAREST_NEARMV)
Zoe Liu85b66462017-04-20 14:28:19 -07008920#else // !CONFIG_COMPOUND_SINGLEREF
Yushin Cho67dda512017-07-25 14:58:22 -07008921 if (this_mode == NEAREST_NEWMV)
Zoe Liu85b66462017-04-20 14:28:19 -07008922#endif // CONFIG_COMPOUND_SINGLEREF
Yushin Cho67dda512017-07-25 14:58:22 -07008923 {
Yaowu Xuc27fc142016-08-22 16:08:15 -07008924 cur_mv[0] = mbmi_ext->ref_mv_stack[ref_frame_type][0].this_mv;
8925
RogerZhou3b635242017-09-19 10:06:46 -07008926#if CONFIG_AMVR
8927 lower_mv_precision(&cur_mv[0].as_mv, cm->allow_high_precision_mv,
8928 cm->cur_frame_mv_precision_level);
8929#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07008930 lower_mv_precision(&cur_mv[0].as_mv, cm->allow_high_precision_mv);
RogerZhou3b635242017-09-19 10:06:46 -07008931#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07008932 clamp_mv2(&cur_mv[0].as_mv, xd);
Alex Converse0fa0f422017-04-24 12:51:14 -07008933 if (mv_check_bounds(&x->mv_limits, &cur_mv[0].as_mv)) return INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008934 mbmi->mv[0].as_int = cur_mv[0].as_int;
8935 }
8936
Debargha Mukherjeebb6e1342017-04-17 16:05:04 -07008937 if (this_mode == NEW_NEARESTMV) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07008938 cur_mv[1] = mbmi_ext->ref_mv_stack[ref_frame_type][0].comp_mv;
8939
RogerZhou3b635242017-09-19 10:06:46 -07008940#if CONFIG_AMVR
8941 lower_mv_precision(&cur_mv[1].as_mv, cm->allow_high_precision_mv,
8942 cm->cur_frame_mv_precision_level);
8943#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07008944 lower_mv_precision(&cur_mv[1].as_mv, cm->allow_high_precision_mv);
RogerZhou3b635242017-09-19 10:06:46 -07008945#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07008946 clamp_mv2(&cur_mv[1].as_mv, xd);
Alex Converse0fa0f422017-04-24 12:51:14 -07008947 if (mv_check_bounds(&x->mv_limits, &cur_mv[1].as_mv)) return INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008948 mbmi->mv[1].as_int = cur_mv[1].as_int;
8949 }
8950 }
8951
8952 if (mbmi_ext->ref_mv_count[ref_frame_type] > 1) {
David Barker404b2e82017-03-27 13:07:47 +01008953 int ref_mv_idx = mbmi->ref_mv_idx + 1;
Zoe Liu85b66462017-04-20 14:28:19 -07008954 if (this_mode == NEAR_NEWMV ||
8955#if CONFIG_COMPOUND_SINGLEREF
8956 this_mode == SR_NEAR_NEWMV ||
8957#endif // CONFIG_COMPOUND_SINGLEREF
8958 this_mode == NEAR_NEARMV) {
David Barker404b2e82017-03-27 13:07:47 +01008959 cur_mv[0] = mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].this_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008960
RogerZhou3b635242017-09-19 10:06:46 -07008961#if CONFIG_AMVR
8962 lower_mv_precision(&cur_mv[0].as_mv, cm->allow_high_precision_mv,
8963 cm->cur_frame_mv_precision_level);
8964#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07008965 lower_mv_precision(&cur_mv[0].as_mv, cm->allow_high_precision_mv);
RogerZhou3b635242017-09-19 10:06:46 -07008966#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07008967 clamp_mv2(&cur_mv[0].as_mv, xd);
Alex Converse0fa0f422017-04-24 12:51:14 -07008968 if (mv_check_bounds(&x->mv_limits, &cur_mv[0].as_mv)) return INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008969 mbmi->mv[0].as_int = cur_mv[0].as_int;
8970 }
8971
Zoe Liu85b66462017-04-20 14:28:19 -07008972 if (this_mode == NEW_NEARMV ||
8973#if CONFIG_COMPOUND_SINGLEREF
8974 this_mode == SR_NEAREST_NEARMV ||
8975#endif // CONFIG_COMPOUND_SINGLEREF
8976 this_mode == NEAR_NEARMV) {
8977#if CONFIG_COMPOUND_SINGLEREF
8978 if (this_mode == SR_NEAREST_NEARMV)
8979 cur_mv[1] = mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].this_mv;
8980 else
8981#endif // CONFIG_COMPOUND_SINGLEREF
8982 cur_mv[1] = mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].comp_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008983
RogerZhou3b635242017-09-19 10:06:46 -07008984#if CONFIG_AMVR
8985 lower_mv_precision(&cur_mv[1].as_mv, cm->allow_high_precision_mv,
8986 cm->cur_frame_mv_precision_level);
8987#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07008988 lower_mv_precision(&cur_mv[1].as_mv, cm->allow_high_precision_mv);
RogerZhou3b635242017-09-19 10:06:46 -07008989#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07008990 clamp_mv2(&cur_mv[1].as_mv, xd);
Alex Converse0fa0f422017-04-24 12:51:14 -07008991 if (mv_check_bounds(&x->mv_limits, &cur_mv[1].as_mv)) return INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008992 mbmi->mv[1].as_int = cur_mv[1].as_int;
8993 }
8994 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07008995
8996 // do first prediction into the destination buffer. Do the next
8997 // prediction into a temporary buffer. Then keep track of which one
8998 // of these currently holds the best predictor, and use the other
8999 // one for future predictions. In the end, copy from tmp_buf to
9000 // dst if necessary.
9001 for (i = 0; i < MAX_MB_PLANE; i++) {
David Barkerac37fa32016-12-02 12:30:21 +00009002 tmp_dst.plane[i] = tmp_buf + i * MAX_SB_SQUARE;
9003 tmp_dst.stride[i] = MAX_SB_SIZE;
Angie Chiang75c22092016-10-25 12:19:16 -07009004 }
9005 for (i = 0; i < MAX_MB_PLANE; i++) {
David Barkerac37fa32016-12-02 12:30:21 +00009006 orig_dst.plane[i] = xd->plane[i].dst.buf;
9007 orig_dst.stride[i] = xd->plane[i].dst.stride;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009008 }
9009
9010 // We don't include the cost of the second reference here, because there
9011 // are only three options: Last/Golden, ARF/Last or Golden/ARF, or in other
9012 // words if you present them in that order, the second one is always known
9013 // if the first is known.
9014 //
9015 // Under some circumstances we discount the cost of new mv mode to encourage
9016 // initiation of a motion field.
9017 if (discount_newmv_test(cpi, this_mode, frame_mv[refs[0]], mode_mv,
9018 refs[0])) {
Yue Chenb23d00a2017-07-28 17:01:21 -07009019 rd_stats->rate += AOMMIN(
9020 cost_mv_ref(x, this_mode, mode_ctx),
9021 cost_mv_ref(x, is_comp_pred ? NEAREST_NEARESTMV : NEARESTMV, mode_ctx));
Yaowu Xuc27fc142016-08-22 16:08:15 -07009022 } else {
Yue Chenb23d00a2017-07-28 17:01:21 -07009023 rd_stats->rate += cost_mv_ref(x, this_mode, mode_ctx);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009024 }
9025
Urvang Joshi70006e42017-06-14 16:08:55 -07009026 if (RDCOST(x->rdmult, rd_stats->rate, 0) > ref_best_rd &&
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009027 mbmi->mode != NEARESTMV && mbmi->mode != NEAREST_NEARESTMV)
Yaowu Xuc27fc142016-08-22 16:08:15 -07009028 return INT64_MAX;
9029
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08009030 int64_t ret_val = interpolation_filter_search(
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -08009031 x, cpi, bsize, mi_row, mi_col, &tmp_dst, &orig_dst, args->single_filter,
9032 &rd, &rs, &skip_txfm_sb, &skip_sse_sb);
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08009033 if (ret_val != 0) return ret_val;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009034
Yue Chen69f18e12016-09-08 14:48:15 -07009035#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -07009036 best_bmc_mbmi = *mbmi;
Angie Chiang76159122016-11-09 12:13:22 -08009037 rate2_bmc_nocoeff = rd_stats->rate;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009038 if (cm->interp_filter == SWITCHABLE) rate2_bmc_nocoeff += rs;
Yue Chen69f18e12016-09-08 14:48:15 -07009039 rate_mv_bmc = rate_mv;
Yue Chen69f18e12016-09-08 14:48:15 -07009040#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -07009041
Yue Chen5e606542017-05-24 17:03:17 -07009042#if CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT
Zoe Liu85b66462017-04-20 14:28:19 -07009043#if CONFIG_COMPOUND_SINGLEREF
Yushin Cho67dda512017-07-25 14:58:22 -07009044 if (is_comp_pred || is_singleref_comp_mode)
Zoe Liu85b66462017-04-20 14:28:19 -07009045#else
Yushin Cho67dda512017-07-25 14:58:22 -07009046 if (is_comp_pred)
Zoe Liu85b66462017-04-20 14:28:19 -07009047#endif // CONFIG_COMPOUND_SINGLEREF
Yushin Cho67dda512017-07-25 14:58:22 -07009048 {
Urvang Joshi368fbc92016-10-17 16:31:34 -07009049 int rate_sum, rs2;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009050 int64_t dist_sum;
Sarah Parker6fdc8532016-11-16 17:47:13 -08009051 int64_t best_rd_compound = INT64_MAX, best_rd_cur = INT64_MAX;
9052 INTERINTER_COMPOUND_DATA best_compound_data;
9053 int_mv best_mv[2];
9054 int best_tmp_rate_mv = rate_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009055 int tmp_skip_txfm_sb;
9056 int64_t tmp_skip_sse_sb;
Yaowu Xu5e8007f2017-06-28 12:39:18 -07009057 DECLARE_ALIGNED(16, uint8_t, pred0[2 * MAX_SB_SQUARE]);
9058 DECLARE_ALIGNED(16, uint8_t, pred1[2 * MAX_SB_SQUARE]);
Sarah Parker6fdc8532016-11-16 17:47:13 -08009059 uint8_t *preds0[1] = { pred0 };
9060 uint8_t *preds1[1] = { pred1 };
9061 int strides[1] = { bw };
Sarah Parker2e604882017-01-17 17:31:25 -08009062 int tmp_rate_mv;
Sarah Parker42d96102017-01-31 21:05:27 -08009063 int masked_compound_used = is_any_masked_compound_used(bsize);
Debargha Mukherjee9e2c7a62017-05-23 21:18:42 -07009064#if CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
9065 masked_compound_used = masked_compound_used && cm->allow_masked_compound;
9066#endif // CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
Sarah Parker6fdc8532016-11-16 17:47:13 -08009067 COMPOUND_TYPE cur_type;
Yue Chena4245512017-08-31 11:58:08 -07009068 int best_compmode_interinter_cost = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009069
Sarah Parker6fdc8532016-11-16 17:47:13 -08009070 best_mv[0].as_int = cur_mv[0].as_int;
9071 best_mv[1].as_int = cur_mv[1].as_int;
Sarah Parker2d0e9b72017-05-04 01:34:16 +00009072 memset(&best_compound_data, 0, sizeof(best_compound_data));
9073#if CONFIG_COMPOUND_SEGMENT
9074 uint8_t tmp_mask_buf[2 * MAX_SB_SQUARE];
9075 best_compound_data.seg_mask = tmp_mask_buf;
9076#endif // CONFIG_COMPOUND_SEGMENT
Yaowu Xuc27fc142016-08-22 16:08:15 -07009077
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009078#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07009079 // TODO(zoeliu): To further check whether the following setups are needed.
9080 // Single ref compound mode: Prepare the 2nd ref frame predictor the same as
9081 // the 1st one.
9082 if (!is_comp_pred && is_singleref_comp_mode) {
9083 xd->block_refs[1] = xd->block_refs[0];
9084 for (i = 0; i < MAX_MB_PLANE; i++)
9085 xd->plane[i].pre[1] = xd->plane[i].pre[0];
9086 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009087#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07009088
Sarah Parker42d96102017-01-31 21:05:27 -08009089 if (masked_compound_used) {
Sarah Parker6fdc8532016-11-16 17:47:13 -08009090 // get inter predictors to use for masked compound modes
Yaowu Xuf883b422016-08-30 14:01:10 -07009091 av1_build_inter_predictors_for_planes_single_buf(
Yaowu Xuc27fc142016-08-22 16:08:15 -07009092 xd, bsize, 0, 0, mi_row, mi_col, 0, preds0, strides);
Yaowu Xuf883b422016-08-30 14:01:10 -07009093 av1_build_inter_predictors_for_planes_single_buf(
Yaowu Xuc27fc142016-08-22 16:08:15 -07009094 xd, bsize, 0, 0, mi_row, mi_col, 1, preds1, strides);
Sarah Parker6fdc8532016-11-16 17:47:13 -08009095 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07009096
Sarah Parker6fdc8532016-11-16 17:47:13 -08009097 for (cur_type = COMPOUND_AVERAGE; cur_type < COMPOUND_TYPES; cur_type++) {
Debargha Mukherjee9e2c7a62017-05-23 21:18:42 -07009098 if (cur_type != COMPOUND_AVERAGE && !masked_compound_used) break;
Yue Chene2518252017-06-05 12:36:46 -07009099 if (!is_interinter_compound_used(cur_type, bsize)) continue;
Sarah Parker2e604882017-01-17 17:31:25 -08009100 tmp_rate_mv = rate_mv;
Sarah Parker6fdc8532016-11-16 17:47:13 -08009101 best_rd_cur = INT64_MAX;
Sarah Parker2d0e9b72017-05-04 01:34:16 +00009102 mbmi->interinter_compound_type = cur_type;
Sarah Parker680b9b12017-08-16 18:55:34 -07009103 int masked_type_cost = 0;
9104 if (masked_compound_used) {
9105#if CONFIG_WEDGE && CONFIG_COMPOUND_SEGMENT
9106 if (!is_interinter_compound_used(COMPOUND_WEDGE, bsize))
9107 masked_type_cost += av1_cost_literal(1);
9108 else
9109#endif // CONFIG_WEDGE && CONFIG_COMPOUND_SEGMENT
9110 masked_type_cost +=
Yue Chena4245512017-08-31 11:58:08 -07009111 x->compound_type_cost[bsize][mbmi->interinter_compound_type];
Sarah Parker680b9b12017-08-16 18:55:34 -07009112 }
Sarah Parker6fdc8532016-11-16 17:47:13 -08009113 rs2 = av1_cost_literal(get_interinter_compound_type_bits(
Sarah Parker2d0e9b72017-05-04 01:34:16 +00009114 bsize, mbmi->interinter_compound_type)) +
Sarah Parker680b9b12017-08-16 18:55:34 -07009115 masked_type_cost;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009116
Sarah Parker6fdc8532016-11-16 17:47:13 -08009117 switch (cur_type) {
9118 case COMPOUND_AVERAGE:
Jingning Hanc44009c2017-05-06 11:36:49 -07009119 av1_build_inter_predictors_sby(cm, xd, mi_row, mi_col, &orig_dst,
9120 bsize);
Sarah Parker6fdc8532016-11-16 17:47:13 -08009121 av1_subtract_plane(x, bsize, 0);
9122 rd = estimate_yrd_for_sb(cpi, bsize, x, &rate_sum, &dist_sum,
9123 &tmp_skip_txfm_sb, &tmp_skip_sse_sb,
9124 INT64_MAX);
9125 if (rd != INT64_MAX)
Urvang Joshi70006e42017-06-14 16:08:55 -07009126 best_rd_cur = RDCOST(x->rdmult, rs2 + rate_mv + rate_sum, dist_sum);
Sarah Parker2e604882017-01-17 17:31:25 -08009127 best_rd_compound = best_rd_cur;
Sarah Parker6fdc8532016-11-16 17:47:13 -08009128 break;
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00009129#if CONFIG_WEDGE
Sarah Parker6fdc8532016-11-16 17:47:13 -08009130 case COMPOUND_WEDGE:
Sarah Parker6fdc8532016-11-16 17:47:13 -08009131 if (x->source_variance > cpi->sf.disable_wedge_search_var_thresh &&
9132 best_rd_compound / 3 < ref_best_rd) {
Sarah Parkerddcea392017-04-25 15:57:22 -07009133 best_rd_cur = build_and_cost_compound_type(
David Barkerac37fa32016-12-02 12:30:21 +00009134 cpi, x, cur_mv, bsize, this_mode, rs2, rate_mv, &orig_dst,
9135 &tmp_rate_mv, preds0, preds1, strides, mi_row, mi_col);
Sarah Parker6fdc8532016-11-16 17:47:13 -08009136 }
9137 break;
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00009138#endif // CONFIG_WEDGE
Sarah Parker2f6ce752016-12-08 15:26:46 -08009139#if CONFIG_COMPOUND_SEGMENT
Sarah Parker569edda2016-12-14 14:57:38 -08009140 case COMPOUND_SEG:
Sarah Parker569edda2016-12-14 14:57:38 -08009141 if (x->source_variance > cpi->sf.disable_wedge_search_var_thresh &&
9142 best_rd_compound / 3 < ref_best_rd) {
Sarah Parkerddcea392017-04-25 15:57:22 -07009143 best_rd_cur = build_and_cost_compound_type(
Sarah Parker569edda2016-12-14 14:57:38 -08009144 cpi, x, cur_mv, bsize, this_mode, rs2, rate_mv, &orig_dst,
9145 &tmp_rate_mv, preds0, preds1, strides, mi_row, mi_col);
Sarah Parker569edda2016-12-14 14:57:38 -08009146 }
9147 break;
Sarah Parker2f6ce752016-12-08 15:26:46 -08009148#endif // CONFIG_COMPOUND_SEGMENT
Sarah Parker6fdc8532016-11-16 17:47:13 -08009149 default: assert(0); return 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009150 }
Sarah Parker2e604882017-01-17 17:31:25 -08009151
9152 if (best_rd_cur < best_rd_compound) {
9153 best_rd_compound = best_rd_cur;
Sarah Parker2d0e9b72017-05-04 01:34:16 +00009154#if CONFIG_WEDGE
9155 best_compound_data.wedge_index = mbmi->wedge_index;
9156 best_compound_data.wedge_sign = mbmi->wedge_sign;
9157#endif // CONFIG_WEDGE
9158#if CONFIG_COMPOUND_SEGMENT
9159 best_compound_data.mask_type = mbmi->mask_type;
9160 memcpy(best_compound_data.seg_mask, xd->seg_mask,
9161 2 * MAX_SB_SQUARE * sizeof(uint8_t));
9162#endif // CONFIG_COMPOUND_SEGMENT
9163 best_compound_data.interinter_compound_type =
9164 mbmi->interinter_compound_type;
Yue Chena4245512017-08-31 11:58:08 -07009165 best_compmode_interinter_cost = rs2;
Sarah Parker2e604882017-01-17 17:31:25 -08009166 if (have_newmv_in_inter_mode(this_mode)) {
9167 if (use_masked_motion_search(cur_type)) {
9168 best_tmp_rate_mv = tmp_rate_mv;
9169 best_mv[0].as_int = mbmi->mv[0].as_int;
9170 best_mv[1].as_int = mbmi->mv[1].as_int;
9171 } else {
9172 best_mv[0].as_int = cur_mv[0].as_int;
9173 best_mv[1].as_int = cur_mv[1].as_int;
9174 }
9175 }
9176 }
9177 // reset to original mvs for next iteration
9178 mbmi->mv[0].as_int = cur_mv[0].as_int;
9179 mbmi->mv[1].as_int = cur_mv[1].as_int;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009180 }
Sarah Parker2d0e9b72017-05-04 01:34:16 +00009181#if CONFIG_WEDGE
9182 mbmi->wedge_index = best_compound_data.wedge_index;
9183 mbmi->wedge_sign = best_compound_data.wedge_sign;
9184#endif // CONFIG_WEDGE
9185#if CONFIG_COMPOUND_SEGMENT
9186 mbmi->mask_type = best_compound_data.mask_type;
9187 memcpy(xd->seg_mask, best_compound_data.seg_mask,
9188 2 * MAX_SB_SQUARE * sizeof(uint8_t));
9189#endif // CONFIG_COMPOUND_SEGMENT
9190 mbmi->interinter_compound_type =
9191 best_compound_data.interinter_compound_type;
Sarah Parker6fdc8532016-11-16 17:47:13 -08009192 if (have_newmv_in_inter_mode(this_mode)) {
9193 mbmi->mv[0].as_int = best_mv[0].as_int;
9194 mbmi->mv[1].as_int = best_mv[1].as_int;
9195 xd->mi[0]->bmi[0].as_mv[0].as_int = mbmi->mv[0].as_int;
9196 xd->mi[0]->bmi[0].as_mv[1].as_int = mbmi->mv[1].as_int;
Sarah Parker2d0e9b72017-05-04 01:34:16 +00009197 if (use_masked_motion_search(mbmi->interinter_compound_type)) {
Sarah Parker6fdc8532016-11-16 17:47:13 -08009198 rd_stats->rate += best_tmp_rate_mv - rate_mv;
9199 rate_mv = best_tmp_rate_mv;
9200 }
9201 }
9202
9203 if (ref_best_rd < INT64_MAX && best_rd_compound / 3 > ref_best_rd) {
David Barkerac37fa32016-12-02 12:30:21 +00009204 restore_dst_buf(xd, orig_dst);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009205 return INT64_MAX;
David Barkerb8069f92016-11-18 14:49:56 +00009206 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07009207
9208 pred_exists = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009209
Yue Chena4245512017-08-31 11:58:08 -07009210 compmode_interinter_cost = best_compmode_interinter_cost;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009211 }
Yue Chen5e606542017-05-24 17:03:17 -07009212#endif // CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT
Yaowu Xuc27fc142016-08-22 16:08:15 -07009213
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00009214#if CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07009215 if (is_comp_interintra_pred) {
9216 INTERINTRA_MODE best_interintra_mode = II_DC_PRED;
9217 int64_t best_interintra_rd = INT64_MAX;
9218 int rmode, rate_sum;
9219 int64_t dist_sum;
9220 int j;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009221 int tmp_rate_mv = 0;
9222 int tmp_skip_txfm_sb;
9223 int64_t tmp_skip_sse_sb;
9224 DECLARE_ALIGNED(16, uint8_t, intrapred_[2 * MAX_SB_SQUARE]);
9225 uint8_t *intrapred;
9226
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02009227#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07009228 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
9229 intrapred = CONVERT_TO_BYTEPTR(intrapred_);
9230 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02009231#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07009232 intrapred = intrapred_;
9233
Emil Keyder01770b32017-01-20 18:03:11 -05009234 mbmi->ref_frame[1] = NONE_FRAME;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009235 for (j = 0; j < MAX_MB_PLANE; j++) {
9236 xd->plane[j].dst.buf = tmp_buf + j * MAX_SB_SQUARE;
9237 xd->plane[j].dst.stride = bw;
9238 }
Debargha Mukherjeead8be032017-05-09 15:28:45 -07009239 av1_build_inter_predictors_sby(cm, xd, mi_row, mi_col, &orig_dst, bsize);
David Barkerac37fa32016-12-02 12:30:21 +00009240 restore_dst_buf(xd, orig_dst);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009241 mbmi->ref_frame[1] = INTRA_FRAME;
9242 mbmi->use_wedge_interintra = 0;
9243
9244 for (j = 0; j < INTERINTRA_MODES; ++j) {
9245 mbmi->interintra_mode = (INTERINTRA_MODE)j;
9246 rmode = interintra_mode_cost[mbmi->interintra_mode];
David Barker761b1ac2017-09-25 11:23:03 +01009247 av1_build_intra_predictors_for_interintra(cm, xd, bsize, 0, &orig_dst,
David Barkerac37fa32016-12-02 12:30:21 +00009248 intrapred, bw);
Yaowu Xuf883b422016-08-30 14:01:10 -07009249 av1_combine_interintra(xd, bsize, 0, tmp_buf, bw, intrapred, bw);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009250 model_rd_for_sb(cpi, bsize, x, xd, 0, 0, &rate_sum, &dist_sum,
9251 &tmp_skip_txfm_sb, &tmp_skip_sse_sb);
Urvang Joshi70006e42017-06-14 16:08:55 -07009252 rd = RDCOST(x->rdmult, tmp_rate_mv + rate_sum + rmode, dist_sum);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009253 if (rd < best_interintra_rd) {
9254 best_interintra_rd = rd;
9255 best_interintra_mode = mbmi->interintra_mode;
9256 }
9257 }
9258 mbmi->interintra_mode = best_interintra_mode;
9259 rmode = interintra_mode_cost[mbmi->interintra_mode];
David Barker761b1ac2017-09-25 11:23:03 +01009260 av1_build_intra_predictors_for_interintra(cm, xd, bsize, 0, &orig_dst,
David Barkerac37fa32016-12-02 12:30:21 +00009261 intrapred, bw);
Yaowu Xuf883b422016-08-30 14:01:10 -07009262 av1_combine_interintra(xd, bsize, 0, tmp_buf, bw, intrapred, bw);
9263 av1_subtract_plane(x, bsize, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009264 rd = estimate_yrd_for_sb(cpi, bsize, x, &rate_sum, &dist_sum,
9265 &tmp_skip_txfm_sb, &tmp_skip_sse_sb, INT64_MAX);
9266 if (rd != INT64_MAX)
Urvang Joshi70006e42017-06-14 16:08:55 -07009267 rd = RDCOST(x->rdmult, rate_mv + rmode + rate_sum, dist_sum);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009268 best_interintra_rd = rd;
9269
9270 if (ref_best_rd < INT64_MAX && best_interintra_rd > 2 * ref_best_rd) {
David Barkerb8069f92016-11-18 14:49:56 +00009271 // Don't need to call restore_dst_buf here
Yaowu Xuc27fc142016-08-22 16:08:15 -07009272 return INT64_MAX;
9273 }
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00009274#if CONFIG_WEDGE
Yaowu Xuc27fc142016-08-22 16:08:15 -07009275 if (is_interintra_wedge_used(bsize)) {
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00009276 int64_t best_interintra_rd_nowedge = INT64_MAX;
9277 int64_t best_interintra_rd_wedge = INT64_MAX;
9278 int_mv tmp_mv;
9279 int rwedge = av1_cost_bit(cm->fc->wedge_interintra_prob[bsize], 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009280 if (rd != INT64_MAX)
Urvang Joshi70006e42017-06-14 16:08:55 -07009281 rd = RDCOST(x->rdmult, rmode + rate_mv + rwedge + rate_sum, dist_sum);
Yue Chenf03907a2017-05-31 12:04:04 -07009282 best_interintra_rd_nowedge = best_interintra_rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009283
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08009284 // Disable wedge search if source variance is small
Yaowu Xuc27fc142016-08-22 16:08:15 -07009285 if (x->source_variance > cpi->sf.disable_wedge_search_var_thresh) {
9286 mbmi->use_wedge_interintra = 1;
9287
Yaowu Xuf883b422016-08-30 14:01:10 -07009288 rwedge = av1_cost_literal(get_interintra_wedge_bits(bsize)) +
9289 av1_cost_bit(cm->fc->wedge_interintra_prob[bsize], 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009290
9291 best_interintra_rd_wedge =
9292 pick_interintra_wedge(cpi, x, bsize, intrapred_, tmp_buf_);
9293
9294 best_interintra_rd_wedge +=
Urvang Joshi70006e42017-06-14 16:08:55 -07009295 RDCOST(x->rdmult, rmode + rate_mv + rwedge, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009296 // Refine motion vector.
9297 if (have_newmv_in_inter_mode(this_mode)) {
9298 // get negative of mask
Yaowu Xuf883b422016-08-30 14:01:10 -07009299 const uint8_t *mask = av1_get_contiguous_soft_mask(
Yaowu Xuc27fc142016-08-22 16:08:15 -07009300 mbmi->interintra_wedge_index, 1, bsize);
David Barkerf19f35f2017-05-22 16:33:22 +01009301 tmp_mv.as_int = x->mbmi_ext->ref_mvs[refs[0]][0].as_int;
9302 compound_single_motion_search(cpi, x, bsize, &tmp_mv.as_mv, mi_row,
9303 mi_col, intrapred, mask, bw,
Timothy B. Terriberry5d24b6f2017-06-15 13:39:35 -07009304 &tmp_rate_mv, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009305 mbmi->mv[0].as_int = tmp_mv.as_int;
Debargha Mukherjeead8be032017-05-09 15:28:45 -07009306 av1_build_inter_predictors_sby(cm, xd, mi_row, mi_col, &orig_dst,
9307 bsize);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009308 model_rd_for_sb(cpi, bsize, x, xd, 0, 0, &rate_sum, &dist_sum,
9309 &tmp_skip_txfm_sb, &tmp_skip_sse_sb);
Urvang Joshi70006e42017-06-14 16:08:55 -07009310 rd = RDCOST(x->rdmult, rmode + tmp_rate_mv + rwedge + rate_sum,
9311 dist_sum);
Yue Chenf03907a2017-05-31 12:04:04 -07009312 if (rd >= best_interintra_rd_wedge) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07009313 tmp_mv.as_int = cur_mv[0].as_int;
9314 tmp_rate_mv = rate_mv;
9315 }
9316 } else {
9317 tmp_mv.as_int = cur_mv[0].as_int;
9318 tmp_rate_mv = rate_mv;
Yaowu Xuf883b422016-08-30 14:01:10 -07009319 av1_combine_interintra(xd, bsize, 0, tmp_buf, bw, intrapred, bw);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009320 }
9321 // Evaluate closer to true rd
Yaowu Xuf883b422016-08-30 14:01:10 -07009322 av1_subtract_plane(x, bsize, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009323 rd =
9324 estimate_yrd_for_sb(cpi, bsize, x, &rate_sum, &dist_sum,
9325 &tmp_skip_txfm_sb, &tmp_skip_sse_sb, INT64_MAX);
9326 if (rd != INT64_MAX)
Urvang Joshi70006e42017-06-14 16:08:55 -07009327 rd = RDCOST(x->rdmult, rmode + tmp_rate_mv + rwedge + rate_sum,
9328 dist_sum);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009329 best_interintra_rd_wedge = rd;
9330 if (best_interintra_rd_wedge < best_interintra_rd_nowedge) {
9331 mbmi->use_wedge_interintra = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009332 mbmi->mv[0].as_int = tmp_mv.as_int;
Angie Chiang76159122016-11-09 12:13:22 -08009333 rd_stats->rate += tmp_rate_mv - rate_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009334 rate_mv = tmp_rate_mv;
9335 } else {
9336 mbmi->use_wedge_interintra = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009337 mbmi->mv[0].as_int = cur_mv[0].as_int;
9338 }
9339 } else {
9340 mbmi->use_wedge_interintra = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009341 }
9342 }
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00009343#endif // CONFIG_WEDGE
Yaowu Xuc27fc142016-08-22 16:08:15 -07009344
9345 pred_exists = 0;
Yue Chen5e606542017-05-24 17:03:17 -07009346 compmode_interintra_cost =
9347 av1_cost_bit(cm->fc->interintra_prob[size_group_lookup[bsize]], 1) +
Fergus Simpson073c6f32017-02-17 12:13:48 -08009348 interintra_mode_cost[mbmi->interintra_mode];
Yaowu Xuc27fc142016-08-22 16:08:15 -07009349 if (is_interintra_wedge_used(bsize)) {
Yue Chen5e606542017-05-24 17:03:17 -07009350 compmode_interintra_cost += av1_cost_bit(
Yaowu Xuc27fc142016-08-22 16:08:15 -07009351 cm->fc->wedge_interintra_prob[bsize], mbmi->use_wedge_interintra);
9352 if (mbmi->use_wedge_interintra) {
Yue Chen5e606542017-05-24 17:03:17 -07009353 compmode_interintra_cost +=
Yaowu Xuf883b422016-08-30 14:01:10 -07009354 av1_cost_literal(get_interintra_wedge_bits(bsize));
Yaowu Xuc27fc142016-08-22 16:08:15 -07009355 }
9356 }
9357 } else if (is_interintra_allowed(mbmi)) {
Yue Chen5e606542017-05-24 17:03:17 -07009358 compmode_interintra_cost =
Yaowu Xuf883b422016-08-30 14:01:10 -07009359 av1_cost_bit(cm->fc->interintra_prob[size_group_lookup[bsize]], 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009360 }
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00009361#endif // CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07009362
Angie Chiang75c22092016-10-25 12:19:16 -07009363 if (pred_exists == 0) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07009364 int tmp_rate;
9365 int64_t tmp_dist;
Jingning Hanc44009c2017-05-06 11:36:49 -07009366 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, &orig_dst, bsize);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009367 model_rd_for_sb(cpi, bsize, x, xd, 0, MAX_MB_PLANE - 1, &tmp_rate,
9368 &tmp_dist, &skip_txfm_sb, &skip_sse_sb);
Urvang Joshi70006e42017-06-14 16:08:55 -07009369 rd = RDCOST(x->rdmult, rs + tmp_rate, tmp_dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009370 }
9371
Fergus Simpson3424c2d2017-03-09 11:48:15 -08009372 if (!is_comp_pred)
Rupert Swarbrick27e90292017-09-28 17:46:50 +01009373 args->single_filter[this_mode][refs[0]] =
9374 av1_extract_interp_filter(mbmi->interp_filters, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009375
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -08009376 if (args->modelled_rd != NULL) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07009377 if (is_comp_pred) {
9378 const int mode0 = compound_ref0_mode(this_mode);
9379 const int mode1 = compound_ref1_mode(this_mode);
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -08009380 const int64_t mrd = AOMMIN(args->modelled_rd[mode0][refs[0]],
9381 args->modelled_rd[mode1][refs[1]]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009382 if (rd / 4 * 3 > mrd && ref_best_rd < INT64_MAX) {
David Barkerac37fa32016-12-02 12:30:21 +00009383 restore_dst_buf(xd, orig_dst);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009384 return INT64_MAX;
9385 }
9386 } else if (!is_comp_interintra_pred) {
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -08009387 args->modelled_rd[this_mode][refs[0]] = rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009388 }
9389 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07009390
9391 if (cpi->sf.use_rd_breakout && ref_best_rd < INT64_MAX) {
9392 // if current pred_error modeled rd is substantially more than the best
9393 // so far, do not bother doing full rd
9394 if (rd / 2 > ref_best_rd) {
David Barkerac37fa32016-12-02 12:30:21 +00009395 restore_dst_buf(xd, orig_dst);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009396 return INT64_MAX;
9397 }
9398 }
9399
Yue Chen5e606542017-05-24 17:03:17 -07009400#if CONFIG_INTERINTRA
9401 rd_stats->rate += compmode_interintra_cost;
9402#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
9403 rate2_bmc_nocoeff += compmode_interintra_cost;
9404#endif
9405#endif
9406#if CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT
9407 rd_stats->rate += compmode_interinter_cost;
9408#endif
Yue Chen5e606542017-05-24 17:03:17 -07009409
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009410 ret_val = motion_mode_rd(
9411 cpi, x, bsize, rd_stats, rd_stats_y, rd_stats_uv, disable_skip, mode_mv,
9412 mi_row, mi_col, args, ref_best_rd, refs, rate_mv,
Yue Chen69f18e12016-09-08 14:48:15 -07009413#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009414 single_newmv, rate2_bmc_nocoeff, &best_bmc_mbmi, rate_mv_bmc,
Yue Chencb60b182016-10-13 15:18:22 -07009415#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009416 rs, &skip_txfm_sb, &skip_sse_sb, &orig_dst);
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08009417 if (ret_val != 0) return ret_val;
Angie Chiang76159122016-11-09 12:13:22 -08009418
Yaowu Xuc27fc142016-08-22 16:08:15 -07009419 return 0; // The rate-distortion cost will be re-calculated by caller.
9420}
9421
Alex Converse28744302017-04-13 14:46:22 -07009422#if CONFIG_INTRABC
Alex Converse28744302017-04-13 14:46:22 -07009423static int64_t rd_pick_intrabc_mode_sb(const AV1_COMP *cpi, MACROBLOCK *x,
Angie Chiang2a2a7dd2017-04-25 16:08:47 -07009424 RD_STATS *rd_cost, BLOCK_SIZE bsize,
Alex Converse28744302017-04-13 14:46:22 -07009425 int64_t best_rd) {
Alex Converse3d8adf32017-04-24 12:35:42 -07009426 const AV1_COMMON *const cm = &cpi->common;
RogerZhouca865462017-10-05 15:06:27 -07009427 if (!av1_allow_intrabc(bsize, cm)) return INT64_MAX;
Alex Converse3d8adf32017-04-24 12:35:42 -07009428
Alex Converse28744302017-04-13 14:46:22 -07009429 MACROBLOCKD *const xd = &x->e_mbd;
Alex Converse3d8adf32017-04-24 12:35:42 -07009430 const TileInfo *tile = &xd->tile;
9431 MODE_INFO *const mi = xd->mi[0];
9432 const int mi_row = -xd->mb_to_top_edge / (8 * MI_SIZE);
9433 const int mi_col = -xd->mb_to_left_edge / (8 * MI_SIZE);
9434 const int w = block_size_wide[bsize];
9435 const int h = block_size_high[bsize];
9436 const int sb_row = mi_row / MAX_MIB_SIZE;
Alex Converse861d7072017-05-15 14:19:53 -07009437 const int sb_col = mi_col / MAX_MIB_SIZE;
Alex Converse3d8adf32017-04-24 12:35:42 -07009438
Alex Converse44c2bad2017-05-11 09:36:10 -07009439 MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
9440 MV_REFERENCE_FRAME ref_frame = INTRA_FRAME;
9441 int_mv *const candidates = x->mbmi_ext->ref_mvs[ref_frame];
9442 av1_find_mv_refs(cm, xd, mi, ref_frame, &mbmi_ext->ref_mv_count[ref_frame],
9443 mbmi_ext->ref_mv_stack[ref_frame],
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009444 mbmi_ext->compound_mode_context, candidates, mi_row, mi_col,
9445 NULL, NULL, mbmi_ext->mode_context);
Alex Converse44c2bad2017-05-11 09:36:10 -07009446
9447 int_mv nearestmv, nearmv;
9448 av1_find_best_ref_mvs(0, candidates, &nearestmv, &nearmv);
9449
9450 int_mv dv_ref = nearestmv.as_int == 0 ? nearmv : nearestmv;
9451 if (dv_ref.as_int == 0) av1_find_ref_dv(&dv_ref, mi_row, mi_col);
9452 mbmi_ext->ref_mvs[INTRA_FRAME][0] = dv_ref;
Alex Converse3d8adf32017-04-24 12:35:42 -07009453
Alex Converse3d8adf32017-04-24 12:35:42 -07009454 struct buf_2d yv12_mb[MAX_MB_PLANE];
9455 av1_setup_pred_block(xd, yv12_mb, xd->cur_buf, mi_row, mi_col, NULL, NULL);
9456 for (int i = 0; i < MAX_MB_PLANE; ++i) {
9457 xd->plane[i].pre[0] = yv12_mb[i];
9458 }
9459
Alex Converse861d7072017-05-15 14:19:53 -07009460 enum IntrabcMotionDirection {
9461 IBC_MOTION_ABOVE,
9462 IBC_MOTION_LEFT,
9463 IBC_MOTION_DIRECTIONS
9464 };
Alex Converse3d8adf32017-04-24 12:35:42 -07009465
Alex Converse3d8adf32017-04-24 12:35:42 -07009466 MB_MODE_INFO *mbmi = &mi->mbmi;
9467 MB_MODE_INFO best_mbmi = *mbmi;
9468 RD_STATS best_rdcost = *rd_cost;
9469 int best_skip = x->skip;
Alex Converse861d7072017-05-15 14:19:53 -07009470
9471 for (enum IntrabcMotionDirection dir = IBC_MOTION_ABOVE;
9472 dir < IBC_MOTION_DIRECTIONS; ++dir) {
9473 const MvLimits tmp_mv_limits = x->mv_limits;
9474 switch (dir) {
9475 case IBC_MOTION_ABOVE:
9476 x->mv_limits.col_min = (tile->mi_col_start - mi_col) * MI_SIZE;
9477 x->mv_limits.col_max = (tile->mi_col_end - mi_col) * MI_SIZE - w;
9478 x->mv_limits.row_min = (tile->mi_row_start - mi_row) * MI_SIZE;
9479 x->mv_limits.row_max = (sb_row * MAX_MIB_SIZE - mi_row) * MI_SIZE - h;
9480 break;
9481 case IBC_MOTION_LEFT:
9482 x->mv_limits.col_min = (tile->mi_col_start - mi_col) * MI_SIZE;
9483 x->mv_limits.col_max = (sb_col * MAX_MIB_SIZE - mi_col) * MI_SIZE - w;
9484 // TODO(aconverse@google.com): Minimize the overlap between above and
9485 // left areas.
9486 x->mv_limits.row_min = (tile->mi_row_start - mi_row) * MI_SIZE;
9487 int bottom_coded_mi_edge =
9488 AOMMIN((sb_row + 1) * MAX_MIB_SIZE, tile->mi_row_end);
9489 x->mv_limits.row_max = (bottom_coded_mi_edge - mi_row) * MI_SIZE - h;
9490 break;
9491 default: assert(0);
9492 }
9493 assert(x->mv_limits.col_min >= tmp_mv_limits.col_min);
9494 assert(x->mv_limits.col_max <= tmp_mv_limits.col_max);
9495 assert(x->mv_limits.row_min >= tmp_mv_limits.row_min);
9496 assert(x->mv_limits.row_max <= tmp_mv_limits.row_max);
9497 av1_set_mv_search_range(&x->mv_limits, &dv_ref.as_mv);
9498
9499 if (x->mv_limits.col_max < x->mv_limits.col_min ||
9500 x->mv_limits.row_max < x->mv_limits.row_min) {
9501 x->mv_limits = tmp_mv_limits;
9502 continue;
9503 }
9504
9505 int step_param = cpi->mv_step_param;
9506 MV mvp_full = dv_ref.as_mv;
9507 mvp_full.col >>= 3;
9508 mvp_full.row >>= 3;
9509 int sadpb = x->sadperbit16;
9510 int cost_list[5];
RogerZhoucc5d35d2017-08-07 22:20:15 -07009511#if CONFIG_HASH_ME
RogerZhoud15e7c12017-09-26 08:49:28 -07009512 int bestsme = av1_full_pixel_search(
9513 cpi, x, bsize, &mvp_full, step_param, sadpb,
9514 cond_cost_list(cpi, cost_list), &dv_ref.as_mv, INT_MAX, 1,
9515 (MI_SIZE * mi_col), (MI_SIZE * mi_row), 1);
RogerZhoucc5d35d2017-08-07 22:20:15 -07009516#else
Alex Converse861d7072017-05-15 14:19:53 -07009517 int bestsme = av1_full_pixel_search(cpi, x, bsize, &mvp_full, step_param,
9518 sadpb, cond_cost_list(cpi, cost_list),
9519 &dv_ref.as_mv, INT_MAX, 1);
RogerZhoucc5d35d2017-08-07 22:20:15 -07009520#endif
Alex Converse861d7072017-05-15 14:19:53 -07009521
9522 x->mv_limits = tmp_mv_limits;
9523 if (bestsme == INT_MAX) continue;
9524 mvp_full = x->best_mv.as_mv;
9525 MV dv = {.row = mvp_full.row * 8, .col = mvp_full.col * 8 };
9526 if (mv_check_bounds(&x->mv_limits, &dv)) continue;
9527 if (!is_dv_valid(dv, tile, mi_row, mi_col, bsize)) continue;
9528
Alex Converse861d7072017-05-15 14:19:53 -07009529 memset(&mbmi->palette_mode_info, 0, sizeof(mbmi->palette_mode_info));
Alex Converse861d7072017-05-15 14:19:53 -07009530 mbmi->use_intrabc = 1;
9531 mbmi->mode = DC_PRED;
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04009532 mbmi->uv_mode = UV_DC_PRED;
Alex Converse861d7072017-05-15 14:19:53 -07009533 mbmi->mv[0].as_mv = dv;
Rupert Swarbrick27e90292017-09-28 17:46:50 +01009534 mbmi->interp_filters = av1_broadcast_interp_filter(BILINEAR);
Alex Converse861d7072017-05-15 14:19:53 -07009535 mbmi->skip = 0;
9536 x->skip = 0;
9537 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, NULL, bsize);
Alex Converse3d8adf32017-04-24 12:35:42 -07009538
Alex Conversed5d9b6c2017-05-23 15:23:45 -07009539 assert(x->mvcost == x->mv_cost_stack[0]);
9540 // TODO(aconverse@google.com): The full motion field defining discount
9541 // in MV_COST_WEIGHT is too large. Explore other values.
Alex Converse861d7072017-05-15 14:19:53 -07009542 int rate_mv = av1_mv_bit_cost(&dv, &dv_ref.as_mv, x->nmvjointcost,
Alex Conversed5d9b6c2017-05-23 15:23:45 -07009543 x->mvcost, MV_COST_WEIGHT_SUB);
Hui Su6c8584f2017-09-14 15:37:02 -07009544 const int rate_mode = x->intrabc_cost[1];
Alex Converse861d7072017-05-15 14:19:53 -07009545 RD_STATS rd_stats, rd_stats_uv;
9546 av1_subtract_plane(x, bsize, 0);
9547 super_block_yrd(cpi, x, &rd_stats, bsize, INT64_MAX);
9548 super_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
9549 av1_merge_rd_stats(&rd_stats, &rd_stats_uv);
Alex Converse3d8adf32017-04-24 12:35:42 -07009550#if CONFIG_RD_DEBUG
Alex Converse861d7072017-05-15 14:19:53 -07009551 mbmi->rd_stats = rd_stats;
Alex Converse3d8adf32017-04-24 12:35:42 -07009552#endif
9553
Alex Conversee16b2662017-05-24 14:00:00 -07009554#if CONFIG_VAR_TX
9555 // TODO(aconverse@google.com): Evaluate allowing VAR TX on intrabc blocks
9556 const int width = block_size_wide[bsize] >> tx_size_wide_log2[0];
9557 const int height = block_size_high[bsize] >> tx_size_high_log2[0];
9558 int idx, idy;
9559 for (idy = 0; idy < height; ++idy)
9560 for (idx = 0; idx < width; ++idx)
9561 mbmi->inter_tx_size[idy >> 1][idx >> 1] = mbmi->tx_size;
9562 mbmi->min_tx_size = get_min_tx_size(mbmi->tx_size);
9563#endif // CONFIG_VAR_TX
9564
Alex Converse861d7072017-05-15 14:19:53 -07009565 const aom_prob skip_prob = av1_get_skip_prob(cm, xd);
Alex Converse3d8adf32017-04-24 12:35:42 -07009566
Alex Converse861d7072017-05-15 14:19:53 -07009567 RD_STATS rdc_noskip;
9568 av1_init_rd_stats(&rdc_noskip);
9569 rdc_noskip.rate =
9570 rate_mode + rate_mv + rd_stats.rate + av1_cost_bit(skip_prob, 0);
9571 rdc_noskip.dist = rd_stats.dist;
Urvang Joshi70006e42017-06-14 16:08:55 -07009572 rdc_noskip.rdcost = RDCOST(x->rdmult, rdc_noskip.rate, rdc_noskip.dist);
Alex Converse861d7072017-05-15 14:19:53 -07009573 if (rdc_noskip.rdcost < best_rd) {
9574 best_rd = rdc_noskip.rdcost;
9575 best_mbmi = *mbmi;
9576 best_skip = x->skip;
9577 best_rdcost = rdc_noskip;
9578 }
Alex Converse3d8adf32017-04-24 12:35:42 -07009579
Alex Converse861d7072017-05-15 14:19:53 -07009580 x->skip = 1;
9581 mbmi->skip = 1;
9582 RD_STATS rdc_skip;
9583 av1_init_rd_stats(&rdc_skip);
9584 rdc_skip.rate = rate_mode + rate_mv + av1_cost_bit(skip_prob, 1);
9585 rdc_skip.dist = rd_stats.sse;
Urvang Joshi70006e42017-06-14 16:08:55 -07009586 rdc_skip.rdcost = RDCOST(x->rdmult, rdc_skip.rate, rdc_skip.dist);
Alex Converse861d7072017-05-15 14:19:53 -07009587 if (rdc_skip.rdcost < best_rd) {
9588 best_rd = rdc_skip.rdcost;
9589 best_mbmi = *mbmi;
9590 best_skip = x->skip;
9591 best_rdcost = rdc_skip;
9592 }
Alex Converse3d8adf32017-04-24 12:35:42 -07009593 }
9594 *mbmi = best_mbmi;
9595 *rd_cost = best_rdcost;
9596 x->skip = best_skip;
9597 return best_rd;
Alex Converse28744302017-04-13 14:46:22 -07009598}
9599#endif // CONFIG_INTRABC
9600
Urvang Joshi52648442016-10-13 17:27:51 -07009601void av1_rd_pick_intra_mode_sb(const AV1_COMP *cpi, MACROBLOCK *x,
Angie Chiang2a2a7dd2017-04-25 16:08:47 -07009602 RD_STATS *rd_cost, BLOCK_SIZE bsize,
Urvang Joshi52648442016-10-13 17:27:51 -07009603 PICK_MODE_CONTEXT *ctx, int64_t best_rd) {
9604 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009605 MACROBLOCKD *const xd = &x->e_mbd;
Luc Trudeau14fc5042017-06-16 12:40:29 -04009606 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009607 struct macroblockd_plane *const pd = xd->plane;
9608 int rate_y = 0, rate_uv = 0, rate_y_tokenonly = 0, rate_uv_tokenonly = 0;
9609 int y_skip = 0, uv_skip = 0;
9610 int64_t dist_y = 0, dist_uv = 0;
9611 TX_SIZE max_uv_tx_size;
Jingning Han271bb2c2016-12-14 12:34:46 -08009612 const int unify_bsize = CONFIG_CB4X4;
9613
Yaowu Xuc27fc142016-08-22 16:08:15 -07009614 ctx->skip = 0;
Luc Trudeau14fc5042017-06-16 12:40:29 -04009615 mbmi->ref_frame[0] = INTRA_FRAME;
9616 mbmi->ref_frame[1] = NONE_FRAME;
Alex Converse28744302017-04-13 14:46:22 -07009617#if CONFIG_INTRABC
Luc Trudeau14fc5042017-06-16 12:40:29 -04009618 mbmi->use_intrabc = 0;
9619 mbmi->mv[0].as_int = 0;
Alex Converse28744302017-04-13 14:46:22 -07009620#endif // CONFIG_INTRABC
Yaowu Xuc27fc142016-08-22 16:08:15 -07009621
Alex Conversed1b6fad2017-04-26 15:39:37 -07009622 const int64_t intra_yrd =
9623 (bsize >= BLOCK_8X8 || unify_bsize)
9624 ? rd_pick_intra_sby_mode(cpi, x, &rate_y, &rate_y_tokenonly, &dist_y,
9625 &y_skip, bsize, best_rd)
9626 : rd_pick_intra_sub_8x8_y_mode(cpi, x, &rate_y, &rate_y_tokenonly,
9627 &dist_y, &y_skip, best_rd);
9628
9629 if (intra_yrd < best_rd) {
Luc Trudeau14fc5042017-06-16 12:40:29 -04009630#if CONFIG_CFL
Luc Trudeau780d2492017-06-15 22:26:41 -04009631#if CONFIG_CB4X4
Luc Trudeaub05eeae2017-08-18 15:14:30 -04009632 // Only store reconstructed luma when there's chroma RDO. When there's no
9633 // chroma RDO, the reconstructed luma will be stored in encode_superblock().
9634 xd->cfl->store_y = !x->skip_chroma_rd;
Luc Trudeau780d2492017-06-15 22:26:41 -04009635#else
Luc Trudeaub05eeae2017-08-18 15:14:30 -04009636 xd->cfl->store_y = 1;
Luc Trudeau6e1cd782017-06-21 13:52:36 -04009637#endif // CONFIG_CB4X4
Luc Trudeaufcca37a2017-08-14 15:05:07 -04009638 if (xd->cfl->store_y) {
Luc Trudeaub05eeae2017-08-18 15:14:30 -04009639 // Perform one extra call to txfm_rd_in_plane(), with the values chosen
9640 // during luma RDO, so we can store reconstructed luma values
9641 RD_STATS this_rd_stats;
Luc Trudeau32306c22017-08-14 14:44:26 -04009642 txfm_rd_in_plane(x, cpi, &this_rd_stats, INT64_MAX, AOM_PLANE_Y,
9643 mbmi->sb_type, mbmi->tx_size,
9644 cpi->sf.use_fast_coef_costing);
Luc Trudeaufcca37a2017-08-14 15:05:07 -04009645 xd->cfl->store_y = 0;
Luc Trudeau32306c22017-08-14 14:44:26 -04009646 }
Luc Trudeau6e1cd782017-06-21 13:52:36 -04009647#endif // CONFIG_CFL
Luc Trudeau14fc5042017-06-16 12:40:29 -04009648 max_uv_tx_size = uv_txsize_lookup[bsize][mbmi->tx_size][pd[1].subsampling_x]
9649 [pd[1].subsampling_y];
9650 init_sbuv_mode(mbmi);
Jingning Han271bb2c2016-12-14 12:34:46 -08009651#if CONFIG_CB4X4
Alex Conversed1b6fad2017-04-26 15:39:37 -07009652 if (!x->skip_chroma_rd)
9653 rd_pick_intra_sbuv_mode(cpi, x, &rate_uv, &rate_uv_tokenonly, &dist_uv,
9654 &uv_skip, bsize, max_uv_tx_size);
Jingning Han271bb2c2016-12-14 12:34:46 -08009655#else
Alex Conversed1b6fad2017-04-26 15:39:37 -07009656 rd_pick_intra_sbuv_mode(cpi, x, &rate_uv, &rate_uv_tokenonly, &dist_uv,
9657 &uv_skip, AOMMAX(BLOCK_8X8, bsize), max_uv_tx_size);
Fergus Simpson4063a682017-02-28 16:52:22 -08009658#endif // CONFIG_CB4X4
Yaowu Xuc27fc142016-08-22 16:08:15 -07009659
Rupert Swarbrickc6cc1f52017-10-04 11:52:12 +01009660 if (y_skip && (uv_skip || x->skip_chroma_rd)) {
Alex Conversed1b6fad2017-04-26 15:39:37 -07009661 rd_cost->rate = rate_y + rate_uv - rate_y_tokenonly - rate_uv_tokenonly +
9662 av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
9663 rd_cost->dist = dist_y + dist_uv;
9664 } else {
9665 rd_cost->rate =
9666 rate_y + rate_uv + av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
9667 rd_cost->dist = dist_y + dist_uv;
9668 }
Urvang Joshi70006e42017-06-14 16:08:55 -07009669 rd_cost->rdcost = RDCOST(x->rdmult, rd_cost->rate, rd_cost->dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009670 } else {
Alex Conversed1b6fad2017-04-26 15:39:37 -07009671 rd_cost->rate = INT_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009672 }
9673
Alex Converse28744302017-04-13 14:46:22 -07009674#if CONFIG_INTRABC
Alex Conversed1b6fad2017-04-26 15:39:37 -07009675 if (rd_cost->rate != INT_MAX && rd_cost->rdcost < best_rd)
9676 best_rd = rd_cost->rdcost;
Alex Converse28744302017-04-13 14:46:22 -07009677 if (rd_pick_intrabc_mode_sb(cpi, x, rd_cost, bsize, best_rd) < best_rd) {
9678 ctx->skip = x->skip; // FIXME where is the proper place to set this?!
Alex Conversed1b6fad2017-04-26 15:39:37 -07009679 assert(rd_cost->rate != INT_MAX);
Urvang Joshi70006e42017-06-14 16:08:55 -07009680 rd_cost->rdcost = RDCOST(x->rdmult, rd_cost->rate, rd_cost->dist);
Alex Converse28744302017-04-13 14:46:22 -07009681 }
9682#endif
Alex Conversed1b6fad2017-04-26 15:39:37 -07009683 if (rd_cost->rate == INT_MAX) return;
Alex Converse28744302017-04-13 14:46:22 -07009684
Yaowu Xuc27fc142016-08-22 16:08:15 -07009685 ctx->mic = *xd->mi[0];
9686 ctx->mbmi_ext = *x->mbmi_ext;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009687}
9688
Yaowu Xuc27fc142016-08-22 16:08:15 -07009689// Do we have an internal image edge (e.g. formatting bars).
Urvang Joshi52648442016-10-13 17:27:51 -07009690int av1_internal_image_edge(const AV1_COMP *cpi) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07009691 return (cpi->oxcf.pass == 2) &&
9692 ((cpi->twopass.this_frame_stats.inactive_zone_rows > 0) ||
9693 (cpi->twopass.this_frame_stats.inactive_zone_cols > 0));
9694}
9695
9696// Checks to see if a super block is on a horizontal image edge.
9697// In most cases this is the "real" edge unless there are formatting
9698// bars embedded in the stream.
Urvang Joshi52648442016-10-13 17:27:51 -07009699int av1_active_h_edge(const AV1_COMP *cpi, int mi_row, int mi_step) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07009700 int top_edge = 0;
9701 int bottom_edge = cpi->common.mi_rows;
9702 int is_active_h_edge = 0;
9703
9704 // For two pass account for any formatting bars detected.
9705 if (cpi->oxcf.pass == 2) {
Urvang Joshi52648442016-10-13 17:27:51 -07009706 const TWO_PASS *const twopass = &cpi->twopass;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009707
9708 // The inactive region is specified in MBs not mi units.
9709 // The image edge is in the following MB row.
9710 top_edge += (int)(twopass->this_frame_stats.inactive_zone_rows * 2);
9711
9712 bottom_edge -= (int)(twopass->this_frame_stats.inactive_zone_rows * 2);
Yaowu Xuf883b422016-08-30 14:01:10 -07009713 bottom_edge = AOMMAX(top_edge, bottom_edge);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009714 }
9715
9716 if (((top_edge >= mi_row) && (top_edge < (mi_row + mi_step))) ||
9717 ((bottom_edge >= mi_row) && (bottom_edge < (mi_row + mi_step)))) {
9718 is_active_h_edge = 1;
9719 }
9720 return is_active_h_edge;
9721}
9722
9723// Checks to see if a super block is on a vertical image edge.
9724// In most cases this is the "real" edge unless there are formatting
9725// bars embedded in the stream.
Urvang Joshi52648442016-10-13 17:27:51 -07009726int av1_active_v_edge(const AV1_COMP *cpi, int mi_col, int mi_step) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07009727 int left_edge = 0;
9728 int right_edge = cpi->common.mi_cols;
9729 int is_active_v_edge = 0;
9730
9731 // For two pass account for any formatting bars detected.
9732 if (cpi->oxcf.pass == 2) {
Urvang Joshi52648442016-10-13 17:27:51 -07009733 const TWO_PASS *const twopass = &cpi->twopass;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009734
9735 // The inactive region is specified in MBs not mi units.
9736 // The image edge is in the following MB row.
9737 left_edge += (int)(twopass->this_frame_stats.inactive_zone_cols * 2);
9738
9739 right_edge -= (int)(twopass->this_frame_stats.inactive_zone_cols * 2);
Yaowu Xuf883b422016-08-30 14:01:10 -07009740 right_edge = AOMMAX(left_edge, right_edge);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009741 }
9742
9743 if (((left_edge >= mi_col) && (left_edge < (mi_col + mi_step))) ||
9744 ((right_edge >= mi_col) && (right_edge < (mi_col + mi_step)))) {
9745 is_active_v_edge = 1;
9746 }
9747 return is_active_v_edge;
9748}
9749
9750// Checks to see if a super block is at the edge of the active image.
9751// In most cases this is the "real" edge unless there are formatting
9752// bars embedded in the stream.
Urvang Joshi52648442016-10-13 17:27:51 -07009753int av1_active_edge_sb(const AV1_COMP *cpi, int mi_row, int mi_col) {
Yaowu Xuf883b422016-08-30 14:01:10 -07009754 return av1_active_h_edge(cpi, mi_row, cpi->common.mib_size) ||
9755 av1_active_v_edge(cpi, mi_col, cpi->common.mib_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009756}
9757
Urvang Joshi52648442016-10-13 17:27:51 -07009758static void restore_uv_color_map(const AV1_COMP *const cpi, MACROBLOCK *x) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07009759 MACROBLOCKD *const xd = &x->e_mbd;
9760 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
9761 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
9762 const BLOCK_SIZE bsize = mbmi->sb_type;
Urvang Joshic9e71d42017-08-09 18:58:33 -07009763 assert(bsize >= BLOCK_8X8);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009764 int src_stride = x->plane[1].src.stride;
9765 const uint8_t *const src_u = x->plane[1].src.buf;
9766 const uint8_t *const src_v = x->plane[2].src.buf;
9767 float *const data = x->palette_buffer->kmeans_data_buf;
9768 float centroids[2 * PALETTE_MAX_SIZE];
9769 uint8_t *const color_map = xd->plane[1].color_index_map;
9770 int r, c;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02009771#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07009772 const uint16_t *const src_u16 = CONVERT_TO_SHORTPTR(src_u);
9773 const uint16_t *const src_v16 = CONVERT_TO_SHORTPTR(src_v);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02009774#endif // CONFIG_HIGHBITDEPTH
Urvang Joshi56ba91b2017-01-10 13:22:09 -08009775 int plane_block_width, plane_block_height, rows, cols;
9776 av1_get_block_dimensions(bsize, 1, xd, &plane_block_width,
9777 &plane_block_height, &rows, &cols);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009778 (void)cpi;
9779
9780 for (r = 0; r < rows; ++r) {
9781 for (c = 0; c < cols; ++c) {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02009782#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07009783 if (cpi->common.use_highbitdepth) {
9784 data[(r * cols + c) * 2] = src_u16[r * src_stride + c];
9785 data[(r * cols + c) * 2 + 1] = src_v16[r * src_stride + c];
9786 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02009787#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07009788 data[(r * cols + c) * 2] = src_u[r * src_stride + c];
9789 data[(r * cols + c) * 2 + 1] = src_v[r * src_stride + c];
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02009790#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07009791 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02009792#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07009793 }
9794 }
9795
9796 for (r = 1; r < 3; ++r) {
9797 for (c = 0; c < pmi->palette_size[1]; ++c) {
9798 centroids[c * 2 + r - 1] = pmi->palette_colors[r * PALETTE_MAX_SIZE + c];
9799 }
9800 }
9801
Yaowu Xuf883b422016-08-30 14:01:10 -07009802 av1_calc_indices(data, centroids, color_map, rows * cols,
9803 pmi->palette_size[1], 2);
Urvang Joshi56ba91b2017-01-10 13:22:09 -08009804 extend_palette_color_map(color_map, cols, rows, plane_block_width,
9805 plane_block_height);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009806}
9807
hui su5db97432016-10-14 16:10:14 -07009808#if CONFIG_FILTER_INTRA
9809static void pick_filter_intra_interframe(
Luc Trudeau9d4cbb82017-07-27 17:01:32 -04009810 const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize, int mi_row,
9811 int mi_col, int *rate_uv_intra, int *rate_uv_tokenonly, int64_t *dist_uv,
9812 int *skip_uv, UV_PREDICTION_MODE *mode_uv,
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04009813 FILTER_INTRA_MODE_INFO *filter_intra_mode_info_uv,
hui su5db97432016-10-14 16:10:14 -07009814#if CONFIG_EXT_INTRA
9815 int8_t *uv_angle_delta,
9816#endif // CONFIG_EXT_INTRA
Urvang Joshic6300aa2017-06-01 14:46:23 -07009817 PALETTE_MODE_INFO *pmi_uv, int palette_ctx, int skip_mask,
9818 unsigned int *ref_costs_single, int64_t *best_rd, int64_t *best_intra_rd,
9819 PREDICTION_MODE *best_intra_mode, int *best_mode_index, int *best_skip2,
9820 int *best_mode_skippable,
Yaowu Xuc27fc142016-08-22 16:08:15 -07009821#if CONFIG_SUPERTX
9822 int *returnrate_nocoef,
9823#endif // CONFIG_SUPERTX
Angie Chiang2a2a7dd2017-04-25 16:08:47 -07009824 int64_t *best_pred_rd, MB_MODE_INFO *best_mbmode, RD_STATS *rd_cost) {
Urvang Joshi52648442016-10-13 17:27:51 -07009825 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009826 MACROBLOCKD *const xd = &x->e_mbd;
9827 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
9828 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
Urvang Joshic9e71d42017-08-09 18:58:33 -07009829 const int try_palette = can_use_palette(cpi, mbmi);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009830 int rate2 = 0, rate_y = INT_MAX, skippable = 0, rate_uv, rate_dummy, i;
9831 int dc_mode_index;
Yue Chenb23d00a2017-07-28 17:01:21 -07009832 const int *const intra_mode_cost = x->mbmode_cost[size_group_lookup[bsize]];
hui su8f4cc0a2017-01-13 15:14:49 -08009833 int64_t distortion2 = 0, distortion_y = 0, this_rd = *best_rd;
9834 int64_t distortion_uv, model_rd = INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009835 TX_SIZE uv_tx;
9836
9837 for (i = 0; i < MAX_MODES; ++i)
Yaowu Xuf883b422016-08-30 14:01:10 -07009838 if (av1_mode_order[i].mode == DC_PRED &&
9839 av1_mode_order[i].ref_frame[0] == INTRA_FRAME)
Yaowu Xuc27fc142016-08-22 16:08:15 -07009840 break;
9841 dc_mode_index = i;
9842 assert(i < MAX_MODES);
9843
9844 // TODO(huisu): use skip_mask for further speedup.
9845 (void)skip_mask;
9846 mbmi->mode = DC_PRED;
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04009847 mbmi->uv_mode = UV_DC_PRED;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009848 mbmi->ref_frame[0] = INTRA_FRAME;
Emil Keyder01770b32017-01-20 18:03:11 -05009849 mbmi->ref_frame[1] = NONE_FRAME;
hui su5db97432016-10-14 16:10:14 -07009850 if (!rd_pick_filter_intra_sby(cpi, x, &rate_dummy, &rate_y, &distortion_y,
9851 &skippable, bsize, intra_mode_cost[mbmi->mode],
hui su8f4cc0a2017-01-13 15:14:49 -08009852 &this_rd, &model_rd, 0)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07009853 return;
hui su5db97432016-10-14 16:10:14 -07009854 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07009855 if (rate_y == INT_MAX) return;
9856
Debargha Mukherjee2f123402016-08-30 17:43:38 -07009857 uv_tx = uv_txsize_lookup[bsize][mbmi->tx_size][xd->plane[1].subsampling_x]
9858 [xd->plane[1].subsampling_y];
Yaowu Xuc27fc142016-08-22 16:08:15 -07009859 if (rate_uv_intra[uv_tx] == INT_MAX) {
Luc Trudeau9d4cbb82017-07-27 17:01:32 -04009860 choose_intra_uv_mode(cpi, x, bsize, uv_tx, &rate_uv_intra[uv_tx],
Yaowu Xuc27fc142016-08-22 16:08:15 -07009861 &rate_uv_tokenonly[uv_tx], &dist_uv[uv_tx],
9862 &skip_uv[uv_tx], &mode_uv[uv_tx]);
9863 if (cm->allow_screen_content_tools) pmi_uv[uv_tx] = *pmi;
hui su5db97432016-10-14 16:10:14 -07009864 filter_intra_mode_info_uv[uv_tx] = mbmi->filter_intra_mode_info;
9865#if CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07009866 uv_angle_delta[uv_tx] = mbmi->angle_delta[1];
hui su5db97432016-10-14 16:10:14 -07009867#endif // CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07009868 }
9869
9870 rate_uv = rate_uv_tokenonly[uv_tx];
9871 distortion_uv = dist_uv[uv_tx];
9872 skippable = skippable && skip_uv[uv_tx];
9873 mbmi->uv_mode = mode_uv[uv_tx];
9874 if (cm->allow_screen_content_tools) {
9875 pmi->palette_size[1] = pmi_uv[uv_tx].palette_size[1];
9876 memcpy(pmi->palette_colors + PALETTE_MAX_SIZE,
9877 pmi_uv[uv_tx].palette_colors + PALETTE_MAX_SIZE,
9878 2 * PALETTE_MAX_SIZE * sizeof(pmi->palette_colors[0]));
9879 }
hui su5db97432016-10-14 16:10:14 -07009880#if CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07009881 mbmi->angle_delta[1] = uv_angle_delta[uv_tx];
hui su5db97432016-10-14 16:10:14 -07009882#endif // CONFIG_EXT_INTRA
9883 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] =
9884 filter_intra_mode_info_uv[uv_tx].use_filter_intra_mode[1];
9885 if (filter_intra_mode_info_uv[uv_tx].use_filter_intra_mode[1]) {
9886 mbmi->filter_intra_mode_info.filter_intra_mode[1] =
9887 filter_intra_mode_info_uv[uv_tx].filter_intra_mode[1];
Yaowu Xuc27fc142016-08-22 16:08:15 -07009888 }
9889
9890 rate2 = rate_y + intra_mode_cost[mbmi->mode] + rate_uv +
Yue Chenb23d00a2017-07-28 17:01:21 -07009891 x->intra_uv_mode_cost[mbmi->mode][mbmi->uv_mode];
Rupert Swarbrick6f9cd942017-08-02 15:57:18 +01009892 if (try_palette && mbmi->mode == DC_PRED)
Yaowu Xuf883b422016-08-30 14:01:10 -07009893 rate2 += av1_cost_bit(
9894 av1_default_palette_y_mode_prob[bsize - BLOCK_8X8][palette_ctx], 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009895
9896 if (!xd->lossless[mbmi->segment_id]) {
9897 // super_block_yrd above includes the cost of the tx_size in the
9898 // tokenonly rate, but for intra blocks, tx_size is always coded
9899 // (prediction granularity), so we account for it in the full rate,
9900 // not the tokenonly rate.
Urvang Joshifeb925f2016-12-05 10:37:29 -08009901 rate_y -= tx_size_cost(cpi, x, bsize, mbmi->tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009902 }
9903
hui su5db97432016-10-14 16:10:14 -07009904 rate2 += av1_cost_bit(cm->fc->filter_intra_probs[0],
9905 mbmi->filter_intra_mode_info.use_filter_intra_mode[0]);
9906 rate2 += write_uniform_cost(
9907 FILTER_INTRA_MODES, mbmi->filter_intra_mode_info.filter_intra_mode[0]);
9908#if CONFIG_EXT_INTRA
Luc Trudeauf24a35f2017-09-11 11:56:33 -04009909 if (av1_is_directional_mode(get_uv_mode(mbmi->uv_mode), bsize) &&
Joe Young830d4ce2017-05-30 17:48:13 -07009910 av1_use_angle_delta(bsize)) {
hui su0a6731f2017-04-26 15:23:47 -07009911 rate2 += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
9912 MAX_ANGLE_DELTA + mbmi->angle_delta[1]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009913 }
hui su5db97432016-10-14 16:10:14 -07009914#endif // CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07009915 if (mbmi->mode == DC_PRED) {
hui su5db97432016-10-14 16:10:14 -07009916 rate2 +=
9917 av1_cost_bit(cpi->common.fc->filter_intra_probs[1],
9918 mbmi->filter_intra_mode_info.use_filter_intra_mode[1]);
9919 if (mbmi->filter_intra_mode_info.use_filter_intra_mode[1])
9920 rate2 +=
9921 write_uniform_cost(FILTER_INTRA_MODES,
9922 mbmi->filter_intra_mode_info.filter_intra_mode[1]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009923 }
9924 distortion2 = distortion_y + distortion_uv;
Jingning Han18c53c82017-02-17 14:49:57 -08009925 av1_encode_intra_block_plane((AV1_COMMON *)cm, x, bsize, 0, 0, mi_row,
9926 mi_col);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009927
9928 rate2 += ref_costs_single[INTRA_FRAME];
9929
9930 if (skippable) {
9931 rate2 -= (rate_y + rate_uv);
9932 rate_y = 0;
9933 rate_uv = 0;
Yaowu Xuf883b422016-08-30 14:01:10 -07009934 rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009935 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -07009936 rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009937 }
Urvang Joshi70006e42017-06-14 16:08:55 -07009938 this_rd = RDCOST(x->rdmult, rate2, distortion2);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009939
9940 if (this_rd < *best_intra_rd) {
9941 *best_intra_rd = this_rd;
9942 *best_intra_mode = mbmi->mode;
9943 }
9944 for (i = 0; i < REFERENCE_MODES; ++i)
Yaowu Xuf883b422016-08-30 14:01:10 -07009945 best_pred_rd[i] = AOMMIN(best_pred_rd[i], this_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009946
9947 if (this_rd < *best_rd) {
9948 *best_mode_index = dc_mode_index;
9949 mbmi->mv[0].as_int = 0;
9950 rd_cost->rate = rate2;
9951#if CONFIG_SUPERTX
9952 if (x->skip)
9953 *returnrate_nocoef = rate2;
9954 else
9955 *returnrate_nocoef = rate2 - rate_y - rate_uv;
Yaowu Xuf883b422016-08-30 14:01:10 -07009956 *returnrate_nocoef -= av1_cost_bit(av1_get_skip_prob(cm, xd), skippable);
9957 *returnrate_nocoef -= av1_cost_bit(av1_get_intra_inter_prob(cm, xd),
9958 mbmi->ref_frame[0] != INTRA_FRAME);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009959#endif // CONFIG_SUPERTX
9960 rd_cost->dist = distortion2;
9961 rd_cost->rdcost = this_rd;
9962 *best_rd = this_rd;
9963 *best_mbmode = *mbmi;
9964 *best_skip2 = 0;
9965 *best_mode_skippable = skippable;
9966 }
9967}
hui su5db97432016-10-14 16:10:14 -07009968#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07009969
Yue Chencb60b182016-10-13 15:18:22 -07009970#if CONFIG_MOTION_VAR
Yaowu Xuf883b422016-08-30 14:01:10 -07009971static void calc_target_weighted_pred(const AV1_COMMON *cm, const MACROBLOCK *x,
9972 const MACROBLOCKD *xd, int mi_row,
9973 int mi_col, const uint8_t *above,
9974 int above_stride, const uint8_t *left,
Yue Chene9638cc2016-10-10 12:37:54 -07009975 int left_stride);
Yue Chencb60b182016-10-13 15:18:22 -07009976#endif // CONFIG_MOTION_VAR
Yaowu Xuc27fc142016-08-22 16:08:15 -07009977
Urvang Joshi52648442016-10-13 17:27:51 -07009978void av1_rd_pick_inter_mode_sb(const AV1_COMP *cpi, TileDataEnc *tile_data,
Yaowu Xuf883b422016-08-30 14:01:10 -07009979 MACROBLOCK *x, int mi_row, int mi_col,
Angie Chiang2a2a7dd2017-04-25 16:08:47 -07009980 RD_STATS *rd_cost,
Yaowu Xuc27fc142016-08-22 16:08:15 -07009981#if CONFIG_SUPERTX
Yaowu Xuf883b422016-08-30 14:01:10 -07009982 int *returnrate_nocoef,
Yaowu Xuc27fc142016-08-22 16:08:15 -07009983#endif // CONFIG_SUPERTX
Yaowu Xuf883b422016-08-30 14:01:10 -07009984 BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
9985 int64_t best_rd_so_far) {
Urvang Joshi52648442016-10-13 17:27:51 -07009986 const AV1_COMMON *const cm = &cpi->common;
9987 const RD_OPT *const rd_opt = &cpi->rd;
9988 const SPEED_FEATURES *const sf = &cpi->sf;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009989 MACROBLOCKD *const xd = &x->e_mbd;
9990 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Urvang Joshic9e71d42017-08-09 18:58:33 -07009991 const int try_palette = can_use_palette(cpi, mbmi);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009992 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
9993 MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
9994 const struct segmentation *const seg = &cm->seg;
9995 PREDICTION_MODE this_mode;
9996 MV_REFERENCE_FRAME ref_frame, second_ref_frame;
9997 unsigned char segment_id = mbmi->segment_id;
9998 int comp_pred, i, k;
9999 int_mv frame_mv[MB_MODE_COUNT][TOTAL_REFS_PER_FRAME];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010000#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070010001 int_mv frame_comp_mv[MB_MODE_COUNT][TOTAL_REFS_PER_FRAME];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010002#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -070010003 struct buf_2d yv12_mb[TOTAL_REFS_PER_FRAME][MAX_MB_PLANE];
Yaowu Xuc27fc142016-08-22 16:08:15 -070010004 int_mv single_newmv[TOTAL_REFS_PER_FRAME] = { { 0 } };
Zoe Liu7f24e1b2017-03-17 17:42:05 -070010005 int single_newmv_rate[TOTAL_REFS_PER_FRAME] = { 0 };
10006 int64_t modelled_rd[MB_MODE_COUNT][TOTAL_REFS_PER_FRAME];
Yaowu Xuc27fc142016-08-22 16:08:15 -070010007 static const int flag_list[TOTAL_REFS_PER_FRAME] = {
10008 0,
Yaowu Xuf883b422016-08-30 14:01:10 -070010009 AOM_LAST_FLAG,
Yaowu Xuc27fc142016-08-22 16:08:15 -070010010#if CONFIG_EXT_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -070010011 AOM_LAST2_FLAG,
10012 AOM_LAST3_FLAG,
Yaowu Xuc27fc142016-08-22 16:08:15 -070010013#endif // CONFIG_EXT_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -070010014 AOM_GOLD_FLAG,
Yaowu Xuc27fc142016-08-22 16:08:15 -070010015#if CONFIG_EXT_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -070010016 AOM_BWD_FLAG,
Zoe Liue9b15e22017-07-19 15:53:01 -070010017 AOM_ALT2_FLAG,
Yaowu Xuc27fc142016-08-22 16:08:15 -070010018#endif // CONFIG_EXT_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -070010019 AOM_ALT_FLAG
Yaowu Xuc27fc142016-08-22 16:08:15 -070010020 };
10021 int64_t best_rd = best_rd_so_far;
10022 int best_rate_y = INT_MAX, best_rate_uv = INT_MAX;
10023 int64_t best_pred_diff[REFERENCE_MODES];
10024 int64_t best_pred_rd[REFERENCE_MODES];
10025 MB_MODE_INFO best_mbmode;
Yaowu Xu4306b6e2016-09-27 12:55:32 -070010026 int rate_skip0 = av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
10027 int rate_skip1 = av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010028 int best_mode_skippable = 0;
10029 int midx, best_mode_index = -1;
10030 unsigned int ref_costs_single[TOTAL_REFS_PER_FRAME];
Zoe Liuc082bbc2017-05-17 13:31:37 -070010031#if CONFIG_EXT_COMP_REFS
10032 unsigned int ref_costs_comp[TOTAL_REFS_PER_FRAME][TOTAL_REFS_PER_FRAME];
10033#else
Yaowu Xuc27fc142016-08-22 16:08:15 -070010034 unsigned int ref_costs_comp[TOTAL_REFS_PER_FRAME];
Zoe Liuc082bbc2017-05-17 13:31:37 -070010035#endif // CONFIG_EXT_COMP_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -070010036 aom_prob comp_mode_p;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010037 int64_t best_intra_rd = INT64_MAX;
10038 unsigned int best_pred_sse = UINT_MAX;
10039 PREDICTION_MODE best_intra_mode = DC_PRED;
Urvang Joshifeb925f2016-12-05 10:37:29 -080010040 int rate_uv_intra[TX_SIZES_ALL], rate_uv_tokenonly[TX_SIZES_ALL];
10041 int64_t dist_uvs[TX_SIZES_ALL];
10042 int skip_uvs[TX_SIZES_ALL];
Luc Trudeaud6d9eee2017-07-12 12:36:50 -040010043 UV_PREDICTION_MODE mode_uv[TX_SIZES_ALL];
Urvang Joshifeb925f2016-12-05 10:37:29 -080010044 PALETTE_MODE_INFO pmi_uv[TX_SIZES_ALL];
Yaowu Xuc27fc142016-08-22 16:08:15 -070010045#if CONFIG_EXT_INTRA
Urvang Joshifeb925f2016-12-05 10:37:29 -080010046 int8_t uv_angle_delta[TX_SIZES_ALL];
Yaowu Xuc27fc142016-08-22 16:08:15 -070010047 int is_directional_mode, angle_stats_ready = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010048 uint8_t directional_mode_skip_mask[INTRA_MODES];
10049#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -070010050#if CONFIG_FILTER_INTRA
10051 int8_t dc_skipped = 1;
Urvang Joshifeb925f2016-12-05 10:37:29 -080010052 FILTER_INTRA_MODE_INFO filter_intra_mode_info_uv[TX_SIZES_ALL];
hui su5db97432016-10-14 16:10:14 -070010053#endif // CONFIG_FILTER_INTRA
Yaowu Xuf883b422016-08-30 14:01:10 -070010054 const int intra_cost_penalty = av1_get_intra_cost_penalty(
Yaowu Xuc27fc142016-08-22 16:08:15 -070010055 cm->base_qindex, cm->y_dc_delta_q, cm->bit_depth);
Yue Chenb23d00a2017-07-28 17:01:21 -070010056 const int *const intra_mode_cost = x->mbmode_cost[size_group_lookup[bsize]];
Yaowu Xuc27fc142016-08-22 16:08:15 -070010057 int best_skip2 = 0;
Zoe Liu97ad0582017-02-09 10:51:00 -080010058 uint16_t ref_frame_skip_mask[2] = { 0 };
Yaowu Xuc27fc142016-08-22 16:08:15 -070010059 uint32_t mode_skip_mask[TOTAL_REFS_PER_FRAME] = { 0 };
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010060#if CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010061 MV_REFERENCE_FRAME best_single_inter_ref = LAST_FRAME;
10062 int64_t best_single_inter_rd = INT64_MAX;
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010063#endif // CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010064 int mode_skip_start = sf->mode_skip_start + 1;
10065 const int *const rd_threshes = rd_opt->threshes[segment_id][bsize];
10066 const int *const rd_thresh_freq_fact = tile_data->thresh_freq_fact[bsize];
10067 int64_t mode_threshold[MAX_MODES];
10068 int *mode_map = tile_data->mode_map[bsize];
10069 const int mode_search_skip_flags = sf->mode_search_skip_flags;
Yushin Cho77bba8d2016-11-04 16:36:56 -070010070#if CONFIG_PVQ
10071 od_rollback_buffer pre_buf;
Fergus Simpson4063a682017-02-28 16:52:22 -080010072#endif // CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -070010073
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080010074 HandleInterModeArgs args = {
Fergus Simpson073c6f32017-02-17 12:13:48 -080010075#if CONFIG_MOTION_VAR
10076 { NULL },
10077 { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE },
10078 { NULL },
10079 { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE },
10080#endif // CONFIG_MOTION_VAR
Fergus Simpson073c6f32017-02-17 12:13:48 -080010081 NULL,
10082 NULL,
10083 NULL,
Fergus Simpson3424c2d2017-03-09 11:48:15 -080010084 { { 0 } },
Fergus Simpson073c6f32017-02-17 12:13:48 -080010085 };
10086
Jingning Hanae5cfde2016-11-30 12:01:44 -080010087 const int rows = block_size_high[bsize];
10088 const int cols = block_size_wide[bsize];
Urvang Joshib100db72016-10-12 16:28:56 -070010089 int palette_ctx = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010090 const MODE_INFO *above_mi = xd->above_mi;
10091 const MODE_INFO *left_mi = xd->left_mi;
Yue Chencb60b182016-10-13 15:18:22 -070010092#if CONFIG_MOTION_VAR
Yaowu Xuc27fc142016-08-22 16:08:15 -070010093 int dst_width1[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
10094 int dst_width2[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
10095 int dst_height1[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
10096 int dst_height2[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
Yaowu Xuc27fc142016-08-22 16:08:15 -070010097
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020010098#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070010099 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
10100 int len = sizeof(uint16_t);
Jingning Hand064cf02017-06-01 10:00:39 -070010101 args.above_pred_buf[0] = CONVERT_TO_BYTEPTR(x->above_pred_buf);
10102 args.above_pred_buf[1] =
10103 CONVERT_TO_BYTEPTR(x->above_pred_buf + MAX_SB_SQUARE * len);
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080010104 args.above_pred_buf[2] =
Jingning Hand064cf02017-06-01 10:00:39 -070010105 CONVERT_TO_BYTEPTR(x->above_pred_buf + 2 * MAX_SB_SQUARE * len);
10106 args.left_pred_buf[0] = CONVERT_TO_BYTEPTR(x->left_pred_buf);
10107 args.left_pred_buf[1] =
10108 CONVERT_TO_BYTEPTR(x->left_pred_buf + MAX_SB_SQUARE * len);
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080010109 args.left_pred_buf[2] =
Jingning Hand064cf02017-06-01 10:00:39 -070010110 CONVERT_TO_BYTEPTR(x->left_pred_buf + 2 * MAX_SB_SQUARE * len);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010111 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020010112#endif // CONFIG_HIGHBITDEPTH
Jingning Hand064cf02017-06-01 10:00:39 -070010113 args.above_pred_buf[0] = x->above_pred_buf;
10114 args.above_pred_buf[1] = x->above_pred_buf + MAX_SB_SQUARE;
10115 args.above_pred_buf[2] = x->above_pred_buf + 2 * MAX_SB_SQUARE;
10116 args.left_pred_buf[0] = x->left_pred_buf;
10117 args.left_pred_buf[1] = x->left_pred_buf + MAX_SB_SQUARE;
10118 args.left_pred_buf[2] = x->left_pred_buf + 2 * MAX_SB_SQUARE;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020010119#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070010120 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020010121#endif // CONFIG_HIGHBITDEPTH
Yue Chencb60b182016-10-13 15:18:22 -070010122#endif // CONFIG_MOTION_VAR
Yaowu Xuc27fc142016-08-22 16:08:15 -070010123
Yaowu Xuf883b422016-08-30 14:01:10 -070010124 av1_zero(best_mbmode);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010125
Urvang Joshib100db72016-10-12 16:28:56 -070010126 av1_zero(pmi_uv);
hui su9bc1d8d2017-03-24 12:36:03 -070010127 if (try_palette) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070010128 if (above_mi)
10129 palette_ctx += (above_mi->mbmi.palette_mode_info.palette_size[0] > 0);
10130 if (left_mi)
10131 palette_ctx += (left_mi->mbmi.palette_mode_info.palette_size[0] > 0);
10132 }
10133
Yaowu Xuc27fc142016-08-22 16:08:15 -070010134 estimate_ref_frame_costs(cm, xd, segment_id, ref_costs_single, ref_costs_comp,
10135 &comp_mode_p);
10136
10137 for (i = 0; i < REFERENCE_MODES; ++i) best_pred_rd[i] = INT64_MAX;
Urvang Joshifeb925f2016-12-05 10:37:29 -080010138 for (i = 0; i < TX_SIZES_ALL; i++) rate_uv_intra[i] = INT_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010139 for (i = 0; i < TOTAL_REFS_PER_FRAME; ++i) x->pred_sse[i] = INT_MAX;
10140 for (i = 0; i < MB_MODE_COUNT; ++i) {
10141 for (k = 0; k < TOTAL_REFS_PER_FRAME; ++k) {
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080010142 args.single_filter[i][k] = SWITCHABLE;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010143 }
10144 }
10145
10146 rd_cost->rate = INT_MAX;
10147#if CONFIG_SUPERTX
10148 *returnrate_nocoef = INT_MAX;
10149#endif // CONFIG_SUPERTX
10150
10151 for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
10152 x->pred_mv_sad[ref_frame] = INT_MAX;
10153 x->mbmi_ext->mode_context[ref_frame] = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010154 x->mbmi_ext->compound_mode_context[ref_frame] = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010155 if (cpi->ref_frame_flags & flag_list[ref_frame]) {
10156 assert(get_ref_frame_buffer(cpi, ref_frame) != NULL);
10157 setup_buffer_inter(cpi, x, ref_frame, bsize, mi_row, mi_col,
10158 frame_mv[NEARESTMV], frame_mv[NEARMV], yv12_mb);
10159 }
10160 frame_mv[NEWMV][ref_frame].as_int = INVALID_MV;
Sarah Parkere5299862016-08-16 14:57:37 -070010161#if CONFIG_GLOBAL_MOTION
10162 frame_mv[ZEROMV][ref_frame].as_int =
Sarah Parkerae7c4582017-02-28 16:30:30 -080010163 gm_get_motion_vector(&cm->global_motion[ref_frame],
Debargha Mukherjeefebb59c2017-03-02 12:23:45 -080010164 cm->allow_high_precision_mv, bsize, mi_col, mi_row,
RogerZhou3b635242017-09-19 10:06:46 -070010165 0
10166#if CONFIG_AMVR
10167 ,
10168 cm->cur_frame_mv_precision_level
10169#endif
10170 )
David Barkercdcac6d2016-12-01 17:04:16 +000010171 .as_int;
Sarah Parkere5299862016-08-16 14:57:37 -070010172#else // CONFIG_GLOBAL_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070010173 frame_mv[ZEROMV][ref_frame].as_int = 0;
Sarah Parkere5299862016-08-16 14:57:37 -070010174#endif // CONFIG_GLOBAL_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070010175 frame_mv[NEW_NEWMV][ref_frame].as_int = INVALID_MV;
Zoe Liu85b66462017-04-20 14:28:19 -070010176#if CONFIG_COMPOUND_SINGLEREF
10177 frame_mv[SR_NEW_NEWMV][ref_frame].as_int = INVALID_MV;
10178 frame_comp_mv[SR_NEW_NEWMV][ref_frame].as_int = INVALID_MV;
10179#endif // CONFIG_COMPOUND_SINGLEREF
Sarah Parkerc2d38712017-01-24 15:15:41 -080010180#if CONFIG_GLOBAL_MOTION
10181 frame_mv[ZERO_ZEROMV][ref_frame].as_int =
Sarah Parkerae7c4582017-02-28 16:30:30 -080010182 gm_get_motion_vector(&cm->global_motion[ref_frame],
Debargha Mukherjeefebb59c2017-03-02 12:23:45 -080010183 cm->allow_high_precision_mv, bsize, mi_col, mi_row,
RogerZhou3b635242017-09-19 10:06:46 -070010184 0
10185#if CONFIG_AMVR
10186 ,
10187 cm->cur_frame_mv_precision_level
10188#endif
10189 )
Sarah Parkerc2d38712017-01-24 15:15:41 -080010190 .as_int;
10191#else // CONFIG_GLOBAL_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070010192 frame_mv[ZERO_ZEROMV][ref_frame].as_int = 0;
Sarah Parkerc2d38712017-01-24 15:15:41 -080010193#endif // CONFIG_GLOBAL_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070010194 }
10195
Yaowu Xuc27fc142016-08-22 16:08:15 -070010196 for (; ref_frame < MODE_CTX_REF_FRAMES; ++ref_frame) {
10197 MODE_INFO *const mi = xd->mi[0];
10198 int_mv *const candidates = x->mbmi_ext->ref_mvs[ref_frame];
10199 x->mbmi_ext->mode_context[ref_frame] = 0;
Yaowu Xuf883b422016-08-30 14:01:10 -070010200 av1_find_mv_refs(cm, xd, mi, ref_frame, &mbmi_ext->ref_mv_count[ref_frame],
10201 mbmi_ext->ref_mv_stack[ref_frame],
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010202 mbmi_ext->compound_mode_context, candidates, mi_row,
10203 mi_col, NULL, NULL, mbmi_ext->mode_context);
Jingning Han731af492016-11-17 11:53:23 -080010204 if (mbmi_ext->ref_mv_count[ref_frame] < 2) {
10205 MV_REFERENCE_FRAME rf[2];
10206 av1_set_ref_frame(rf, ref_frame);
David Barkercdcac6d2016-12-01 17:04:16 +000010207 if (mbmi_ext->ref_mvs[rf[0]][0].as_int !=
10208 frame_mv[ZEROMV][rf[0]].as_int ||
10209 mbmi_ext->ref_mvs[rf[0]][1].as_int !=
10210 frame_mv[ZEROMV][rf[0]].as_int ||
10211 mbmi_ext->ref_mvs[rf[1]][0].as_int !=
10212 frame_mv[ZEROMV][rf[1]].as_int ||
10213 mbmi_ext->ref_mvs[rf[1]][1].as_int != frame_mv[ZEROMV][rf[1]].as_int)
Jingning Han731af492016-11-17 11:53:23 -080010214 mbmi_ext->mode_context[ref_frame] &= ~(1 << ALL_ZERO_FLAG_OFFSET);
10215 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070010216 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070010217
Yue Chencb60b182016-10-13 15:18:22 -070010218#if CONFIG_MOTION_VAR
Yue Chen5329a2b2017-02-28 17:33:00 +080010219 av1_count_overlappable_neighbors(cm, xd, mi_row, mi_col);
Jingning Hanad586b92017-05-23 10:24:57 -070010220
Yue Chenf7ba6472017-04-19 11:08:58 -070010221 if (check_num_overlappable_neighbors(mbmi) &&
10222 is_motion_variation_allowed_bsize(bsize)) {
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080010223 av1_build_prediction_by_above_preds(cm, xd, mi_row, mi_col,
10224 args.above_pred_buf, dst_width1,
10225 dst_height1, args.above_pred_stride);
Yue Chen5329a2b2017-02-28 17:33:00 +080010226 av1_build_prediction_by_left_preds(cm, xd, mi_row, mi_col,
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080010227 args.left_pred_buf, dst_width2,
10228 dst_height2, args.left_pred_stride);
Jingning Han91d9a792017-04-18 12:01:52 -070010229 av1_setup_dst_planes(xd->plane, bsize, get_frame_new_buffer(cm), mi_row,
10230 mi_col);
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080010231 calc_target_weighted_pred(cm, x, xd, mi_row, mi_col, args.above_pred_buf[0],
10232 args.above_pred_stride[0], args.left_pred_buf[0],
10233 args.left_pred_stride[0]);
Yue Chen5329a2b2017-02-28 17:33:00 +080010234 }
Yue Chencb60b182016-10-13 15:18:22 -070010235#endif // CONFIG_MOTION_VAR
Yaowu Xuc27fc142016-08-22 16:08:15 -070010236
10237 for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
10238 if (!(cpi->ref_frame_flags & flag_list[ref_frame])) {
Zoe Liue9b15e22017-07-19 15:53:01 -070010239 // Skip checking missing references in both single and compound reference
10240 // modes. Note that a mode will be skipped iff both reference frames
10241 // are masked out.
Zoe Liuc082bbc2017-05-17 13:31:37 -070010242 ref_frame_skip_mask[0] |= (1 << ref_frame);
10243 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010244 } else {
10245 for (i = LAST_FRAME; i <= ALTREF_FRAME; ++i) {
10246 // Skip fixed mv modes for poor references
10247 if ((x->pred_mv_sad[ref_frame] >> 2) > x->pred_mv_sad[i]) {
10248 mode_skip_mask[ref_frame] |= INTER_NEAREST_NEAR_ZERO;
10249 break;
10250 }
10251 }
10252 }
10253 // If the segment reference frame feature is enabled....
10254 // then do nothing if the current ref frame is not allowed..
10255 if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME) &&
10256 get_segdata(seg, segment_id, SEG_LVL_REF_FRAME) != (int)ref_frame) {
10257 ref_frame_skip_mask[0] |= (1 << ref_frame);
10258 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
10259 }
10260 }
10261
10262 // Disable this drop out case if the ref frame
10263 // segment level feature is enabled for this segment. This is to
10264 // prevent the possibility that we end up unable to pick any mode.
10265 if (!segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) {
10266 // Only consider ZEROMV/ALTREF_FRAME for alt ref frame,
10267 // unless ARNR filtering is enabled in which case we want
10268 // an unfiltered alternative. We allow near/nearest as well
10269 // because they may result in zero-zero MVs but be cheaper.
10270 if (cpi->rc.is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0)) {
Sarah Parkere5299862016-08-16 14:57:37 -070010271 int_mv zeromv;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010272 ref_frame_skip_mask[0] = (1 << LAST_FRAME) |
10273#if CONFIG_EXT_REFS
10274 (1 << LAST2_FRAME) | (1 << LAST3_FRAME) |
Zoe Liu3ac20932017-08-30 16:35:55 -070010275 (1 << BWDREF_FRAME) | (1 << ALTREF2_FRAME) |
Yaowu Xuc27fc142016-08-22 16:08:15 -070010276#endif // CONFIG_EXT_REFS
10277 (1 << GOLDEN_FRAME);
10278 ref_frame_skip_mask[1] = SECOND_REF_FRAME_MASK;
10279 // TODO(zoeliu): To further explore whether following needs to be done for
10280 // BWDREF_FRAME as well.
10281 mode_skip_mask[ALTREF_FRAME] = ~INTER_NEAREST_NEAR_ZERO;
Sarah Parkere5299862016-08-16 14:57:37 -070010282#if CONFIG_GLOBAL_MOTION
David Barkercdcac6d2016-12-01 17:04:16 +000010283 zeromv.as_int = gm_get_motion_vector(&cm->global_motion[ALTREF_FRAME],
Sarah Parkerae7c4582017-02-28 16:30:30 -080010284 cm->allow_high_precision_mv, bsize,
RogerZhou3b635242017-09-19 10:06:46 -070010285 mi_col, mi_row, 0
10286#if CONFIG_AMVR
10287 ,
10288 cm->cur_frame_mv_precision_level
10289#endif
10290 )
David Barkercdcac6d2016-12-01 17:04:16 +000010291 .as_int;
Sarah Parkere5299862016-08-16 14:57:37 -070010292#else
10293 zeromv.as_int = 0;
10294#endif // CONFIG_GLOBAL_MOTION
10295 if (frame_mv[NEARMV][ALTREF_FRAME].as_int != zeromv.as_int)
Yaowu Xuc27fc142016-08-22 16:08:15 -070010296 mode_skip_mask[ALTREF_FRAME] |= (1 << NEARMV);
Sarah Parkere5299862016-08-16 14:57:37 -070010297 if (frame_mv[NEARESTMV][ALTREF_FRAME].as_int != zeromv.as_int)
Yaowu Xuc27fc142016-08-22 16:08:15 -070010298 mode_skip_mask[ALTREF_FRAME] |= (1 << NEARESTMV);
Sarah Parkere5299862016-08-16 14:57:37 -070010299 if (frame_mv[NEAREST_NEARESTMV][ALTREF_FRAME].as_int != zeromv.as_int)
Yaowu Xuc27fc142016-08-22 16:08:15 -070010300 mode_skip_mask[ALTREF_FRAME] |= (1 << NEAREST_NEARESTMV);
Sarah Parkere5299862016-08-16 14:57:37 -070010301 if (frame_mv[NEAR_NEARMV][ALTREF_FRAME].as_int != zeromv.as_int)
Yaowu Xuc27fc142016-08-22 16:08:15 -070010302 mode_skip_mask[ALTREF_FRAME] |= (1 << NEAR_NEARMV);
Zoe Liu85b66462017-04-20 14:28:19 -070010303#if CONFIG_COMPOUND_SINGLEREF
10304 if (frame_mv[SR_NEAREST_NEARMV][ALTREF_FRAME].as_int != zeromv.as_int ||
10305 frame_comp_mv[SR_NEAREST_NEARMV][ALTREF_FRAME].as_int !=
10306 zeromv.as_int)
10307 mode_skip_mask[ALTREF_FRAME] |= (1 << SR_NEAREST_NEARMV);
10308#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -070010309 }
10310 }
10311
10312 if (cpi->rc.is_src_frame_alt_ref) {
10313 if (sf->alt_ref_search_fp) {
10314 assert(cpi->ref_frame_flags & flag_list[ALTREF_FRAME]);
10315 mode_skip_mask[ALTREF_FRAME] = 0;
10316 ref_frame_skip_mask[0] = ~(1 << ALTREF_FRAME);
10317 ref_frame_skip_mask[1] = SECOND_REF_FRAME_MASK;
10318 }
10319 }
10320
10321 if (sf->alt_ref_search_fp)
10322 if (!cm->show_frame && x->pred_mv_sad[GOLDEN_FRAME] < INT_MAX)
10323 if (x->pred_mv_sad[ALTREF_FRAME] > (x->pred_mv_sad[GOLDEN_FRAME] << 1))
10324 mode_skip_mask[ALTREF_FRAME] |= INTER_ALL;
10325
10326 if (sf->adaptive_mode_search) {
10327 if (cm->show_frame && !cpi->rc.is_src_frame_alt_ref &&
10328 cpi->rc.frames_since_golden >= 3)
Yaowu Xu36bad472017-05-16 18:29:53 -070010329 if ((x->pred_mv_sad[GOLDEN_FRAME] >> 1) > x->pred_mv_sad[LAST_FRAME])
Yaowu Xuc27fc142016-08-22 16:08:15 -070010330 mode_skip_mask[GOLDEN_FRAME] |= INTER_ALL;
10331 }
10332
10333 if (bsize > sf->max_intra_bsize) {
10334 ref_frame_skip_mask[0] |= (1 << INTRA_FRAME);
10335 ref_frame_skip_mask[1] |= (1 << INTRA_FRAME);
10336 }
10337
10338 mode_skip_mask[INTRA_FRAME] |=
10339 ~(sf->intra_y_mode_mask[max_txsize_lookup[bsize]]);
10340
10341 for (i = 0; i <= LAST_NEW_MV_INDEX; ++i) mode_threshold[i] = 0;
10342 for (i = LAST_NEW_MV_INDEX + 1; i < MAX_MODES; ++i)
10343 mode_threshold[i] = ((int64_t)rd_threshes[i] * rd_thresh_freq_fact[i]) >> 5;
10344
10345 midx = sf->schedule_mode_search ? mode_skip_start : 0;
10346 while (midx > 4) {
10347 uint8_t end_pos = 0;
10348 for (i = 5; i < midx; ++i) {
10349 if (mode_threshold[mode_map[i - 1]] > mode_threshold[mode_map[i]]) {
10350 uint8_t tmp = mode_map[i];
10351 mode_map[i] = mode_map[i - 1];
10352 mode_map[i - 1] = tmp;
10353 end_pos = i;
10354 }
10355 }
10356 midx = end_pos;
10357 }
10358
10359 if (cpi->sf.tx_type_search.fast_intra_tx_type_search)
10360 x->use_default_intra_tx_type = 1;
10361 else
10362 x->use_default_intra_tx_type = 0;
10363
10364 if (cpi->sf.tx_type_search.fast_inter_tx_type_search)
10365 x->use_default_inter_tx_type = 1;
10366 else
10367 x->use_default_inter_tx_type = 0;
Yushin Cho77bba8d2016-11-04 16:36:56 -070010368#if CONFIG_PVQ
10369 od_encode_checkpoint(&x->daala_enc, &pre_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -080010370#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -070010371 for (i = 0; i < MB_MODE_COUNT; ++i)
10372 for (ref_frame = 0; ref_frame < TOTAL_REFS_PER_FRAME; ++ref_frame)
10373 modelled_rd[i][ref_frame] = INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010374
10375 for (midx = 0; midx < MAX_MODES; ++midx) {
10376 int mode_index;
10377 int mode_excluded = 0;
10378 int64_t this_rd = INT64_MAX;
10379 int disable_skip = 0;
10380 int compmode_cost = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010381 int rate2 = 0, rate_y = 0, rate_uv = 0;
10382 int64_t distortion2 = 0, distortion_y = 0, distortion_uv = 0;
10383 int skippable = 0;
10384 int this_skip2 = 0;
10385 int64_t total_sse = INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010386 uint8_t ref_frame_type;
Yushin Cho77bba8d2016-11-04 16:36:56 -070010387#if CONFIG_PVQ
10388 od_encode_rollback(&x->daala_enc, &pre_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -080010389#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -070010390 mode_index = mode_map[midx];
Yaowu Xuf883b422016-08-30 14:01:10 -070010391 this_mode = av1_mode_order[mode_index].mode;
10392 ref_frame = av1_mode_order[mode_index].ref_frame[0];
10393 second_ref_frame = av1_mode_order[mode_index].ref_frame[1];
Yaowu Xu4306b6e2016-09-27 12:55:32 -070010394 mbmi->ref_mv_idx = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010395
Yaowu Xuc27fc142016-08-22 16:08:15 -070010396 if (ref_frame > INTRA_FRAME && second_ref_frame == INTRA_FRAME) {
10397 // Mode must by compatible
Debargha Mukherjee37f6fe62017-02-10 21:44:13 -080010398 if (!is_interintra_allowed_mode(this_mode)) continue;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010399 if (!is_interintra_allowed_bsize(bsize)) continue;
10400 }
10401
10402 if (is_inter_compound_mode(this_mode)) {
10403 frame_mv[this_mode][ref_frame].as_int =
10404 frame_mv[compound_ref0_mode(this_mode)][ref_frame].as_int;
10405 frame_mv[this_mode][second_ref_frame].as_int =
10406 frame_mv[compound_ref1_mode(this_mode)][second_ref_frame].as_int;
Zoe Liu85b66462017-04-20 14:28:19 -070010407#if CONFIG_COMPOUND_SINGLEREF
10408 } else if (is_inter_singleref_comp_mode(this_mode)) {
10409 frame_mv[this_mode][ref_frame].as_int =
10410 frame_mv[compound_ref0_mode(this_mode)][ref_frame].as_int;
10411 frame_comp_mv[this_mode][ref_frame].as_int =
10412 frame_mv[compound_ref1_mode(this_mode)][ref_frame].as_int;
10413#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -070010414 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070010415
10416 // Look at the reference frame of the best mode so far and set the
10417 // skip mask to look at a subset of the remaining modes.
10418 if (midx == mode_skip_start && best_mode_index >= 0) {
10419 switch (best_mbmode.ref_frame[0]) {
10420 case INTRA_FRAME: break;
10421 case LAST_FRAME:
10422 ref_frame_skip_mask[0] |= LAST_FRAME_MODE_MASK;
10423 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
10424 break;
10425#if CONFIG_EXT_REFS
10426 case LAST2_FRAME:
10427 ref_frame_skip_mask[0] |= LAST2_FRAME_MODE_MASK;
10428 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
10429 break;
10430 case LAST3_FRAME:
10431 ref_frame_skip_mask[0] |= LAST3_FRAME_MODE_MASK;
10432 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
10433 break;
10434#endif // CONFIG_EXT_REFS
10435 case GOLDEN_FRAME:
10436 ref_frame_skip_mask[0] |= GOLDEN_FRAME_MODE_MASK;
10437 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
10438 break;
10439#if CONFIG_EXT_REFS
10440 case BWDREF_FRAME:
10441 ref_frame_skip_mask[0] |= BWDREF_FRAME_MODE_MASK;
10442 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
10443 break;
Zoe Liue9b15e22017-07-19 15:53:01 -070010444 case ALTREF2_FRAME:
10445 ref_frame_skip_mask[0] |= ALTREF2_FRAME_MODE_MASK;
10446 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
10447 break;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010448#endif // CONFIG_EXT_REFS
10449 case ALTREF_FRAME: ref_frame_skip_mask[0] |= ALTREF_FRAME_MODE_MASK;
10450#if CONFIG_EXT_REFS
10451 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
10452#endif // CONFIG_EXT_REFS
10453 break;
Emil Keyder01770b32017-01-20 18:03:11 -050010454 case NONE_FRAME:
Yaowu Xuc27fc142016-08-22 16:08:15 -070010455 case TOTAL_REFS_PER_FRAME:
10456 assert(0 && "Invalid Reference frame");
10457 break;
10458 }
10459 }
10460
10461 if ((ref_frame_skip_mask[0] & (1 << ref_frame)) &&
Yaowu Xuf883b422016-08-30 14:01:10 -070010462 (ref_frame_skip_mask[1] & (1 << AOMMAX(0, second_ref_frame))))
Yaowu Xuc27fc142016-08-22 16:08:15 -070010463 continue;
10464
Zoe Liuc082bbc2017-05-17 13:31:37 -070010465#if CONFIG_EXT_COMP_REFS
10466// TODO(zoeliu): Following toggle between #if 0/1 and the bug will manifest
10467// itself.
10468#if 0
10469 if (!(cpi->ref_frame_flags & flag_list[ref_frame]) ||
10470 (second_ref_frame > INTRA_FRAME &&
10471 (!(cpi->ref_frame_flags & flag_list[second_ref_frame]))))
10472 printf("Frame=%d, bsize=%d, (mi_row,mi_col)=(%d,%d), ref_frame=%d, "
10473 "second_ref_frame=%d\n", cm->current_video_frame, bsize, mi_row,
10474 mi_col, ref_frame, second_ref_frame);
10475
10476 if (!(cpi->ref_frame_flags & flag_list[ref_frame])) continue;
10477 if (second_ref_frame > INTRA_FRAME &&
10478 (!(cpi->ref_frame_flags & flag_list[second_ref_frame])))
10479 continue;
10480#endif // 0
10481
10482#if !USE_UNI_COMP_REFS
10483 // NOTE(zoeliu): Temporarily disable uni-directional comp refs
10484 if (second_ref_frame > INTRA_FRAME) {
10485 if (!((ref_frame < BWDREF_FRAME) ^ (second_ref_frame < BWDREF_FRAME)))
10486 continue;
10487 }
10488 assert(second_ref_frame <= INTRA_FRAME ||
10489 ((ref_frame < BWDREF_FRAME) ^ (second_ref_frame < BWDREF_FRAME)));
10490#endif // !USE_UNI_COMP_REFS
10491#endif // CONFIG_EXT_COMP_REFS
10492
Yaowu Xuc27fc142016-08-22 16:08:15 -070010493 if (mode_skip_mask[ref_frame] & (1 << this_mode)) continue;
10494
10495 // Test best rd so far against threshold for trying this mode.
10496 if (best_mode_skippable && sf->schedule_mode_search)
10497 mode_threshold[mode_index] <<= 1;
10498
10499 if (best_rd < mode_threshold[mode_index]) continue;
10500
Yunqing Wangff4fa062017-04-21 10:56:08 -070010501 // This is only used in motion vector unit test.
10502 if (cpi->oxcf.motion_vector_unit_test && ref_frame == INTRA_FRAME) continue;
10503
Zoe Liu5a978832017-08-15 16:33:34 -070010504#if CONFIG_ONE_SIDED_COMPOUND && !CONFIG_EXT_COMP_REFS // Changes LL bitstream
Arild Fuldseth (arilfuld)3f429082017-04-28 15:54:28 +020010505#if CONFIG_EXT_REFS
10506 if (cpi->oxcf.pass == 0) {
10507 // Complexity-compression trade-offs
10508 // if (ref_frame == ALTREF_FRAME) continue;
10509 // if (ref_frame == BWDREF_FRAME) continue;
10510 if (second_ref_frame == ALTREF_FRAME) continue;
10511 // if (second_ref_frame == BWDREF_FRAME) continue;
10512 }
Zoe Liu5a978832017-08-15 16:33:34 -070010513#endif // CONFIG_EXT_REFS
10514#endif // CONFIG_ONE_SIDED_COMPOUND && !CONFIG_EXT_COMP_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -070010515 comp_pred = second_ref_frame > INTRA_FRAME;
10516 if (comp_pred) {
10517 if (!cpi->allow_comp_inter_inter) continue;
10518
10519 // Skip compound inter modes if ARF is not available.
10520 if (!(cpi->ref_frame_flags & flag_list[second_ref_frame])) continue;
10521
10522 // Do not allow compound prediction if the segment level reference frame
10523 // feature is in use as in this case there can only be one reference.
10524 if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) continue;
10525
10526 if ((mode_search_skip_flags & FLAG_SKIP_COMP_BESTINTRA) &&
10527 best_mode_index >= 0 && best_mbmode.ref_frame[0] == INTRA_FRAME)
10528 continue;
10529
10530 mode_excluded = cm->reference_mode == SINGLE_REFERENCE;
10531 } else {
10532 if (ref_frame != INTRA_FRAME)
10533 mode_excluded = cm->reference_mode == COMPOUND_REFERENCE;
10534 }
10535
10536 if (ref_frame == INTRA_FRAME) {
10537 if (sf->adaptive_mode_search)
10538 if ((x->source_variance << num_pels_log2_lookup[bsize]) > best_pred_sse)
10539 continue;
10540
10541 if (this_mode != DC_PRED) {
10542 // Disable intra modes other than DC_PRED for blocks with low variance
10543 // Threshold for intra skipping based on source variance
10544 // TODO(debargha): Specialize the threshold for super block sizes
10545 const unsigned int skip_intra_var_thresh = 64;
10546 if ((mode_search_skip_flags & FLAG_SKIP_INTRA_LOWVAR) &&
10547 x->source_variance < skip_intra_var_thresh)
10548 continue;
10549 // Only search the oblique modes if the best so far is
10550 // one of the neighboring directional modes
10551 if ((mode_search_skip_flags & FLAG_SKIP_INTRA_BESTINTER) &&
10552 (this_mode >= D45_PRED && this_mode <= TM_PRED)) {
10553 if (best_mode_index >= 0 && best_mbmode.ref_frame[0] > INTRA_FRAME)
10554 continue;
10555 }
10556 if (mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
10557 if (conditional_skipintra(this_mode, best_intra_mode)) continue;
10558 }
10559 }
Sarah Parkere5299862016-08-16 14:57:37 -070010560#if CONFIG_GLOBAL_MOTION
David Barkercf3d0b02016-11-10 10:14:49 +000010561 } else if (cm->global_motion[ref_frame].wmtype == IDENTITY &&
Sarah Parkere5299862016-08-16 14:57:37 -070010562 (!comp_pred ||
David Barkercf3d0b02016-11-10 10:14:49 +000010563 cm->global_motion[second_ref_frame].wmtype == IDENTITY)) {
Sarah Parkere5299862016-08-16 14:57:37 -070010564#else // CONFIG_GLOBAL_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070010565 } else {
Sarah Parkere5299862016-08-16 14:57:37 -070010566#endif // CONFIG_GLOBAL_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070010567 const MV_REFERENCE_FRAME ref_frames[2] = { ref_frame, second_ref_frame };
Yue Chenb23d00a2017-07-28 17:01:21 -070010568 if (!check_best_zero_mv(cpi, x, mbmi_ext->mode_context,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010569 mbmi_ext->compound_mode_context, frame_mv,
10570 this_mode, ref_frames, bsize, -1, mi_row, mi_col))
Yaowu Xuc27fc142016-08-22 16:08:15 -070010571 continue;
10572 }
10573
10574 mbmi->mode = this_mode;
Luc Trudeaud6d9eee2017-07-12 12:36:50 -040010575 mbmi->uv_mode = UV_DC_PRED;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010576 mbmi->ref_frame[0] = ref_frame;
10577 mbmi->ref_frame[1] = second_ref_frame;
10578 pmi->palette_size[0] = 0;
10579 pmi->palette_size[1] = 0;
hui su5db97432016-10-14 16:10:14 -070010580#if CONFIG_FILTER_INTRA
10581 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] = 0;
10582 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] = 0;
10583#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010584 // Evaluate all sub-pel filters irrespective of whether we can use
10585 // them for this frame.
Debargha Mukherjee0df711f2017-05-02 16:00:20 -070010586
10587 set_default_interp_filters(mbmi, cm->interp_filter);
10588
Yaowu Xuc27fc142016-08-22 16:08:15 -070010589 mbmi->mv[0].as_int = mbmi->mv[1].as_int = 0;
Yue Chencb60b182016-10-13 15:18:22 -070010590 mbmi->motion_mode = SIMPLE_TRANSLATION;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010591
10592 x->skip = 0;
10593 set_ref_ptrs(cm, xd, ref_frame, second_ref_frame);
10594
10595 // Select prediction reference frames.
10596 for (i = 0; i < MAX_MB_PLANE; i++) {
10597 xd->plane[i].pre[0] = yv12_mb[ref_frame][i];
10598 if (comp_pred) xd->plane[i].pre[1] = yv12_mb[second_ref_frame][i];
10599 }
10600
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010601#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070010602 // Single ref compound mode
10603 if (!comp_pred && is_inter_singleref_comp_mode(mbmi->mode)) {
10604 xd->block_refs[1] = xd->block_refs[0];
10605 for (i = 0; i < MAX_MB_PLANE; i++)
10606 xd->plane[i].pre[1] = xd->plane[i].pre[0];
10607 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010608#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070010609
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010610#if CONFIG_INTERINTRA
Debargha Mukherjeecb603792016-10-04 13:10:23 -070010611 mbmi->interintra_mode = (INTERINTRA_MODE)(II_DC_PRED - 1);
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010612#endif // CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010613
10614 if (ref_frame == INTRA_FRAME) {
Angie Chiang0e9a2e92016-11-08 09:45:40 -080010615 RD_STATS rd_stats_y;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010616 TX_SIZE uv_tx;
10617 struct macroblockd_plane *const pd = &xd->plane[1];
10618#if CONFIG_EXT_INTRA
hui su45dc5972016-12-08 17:42:50 -080010619 is_directional_mode = av1_is_directional_mode(mbmi->mode, bsize);
Joe Young830d4ce2017-05-30 17:48:13 -070010620 if (is_directional_mode && av1_use_angle_delta(bsize)) {
hui su45dc5972016-12-08 17:42:50 -080010621 int rate_dummy;
hui su9a416f52017-01-13 11:37:53 -080010622 int64_t model_rd = INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010623 if (!angle_stats_ready) {
10624 const int src_stride = x->plane[0].src.stride;
10625 const uint8_t *src = x->plane[0].src.buf;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020010626#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070010627 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
hui su9cc10652017-04-27 17:22:07 -070010628 highbd_angle_estimation(src, src_stride, rows, cols, bsize,
Yaowu Xuc27fc142016-08-22 16:08:15 -070010629 directional_mode_skip_mask);
10630 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020010631#endif // CONFIG_HIGHBITDEPTH
hui su9cc10652017-04-27 17:22:07 -070010632 angle_estimation(src, src_stride, rows, cols, bsize,
Yaowu Xuc27fc142016-08-22 16:08:15 -070010633 directional_mode_skip_mask);
10634 angle_stats_ready = 1;
10635 }
10636 if (directional_mode_skip_mask[mbmi->mode]) continue;
hui su45dc5972016-12-08 17:42:50 -080010637 rd_stats_y.rate = INT_MAX;
Yue Chenb0f808b2017-04-26 11:55:14 -070010638 rd_pick_intra_angle_sby(cpi, x, &rate_dummy, &rd_stats_y, bsize,
10639 intra_mode_cost[mbmi->mode], best_rd,
10640 &model_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010641 } else {
10642 mbmi->angle_delta[0] = 0;
Angie Chiang0e9a2e92016-11-08 09:45:40 -080010643 super_block_yrd(cpi, x, &rd_stats_y, bsize, best_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010644 }
10645#else
Angie Chiang0e9a2e92016-11-08 09:45:40 -080010646 super_block_yrd(cpi, x, &rd_stats_y, bsize, best_rd);
hui su45dc5972016-12-08 17:42:50 -080010647#endif // CONFIG_EXT_INTRA
Angie Chiang0e9a2e92016-11-08 09:45:40 -080010648 rate_y = rd_stats_y.rate;
10649 distortion_y = rd_stats_y.dist;
10650 skippable = rd_stats_y.skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010651
10652 if (rate_y == INT_MAX) continue;
10653
hui su5db97432016-10-14 16:10:14 -070010654#if CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010655 if (mbmi->mode == DC_PRED) dc_skipped = 0;
hui su5db97432016-10-14 16:10:14 -070010656#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010657
Debargha Mukherjee2f123402016-08-30 17:43:38 -070010658 uv_tx = uv_txsize_lookup[bsize][mbmi->tx_size][pd->subsampling_x]
10659 [pd->subsampling_y];
Yaowu Xuc27fc142016-08-22 16:08:15 -070010660 if (rate_uv_intra[uv_tx] == INT_MAX) {
Luc Trudeau9d4cbb82017-07-27 17:01:32 -040010661 choose_intra_uv_mode(cpi, x, bsize, uv_tx, &rate_uv_intra[uv_tx],
Urvang Joshi368fbc92016-10-17 16:31:34 -070010662 &rate_uv_tokenonly[uv_tx], &dist_uvs[uv_tx],
10663 &skip_uvs[uv_tx], &mode_uv[uv_tx]);
hui su9bc1d8d2017-03-24 12:36:03 -070010664 if (try_palette) pmi_uv[uv_tx] = *pmi;
Urvang Joshib100db72016-10-12 16:28:56 -070010665
Yaowu Xuc27fc142016-08-22 16:08:15 -070010666#if CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010667 uv_angle_delta[uv_tx] = mbmi->angle_delta[1];
10668#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -070010669#if CONFIG_FILTER_INTRA
10670 filter_intra_mode_info_uv[uv_tx] = mbmi->filter_intra_mode_info;
10671#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010672 }
10673
10674 rate_uv = rate_uv_tokenonly[uv_tx];
Urvang Joshi368fbc92016-10-17 16:31:34 -070010675 distortion_uv = dist_uvs[uv_tx];
10676 skippable = skippable && skip_uvs[uv_tx];
Yaowu Xuc27fc142016-08-22 16:08:15 -070010677 mbmi->uv_mode = mode_uv[uv_tx];
hui su9bc1d8d2017-03-24 12:36:03 -070010678 if (try_palette) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070010679 pmi->palette_size[1] = pmi_uv[uv_tx].palette_size[1];
10680 memcpy(pmi->palette_colors + PALETTE_MAX_SIZE,
10681 pmi_uv[uv_tx].palette_colors + PALETTE_MAX_SIZE,
10682 2 * PALETTE_MAX_SIZE * sizeof(pmi->palette_colors[0]));
10683 }
Urvang Joshib100db72016-10-12 16:28:56 -070010684
Yaowu Xuc27fc142016-08-22 16:08:15 -070010685#if CONFIG_EXT_INTRA
10686 mbmi->angle_delta[1] = uv_angle_delta[uv_tx];
Yaowu Xuc27fc142016-08-22 16:08:15 -070010687#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -070010688#if CONFIG_FILTER_INTRA
10689 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] =
10690 filter_intra_mode_info_uv[uv_tx].use_filter_intra_mode[1];
10691 if (filter_intra_mode_info_uv[uv_tx].use_filter_intra_mode[1]) {
10692 mbmi->filter_intra_mode_info.filter_intra_mode[1] =
10693 filter_intra_mode_info_uv[uv_tx].filter_intra_mode[1];
10694 }
10695#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010696
Jingning Han36fe3202017-02-20 22:31:49 -080010697#if CONFIG_CB4X4
10698 rate2 = rate_y + intra_mode_cost[mbmi->mode];
10699 if (!x->skip_chroma_rd)
Yue Chenb23d00a2017-07-28 17:01:21 -070010700 rate2 += rate_uv + x->intra_uv_mode_cost[mbmi->mode][mbmi->uv_mode];
Jingning Han36fe3202017-02-20 22:31:49 -080010701#else
Yaowu Xuc27fc142016-08-22 16:08:15 -070010702 rate2 = rate_y + intra_mode_cost[mbmi->mode] + rate_uv +
Yue Chenb23d00a2017-07-28 17:01:21 -070010703 x->intra_uv_mode_cost[mbmi->mode][mbmi->uv_mode];
Fergus Simpson4063a682017-02-28 16:52:22 -080010704#endif // CONFIG_CB4X4
Jingning Han36fe3202017-02-20 22:31:49 -080010705
hui su9bc1d8d2017-03-24 12:36:03 -070010706 if (try_palette && mbmi->mode == DC_PRED) {
Yaowu Xuf883b422016-08-30 14:01:10 -070010707 rate2 += av1_cost_bit(
10708 av1_default_palette_y_mode_prob[bsize - BLOCK_8X8][palette_ctx], 0);
hui su9bc1d8d2017-03-24 12:36:03 -070010709 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070010710
Jingning Hanbf9c6b72016-12-14 14:50:45 -080010711 if (!xd->lossless[mbmi->segment_id] && bsize >= BLOCK_8X8) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070010712 // super_block_yrd above includes the cost of the tx_size in the
10713 // tokenonly rate, but for intra blocks, tx_size is always coded
10714 // (prediction granularity), so we account for it in the full rate,
10715 // not the tokenonly rate.
Urvang Joshifeb925f2016-12-05 10:37:29 -080010716 rate_y -= tx_size_cost(cpi, x, bsize, mbmi->tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010717 }
10718#if CONFIG_EXT_INTRA
10719 if (is_directional_mode) {
hui sueda3d762016-12-06 16:58:23 -080010720#if CONFIG_INTRA_INTERP
Yaowu Xuf883b422016-08-30 14:01:10 -070010721 const int intra_filter_ctx = av1_get_pred_context_intra_interp(xd);
hui su0a6731f2017-04-26 15:23:47 -070010722 const int p_angle =
10723 mode_to_angle_map[mbmi->mode] + mbmi->angle_delta[0] * ANGLE_STEP;
Yaowu Xuf883b422016-08-30 14:01:10 -070010724 if (av1_is_intra_filter_switchable(p_angle))
Yue Chenb23d00a2017-07-28 17:01:21 -070010725 rate2 += x->intra_filter_cost[intra_filter_ctx][mbmi->intra_filter];
hui sueda3d762016-12-06 16:58:23 -080010726#endif // CONFIG_INTRA_INTERP
Joe Young830d4ce2017-05-30 17:48:13 -070010727 if (av1_use_angle_delta(bsize)) {
10728 rate2 += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
10729 MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
10730 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070010731 }
Luc Trudeauf24a35f2017-09-11 11:56:33 -040010732 if (av1_is_directional_mode(get_uv_mode(mbmi->uv_mode), bsize) &&
Joe Young830d4ce2017-05-30 17:48:13 -070010733 av1_use_angle_delta(bsize)) {
hui su0a6731f2017-04-26 15:23:47 -070010734 rate2 += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
10735 MAX_ANGLE_DELTA + mbmi->angle_delta[1]);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010736 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070010737#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -070010738#if CONFIG_FILTER_INTRA
10739 if (mbmi->mode == DC_PRED) {
10740 rate2 +=
10741 av1_cost_bit(cm->fc->filter_intra_probs[0],
10742 mbmi->filter_intra_mode_info.use_filter_intra_mode[0]);
10743 if (mbmi->filter_intra_mode_info.use_filter_intra_mode[0]) {
10744 rate2 += write_uniform_cost(
10745 FILTER_INTRA_MODES,
10746 mbmi->filter_intra_mode_info.filter_intra_mode[0]);
10747 }
10748 }
Luc Trudeaud6d9eee2017-07-12 12:36:50 -040010749 if (mbmi->uv_mode == UV_DC_PRED) {
hui su5db97432016-10-14 16:10:14 -070010750 rate2 +=
10751 av1_cost_bit(cpi->common.fc->filter_intra_probs[1],
10752 mbmi->filter_intra_mode_info.use_filter_intra_mode[1]);
10753 if (mbmi->filter_intra_mode_info.use_filter_intra_mode[1])
10754 rate2 += write_uniform_cost(
10755 FILTER_INTRA_MODES,
10756 mbmi->filter_intra_mode_info.filter_intra_mode[1]);
10757 }
10758#endif // CONFIG_FILTER_INTRA
Zoe Liu1157d502017-04-30 07:57:14 -070010759 if (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED)
Yaowu Xuc27fc142016-08-22 16:08:15 -070010760 rate2 += intra_cost_penalty;
10761 distortion2 = distortion_y + distortion_uv;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010762 } else {
Yaowu Xuc27fc142016-08-22 16:08:15 -070010763 int_mv backup_ref_mv[2];
10764
Debargha Mukherjee0f248c42017-09-07 12:40:18 -070010765 if (!is_comp_ref_allowed(bsize) && mbmi->ref_frame[1] > INTRA_FRAME)
10766 continue;
Jingning Hanc41a5492017-02-24 11:18:52 -080010767
Yaowu Xuc27fc142016-08-22 16:08:15 -070010768 backup_ref_mv[0] = mbmi_ext->ref_mvs[ref_frame][0];
10769 if (comp_pred) backup_ref_mv[1] = mbmi_ext->ref_mvs[second_ref_frame][0];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010770#if CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010771 if (second_ref_frame == INTRA_FRAME) {
10772 if (best_single_inter_ref != ref_frame) continue;
Debargha Mukherjeecb603792016-10-04 13:10:23 -070010773 mbmi->interintra_mode = intra_to_interintra_mode[best_intra_mode];
hui su5db97432016-10-14 16:10:14 -070010774// TODO(debargha|geza.lore):
10775// Should we use ext_intra modes for interintra?
Yaowu Xuc27fc142016-08-22 16:08:15 -070010776#if CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010777 mbmi->angle_delta[0] = 0;
10778 mbmi->angle_delta[1] = 0;
hui sueda3d762016-12-06 16:58:23 -080010779#if CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -070010780 mbmi->intra_filter = INTRA_FILTER_LINEAR;
hui sueda3d762016-12-06 16:58:23 -080010781#endif // CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -070010782#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -070010783#if CONFIG_FILTER_INTRA
10784 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] = 0;
10785 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] = 0;
10786#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010787 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010788#endif // CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010789 mbmi->ref_mv_idx = 0;
Yaowu Xuf883b422016-08-30 14:01:10 -070010790 ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010791
David Barker404b2e82017-03-27 13:07:47 +010010792 if (comp_pred) {
10793 if (mbmi_ext->ref_mv_count[ref_frame_type] > 1) {
David Barker3dfba992017-04-03 16:10:09 +010010794 int ref_mv_idx = 0;
10795 // Special case: NEAR_NEWMV and NEW_NEARMV modes use
10796 // 1 + mbmi->ref_mv_idx (like NEARMV) instead of
10797 // mbmi->ref_mv_idx (like NEWMV)
10798 if (mbmi->mode == NEAR_NEWMV || mbmi->mode == NEW_NEARMV)
10799 ref_mv_idx = 1;
10800
10801 if (compound_ref0_mode(mbmi->mode) == NEWMV) {
10802 int_mv this_mv =
10803 mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].this_mv;
David Barker404b2e82017-03-27 13:07:47 +010010804 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
10805 xd->n8_h << MI_SIZE_LOG2, xd);
10806 mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0] = this_mv;
10807 }
David Barker3dfba992017-04-03 16:10:09 +010010808 if (compound_ref1_mode(mbmi->mode) == NEWMV) {
10809 int_mv this_mv =
10810 mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].comp_mv;
David Barker404b2e82017-03-27 13:07:47 +010010811 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
10812 xd->n8_h << MI_SIZE_LOG2, xd);
10813 mbmi_ext->ref_mvs[mbmi->ref_frame[1]][0] = this_mv;
10814 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070010815 }
Zoe Liu85b66462017-04-20 14:28:19 -070010816#if CONFIG_COMPOUND_SINGLEREF
10817 } else if (is_inter_singleref_comp_mode(mbmi->mode)) {
10818 if (mbmi_ext->ref_mv_count[ref_frame_type] > 1) {
10819 // TODO(zoeliu): To further investigate which ref_mv_idx should be
10820 // chosen for the mode of SR_NEAR_NEWMV.
10821 int ref_mv_idx = 0;
10822 // Special case: SR_NEAR_NEWMV mode use
10823 // 1 + mbmi->ref_mv_idx (like NEARMV) instead of
10824 // mbmi->ref_mv_idx (like NEWMV)
10825 if (mbmi->mode == SR_NEAR_NEWMV) ref_mv_idx = 1;
10826
10827 if (compound_ref0_mode(mbmi->mode) == NEWMV ||
10828 compound_ref1_mode(mbmi->mode) == NEWMV) {
10829 int_mv this_mv =
10830 mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].this_mv;
10831 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
10832 xd->n8_h << MI_SIZE_LOG2, xd);
10833 mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0] = this_mv;
10834 }
10835 }
10836#endif // CONFIG_COMPOUND_SINGLEREF
David Barker404b2e82017-03-27 13:07:47 +010010837 } else {
Zoe Liu1157d502017-04-30 07:57:14 -070010838 if (mbmi->mode == NEWMV && mbmi_ext->ref_mv_count[ref_frame_type] > 1) {
David Barker404b2e82017-03-27 13:07:47 +010010839 int ref;
10840 for (ref = 0; ref < 1 + comp_pred; ++ref) {
10841 int_mv this_mv =
10842 (ref == 0) ? mbmi_ext->ref_mv_stack[ref_frame_type][0].this_mv
10843 : mbmi_ext->ref_mv_stack[ref_frame_type][0].comp_mv;
10844 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
10845 xd->n8_h << MI_SIZE_LOG2, xd);
10846 mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][0] = this_mv;
10847 }
10848 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070010849 }
Angie Chiang76159122016-11-09 12:13:22 -080010850 {
10851 RD_STATS rd_stats, rd_stats_y, rd_stats_uv;
10852 av1_init_rd_stats(&rd_stats);
10853 rd_stats.rate = rate2;
Fergus Simpson073c6f32017-02-17 12:13:48 -080010854
Zoe Liu7f24e1b2017-03-17 17:42:05 -070010855 // Point to variables that are maintained between loop iterations
10856 args.single_newmv = single_newmv;
Zoe Liu7f24e1b2017-03-17 17:42:05 -070010857 args.single_newmv_rate = single_newmv_rate;
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080010858 args.modelled_rd = modelled_rd;
Fergus Simpson3424c2d2017-03-09 11:48:15 -080010859 this_rd = handle_inter_mode(cpi, x, bsize, &rd_stats, &rd_stats_y,
10860 &rd_stats_uv, &disable_skip, frame_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010861#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070010862 frame_comp_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010863#endif // CONFIG_COMPOUND_SINGLEREF
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080010864 mi_row, mi_col, &args, best_rd);
Angie Chiang76159122016-11-09 12:13:22 -080010865
10866 rate2 = rd_stats.rate;
10867 skippable = rd_stats.skip;
10868 distortion2 = rd_stats.dist;
10869 total_sse = rd_stats.sse;
10870 rate_y = rd_stats_y.rate;
10871 rate_uv = rd_stats_uv.rate;
10872 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070010873
David Barker404b2e82017-03-27 13:07:47 +010010874// TODO(jingning): This needs some refactoring to improve code quality
10875// and reduce redundant steps.
Zoe Liu85b66462017-04-20 14:28:19 -070010876#if CONFIG_COMPOUND_SINGLEREF
10877 if ((have_nearmv_in_inter_mode(mbmi->mode) &&
10878 mbmi_ext->ref_mv_count[ref_frame_type] > 2) ||
10879 ((mbmi->mode == NEWMV || mbmi->mode == SR_NEW_NEWMV ||
10880 mbmi->mode == NEW_NEWMV) &&
Yushin Cho67dda512017-07-25 14:58:22 -070010881 mbmi_ext->ref_mv_count[ref_frame_type] > 1))
Zoe Liu85b66462017-04-20 14:28:19 -070010882#else // !CONFIG_COMPOUND_SINGLEREF
David Barker3dfba992017-04-03 16:10:09 +010010883 if ((have_nearmv_in_inter_mode(mbmi->mode) &&
David Barker404b2e82017-03-27 13:07:47 +010010884 mbmi_ext->ref_mv_count[ref_frame_type] > 2) ||
10885 ((mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV) &&
Yushin Cho67dda512017-07-25 14:58:22 -070010886 mbmi_ext->ref_mv_count[ref_frame_type] > 1))
Zoe Liu85b66462017-04-20 14:28:19 -070010887#endif // CONFIG_COMPOUND_SINGLEREF
Yushin Cho67dda512017-07-25 14:58:22 -070010888 {
Yaowu Xuc27fc142016-08-22 16:08:15 -070010889 int_mv backup_mv = frame_mv[NEARMV][ref_frame];
10890 MB_MODE_INFO backup_mbmi = *mbmi;
10891 int backup_skip = x->skip;
10892 int64_t tmp_ref_rd = this_rd;
10893 int ref_idx;
10894
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010895 // TODO(jingning): This should be deprecated shortly.
David Barker3dfba992017-04-03 16:10:09 +010010896 int idx_offset = have_nearmv_in_inter_mode(mbmi->mode) ? 1 : 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010897 int ref_set =
Yaowu Xuf883b422016-08-30 14:01:10 -070010898 AOMMIN(2, mbmi_ext->ref_mv_count[ref_frame_type] - 1 - idx_offset);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010899
10900 uint8_t drl_ctx =
Yaowu Xuf883b422016-08-30 14:01:10 -070010901 av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx_offset);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010902 // Dummy
10903 int_mv backup_fmv[2];
10904 backup_fmv[0] = frame_mv[NEWMV][ref_frame];
10905 if (comp_pred) backup_fmv[1] = frame_mv[NEWMV][second_ref_frame];
10906
Yue Chenb23d00a2017-07-28 17:01:21 -070010907 rate2 += (rate2 < INT_MAX ? x->drl_mode_cost0[drl_ctx][0] : 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010908
10909 if (this_rd < INT64_MAX) {
Urvang Joshi70006e42017-06-14 16:08:55 -070010910 if (RDCOST(x->rdmult, rate_y + rate_uv, distortion2) <
10911 RDCOST(x->rdmult, 0, total_sse))
10912 tmp_ref_rd = RDCOST(
10913 x->rdmult, rate2 + av1_cost_bit(av1_get_skip_prob(cm, xd), 0),
10914 distortion2);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010915 else
clang-format4eafefe2017-09-04 12:51:20 -070010916 tmp_ref_rd =
10917 RDCOST(x->rdmult,
10918 rate2 + av1_cost_bit(av1_get_skip_prob(cm, xd), 1) -
10919 rate_y - rate_uv,
10920 total_sse);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010921 }
10922#if CONFIG_VAR_TX
10923 for (i = 0; i < MAX_MB_PLANE; ++i)
10924 memcpy(x->blk_skip_drl[i], x->blk_skip[i],
10925 sizeof(uint8_t) * ctx->num_4x4_blk);
Fergus Simpson4063a682017-02-28 16:52:22 -080010926#endif // CONFIG_VAR_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -070010927
10928 for (ref_idx = 0; ref_idx < ref_set; ++ref_idx) {
10929 int64_t tmp_alt_rd = INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010930 int dummy_disable_skip = 0;
10931 int ref;
10932 int_mv cur_mv;
Angie Chiang76159122016-11-09 12:13:22 -080010933 RD_STATS tmp_rd_stats, tmp_rd_stats_y, tmp_rd_stats_uv;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010934
Yaowu Xu5bfbfdf2016-11-22 16:43:34 -080010935 av1_invalid_rd_stats(&tmp_rd_stats);
Yushin Choc0f6bf22017-06-09 16:08:02 -070010936
Jingning Han52617b22017-04-11 12:50:08 -070010937 x->skip = 0;
Yaowu Xu5bfbfdf2016-11-22 16:43:34 -080010938
Yaowu Xuc27fc142016-08-22 16:08:15 -070010939 mbmi->ref_mv_idx = 1 + ref_idx;
10940
David Barker3dfba992017-04-03 16:10:09 +010010941 if (comp_pred) {
10942 int ref_mv_idx = mbmi->ref_mv_idx;
10943 // Special case: NEAR_NEWMV and NEW_NEARMV modes use
10944 // 1 + mbmi->ref_mv_idx (like NEARMV) instead of
10945 // mbmi->ref_mv_idx (like NEWMV)
10946 if (mbmi->mode == NEAR_NEWMV || mbmi->mode == NEW_NEARMV)
10947 ref_mv_idx = 1 + mbmi->ref_mv_idx;
10948
10949 if (compound_ref0_mode(mbmi->mode) == NEWMV) {
10950 int_mv this_mv =
10951 mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].this_mv;
10952 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
10953 xd->n8_h << MI_SIZE_LOG2, xd);
10954 mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0] = this_mv;
10955 } else if (compound_ref0_mode(mbmi->mode) == NEARESTMV) {
10956 int_mv this_mv =
10957 mbmi_ext->ref_mv_stack[ref_frame_type][0].this_mv;
10958 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
10959 xd->n8_h << MI_SIZE_LOG2, xd);
10960 mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0] = this_mv;
10961 }
10962
10963 if (compound_ref1_mode(mbmi->mode) == NEWMV) {
10964 int_mv this_mv =
10965 mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].comp_mv;
10966 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
10967 xd->n8_h << MI_SIZE_LOG2, xd);
10968 mbmi_ext->ref_mvs[mbmi->ref_frame[1]][0] = this_mv;
10969 } else if (compound_ref1_mode(mbmi->mode) == NEARESTMV) {
10970 int_mv this_mv =
10971 mbmi_ext->ref_mv_stack[ref_frame_type][0].comp_mv;
10972 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
10973 xd->n8_h << MI_SIZE_LOG2, xd);
10974 mbmi_ext->ref_mvs[mbmi->ref_frame[1]][0] = this_mv;
10975 }
Zoe Liu85b66462017-04-20 14:28:19 -070010976#if CONFIG_COMPOUND_SINGLEREF
10977 } else if (is_inter_singleref_comp_mode(mbmi->mode)) {
10978 int ref_mv_idx = mbmi->ref_mv_idx;
10979 // Special case: SR_NEAR_NEWMV mode use
10980 // 1 + mbmi->ref_mv_idx (like NEARMV) instead of
10981 // mbmi->ref_mv_idx (like NEWMV)
10982 if (mbmi->mode == SR_NEAR_NEWMV) ref_mv_idx = 1 + mbmi->ref_mv_idx;
10983
10984 // TODO(zoeliu): For the mode of SR_NEAREST_NEWMV, as it only runs
10985 // the "if", not the "else if",
10986 // mbmi_ext->ref_mvs[mbmi->ref_frame[0]] takes the
10987 // value for "NEWMV", instead of "NEARESTMV".
10988 if (compound_ref0_mode(mbmi->mode) == NEWMV ||
10989 compound_ref1_mode(mbmi->mode) == NEWMV) {
10990 int_mv this_mv =
10991 mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].this_mv;
10992 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
10993 xd->n8_h << MI_SIZE_LOG2, xd);
10994 mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0] = this_mv;
10995 } else if (compound_ref0_mode(mbmi->mode) == NEARESTMV ||
10996 compound_ref1_mode(mbmi->mode) == NEARESTMV) {
10997 int_mv this_mv =
10998 mbmi_ext->ref_mv_stack[ref_frame_type][0].this_mv;
10999 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
11000 xd->n8_h << MI_SIZE_LOG2, xd);
11001 mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0] = this_mv;
11002 }
11003#endif // CONFIG_COMPOUND_SINGLEREF
David Barker3dfba992017-04-03 16:10:09 +010011004 } else {
David Barker3dfba992017-04-03 16:10:09 +010011005 for (ref = 0; ref < 1 + comp_pred; ++ref) {
11006 int_mv this_mv =
11007 (ref == 0)
11008 ? mbmi_ext->ref_mv_stack[ref_frame_type][mbmi->ref_mv_idx]
11009 .this_mv
11010 : mbmi_ext->ref_mv_stack[ref_frame_type][mbmi->ref_mv_idx]
11011 .comp_mv;
11012 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
11013 xd->n8_h << MI_SIZE_LOG2, xd);
11014 mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][0] = this_mv;
11015 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070011016 }
11017
11018 cur_mv =
11019 mbmi_ext->ref_mv_stack[ref_frame][mbmi->ref_mv_idx + idx_offset]
11020 .this_mv;
11021 clamp_mv2(&cur_mv.as_mv, xd);
11022
Alex Converse0fa0f422017-04-24 12:51:14 -070011023 if (!mv_check_bounds(&x->mv_limits, &cur_mv.as_mv)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011024 int_mv dummy_single_newmv[TOTAL_REFS_PER_FRAME] = { { 0 } };
Zoe Liu7f24e1b2017-03-17 17:42:05 -070011025 int dummy_single_newmv_rate[TOTAL_REFS_PER_FRAME] = { 0 };
Yaowu Xuc27fc142016-08-22 16:08:15 -070011026
11027 frame_mv[NEARMV][ref_frame] = cur_mv;
Angie Chiang76159122016-11-09 12:13:22 -080011028 av1_init_rd_stats(&tmp_rd_stats);
Yushin Cho8e75e8b2017-09-12 16:33:28 -070011029
Zoe Liu7f24e1b2017-03-17 17:42:05 -070011030 // Point to variables that are not maintained between iterations
11031 args.single_newmv = dummy_single_newmv;
Zoe Liu7f24e1b2017-03-17 17:42:05 -070011032 args.single_newmv_rate = dummy_single_newmv_rate;
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080011033 args.modelled_rd = NULL;
Zoe Liu85b66462017-04-20 14:28:19 -070011034 tmp_alt_rd = handle_inter_mode(cpi, x, bsize, &tmp_rd_stats,
11035 &tmp_rd_stats_y, &tmp_rd_stats_uv,
11036 &dummy_disable_skip, frame_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011037#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070011038 frame_comp_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011039#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070011040 mi_row, mi_col, &args, best_rd);
Zoe Liu7f24e1b2017-03-17 17:42:05 -070011041 // Prevent pointers from escaping local scope
11042 args.single_newmv = NULL;
Zoe Liu7f24e1b2017-03-17 17:42:05 -070011043 args.single_newmv_rate = NULL;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011044 }
11045
11046 for (i = 0; i < mbmi->ref_mv_idx; ++i) {
11047 uint8_t drl1_ctx = 0;
Yaowu Xuf883b422016-08-30 14:01:10 -070011048 drl1_ctx = av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type],
11049 i + idx_offset);
Angie Chiang76159122016-11-09 12:13:22 -080011050 tmp_rd_stats.rate +=
Yue Chenb23d00a2017-07-28 17:01:21 -070011051 (tmp_rd_stats.rate < INT_MAX ? x->drl_mode_cost0[drl1_ctx][1]
Angie Chiang76159122016-11-09 12:13:22 -080011052 : 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011053 }
11054
11055 if (mbmi_ext->ref_mv_count[ref_frame_type] >
11056 mbmi->ref_mv_idx + idx_offset + 1 &&
11057 ref_idx < ref_set - 1) {
11058 uint8_t drl1_ctx =
Yaowu Xuf883b422016-08-30 14:01:10 -070011059 av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type],
11060 mbmi->ref_mv_idx + idx_offset);
Yaowu Xu83ed6fe2016-11-22 11:15:29 -080011061 tmp_rd_stats.rate +=
Yue Chenb23d00a2017-07-28 17:01:21 -070011062 (tmp_rd_stats.rate < INT_MAX ? x->drl_mode_cost0[drl1_ctx][0]
Yaowu Xu83ed6fe2016-11-22 11:15:29 -080011063 : 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011064 }
11065
11066 if (tmp_alt_rd < INT64_MAX) {
Yue Chen69f18e12016-09-08 14:48:15 -070011067#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Urvang Joshi70006e42017-06-14 16:08:55 -070011068 tmp_alt_rd =
11069 RDCOST(x->rdmult, tmp_rd_stats.rate, tmp_rd_stats.dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011070#else
Urvang Joshi70006e42017-06-14 16:08:55 -070011071 if (RDCOST(x->rdmult, tmp_rd_stats_y.rate + tmp_rd_stats_uv.rate,
Angie Chiang76159122016-11-09 12:13:22 -080011072 tmp_rd_stats.dist) <
Urvang Joshi70006e42017-06-14 16:08:55 -070011073 RDCOST(x->rdmult, 0, tmp_rd_stats.sse))
clang-format4eafefe2017-09-04 12:51:20 -070011074 tmp_alt_rd =
11075 RDCOST(x->rdmult,
11076 tmp_rd_stats.rate +
11077 av1_cost_bit(av1_get_skip_prob(cm, xd), 0),
11078 tmp_rd_stats.dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011079 else
clang-format4eafefe2017-09-04 12:51:20 -070011080 tmp_alt_rd =
11081 RDCOST(x->rdmult,
11082 tmp_rd_stats.rate +
11083 av1_cost_bit(av1_get_skip_prob(cm, xd), 1) -
11084 tmp_rd_stats_y.rate - tmp_rd_stats_uv.rate,
11085 tmp_rd_stats.sse);
Yue Chen69f18e12016-09-08 14:48:15 -070011086#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070011087 }
11088
11089 if (tmp_ref_rd > tmp_alt_rd) {
Angie Chiang76159122016-11-09 12:13:22 -080011090 rate2 = tmp_rd_stats.rate;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011091 disable_skip = dummy_disable_skip;
Angie Chiang76159122016-11-09 12:13:22 -080011092 distortion2 = tmp_rd_stats.dist;
11093 skippable = tmp_rd_stats.skip;
11094 rate_y = tmp_rd_stats_y.rate;
11095 rate_uv = tmp_rd_stats_uv.rate;
11096 total_sse = tmp_rd_stats.sse;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011097 this_rd = tmp_alt_rd;
11098 tmp_ref_rd = tmp_alt_rd;
11099 backup_mbmi = *mbmi;
11100 backup_skip = x->skip;
11101#if CONFIG_VAR_TX
11102 for (i = 0; i < MAX_MB_PLANE; ++i)
11103 memcpy(x->blk_skip_drl[i], x->blk_skip[i],
11104 sizeof(uint8_t) * ctx->num_4x4_blk);
Fergus Simpson4063a682017-02-28 16:52:22 -080011105#endif // CONFIG_VAR_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -070011106 } else {
11107 *mbmi = backup_mbmi;
11108 x->skip = backup_skip;
11109 }
11110 }
11111
11112 frame_mv[NEARMV][ref_frame] = backup_mv;
11113 frame_mv[NEWMV][ref_frame] = backup_fmv[0];
11114 if (comp_pred) frame_mv[NEWMV][second_ref_frame] = backup_fmv[1];
11115#if CONFIG_VAR_TX
11116 for (i = 0; i < MAX_MB_PLANE; ++i)
11117 memcpy(x->blk_skip[i], x->blk_skip_drl[i],
11118 sizeof(uint8_t) * ctx->num_4x4_blk);
Fergus Simpson4063a682017-02-28 16:52:22 -080011119#endif // CONFIG_VAR_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -070011120 }
11121 mbmi_ext->ref_mvs[ref_frame][0] = backup_ref_mv[0];
11122 if (comp_pred) mbmi_ext->ref_mvs[second_ref_frame][0] = backup_ref_mv[1];
Yaowu Xuc27fc142016-08-22 16:08:15 -070011123
11124 if (this_rd == INT64_MAX) continue;
11125
Debargha Mukherjee0f248c42017-09-07 12:40:18 -070011126 if (is_comp_ref_allowed(mbmi->sb_type))
Jingning Hanc41a5492017-02-24 11:18:52 -080011127 compmode_cost = av1_cost_bit(comp_mode_p, comp_pred);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011128
11129 if (cm->reference_mode == REFERENCE_MODE_SELECT) rate2 += compmode_cost;
11130 }
11131
Yaowu Xuc27fc142016-08-22 16:08:15 -070011132 // Estimate the reference frame signaling cost and add it
11133 // to the rolling cost variable.
11134 if (comp_pred) {
Zoe Liuc082bbc2017-05-17 13:31:37 -070011135#if CONFIG_EXT_COMP_REFS
11136 rate2 += ref_costs_comp[ref_frame][second_ref_frame];
11137#else // !CONFIG_EXT_COMP_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -070011138 rate2 += ref_costs_comp[ref_frame];
11139#if CONFIG_EXT_REFS
11140 rate2 += ref_costs_comp[second_ref_frame];
11141#endif // CONFIG_EXT_REFS
Zoe Liuc082bbc2017-05-17 13:31:37 -070011142#endif // CONFIG_EXT_COMP_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -070011143 } else {
11144 rate2 += ref_costs_single[ref_frame];
11145 }
11146
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011147#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070011148 // Add the cost to signal single/comp mode in single ref.
11149 if (!comp_pred && cm->reference_mode != COMPOUND_REFERENCE) {
11150 aom_prob singleref_comp_mode_p = av1_get_inter_mode_prob(cm, xd);
11151 rate2 += av1_cost_bit(singleref_comp_mode_p,
11152 is_inter_singleref_comp_mode(mbmi->mode));
11153 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011154#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070011155
Yue Chen69f18e12016-09-08 14:48:15 -070011156#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yushin Cho67dda512017-07-25 14:58:22 -070011157 if (ref_frame == INTRA_FRAME)
Yaowu Xuc27fc142016-08-22 16:08:15 -070011158#else
Yushin Cho67dda512017-07-25 14:58:22 -070011159 if (!disable_skip)
Yue Chen69f18e12016-09-08 14:48:15 -070011160#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yushin Cho67dda512017-07-25 14:58:22 -070011161 {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011162 if (skippable) {
11163 // Back out the coefficient coding costs
11164 rate2 -= (rate_y + rate_uv);
11165 rate_y = 0;
11166 rate_uv = 0;
11167 // Cost the skip mb case
Yaowu Xuf883b422016-08-30 14:01:10 -070011168 rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011169 } else if (ref_frame != INTRA_FRAME && !xd->lossless[mbmi->segment_id]) {
Urvang Joshi70006e42017-06-14 16:08:55 -070011170 if (RDCOST(x->rdmult, rate_y + rate_uv + rate_skip0, distortion2) <
11171 RDCOST(x->rdmult, rate_skip1, total_sse)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011172 // Add in the cost of the no skip flag.
Yaowu Xuf883b422016-08-30 14:01:10 -070011173 rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011174 } else {
11175 // FIXME(rbultje) make this work for splitmv also
Yaowu Xuf883b422016-08-30 14:01:10 -070011176 rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011177 distortion2 = total_sse;
11178 assert(total_sse >= 0);
11179 rate2 -= (rate_y + rate_uv);
11180 this_skip2 = 1;
11181 rate_y = 0;
11182 rate_uv = 0;
11183 }
11184 } else {
11185 // Add in the cost of the no skip flag.
Yaowu Xuf883b422016-08-30 14:01:10 -070011186 rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011187 }
11188
11189 // Calculate the final RD estimate for this mode.
Urvang Joshi70006e42017-06-14 16:08:55 -070011190 this_rd = RDCOST(x->rdmult, rate2, distortion2);
Yue Chen69f18e12016-09-08 14:48:15 -070011191#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070011192 } else {
11193 this_skip2 = mbmi->skip;
Urvang Joshi70006e42017-06-14 16:08:55 -070011194 this_rd = RDCOST(x->rdmult, rate2, distortion2);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011195 if (this_skip2) {
11196 rate_y = 0;
11197 rate_uv = 0;
11198 }
Yue Chen69f18e12016-09-08 14:48:15 -070011199#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070011200 }
11201
Yaowu Xuc27fc142016-08-22 16:08:15 -070011202 if (ref_frame == INTRA_FRAME) {
11203 // Keep record of best intra rd
11204 if (this_rd < best_intra_rd) {
11205 best_intra_rd = this_rd;
11206 best_intra_mode = mbmi->mode;
11207 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011208#if CONFIG_INTERINTRA
Emil Keyder01770b32017-01-20 18:03:11 -050011209 } else if (second_ref_frame == NONE_FRAME) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011210 if (this_rd < best_single_inter_rd) {
11211 best_single_inter_rd = this_rd;
11212 best_single_inter_ref = mbmi->ref_frame[0];
11213 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011214#endif // CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011215 }
11216
11217 if (!disable_skip && ref_frame == INTRA_FRAME) {
11218 for (i = 0; i < REFERENCE_MODES; ++i)
Yaowu Xuf883b422016-08-30 14:01:10 -070011219 best_pred_rd[i] = AOMMIN(best_pred_rd[i], this_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011220 }
11221
11222 // Did this mode help.. i.e. is it the new best mode
11223 if (this_rd < best_rd || x->skip) {
11224 if (!mode_excluded) {
11225 // Note index of best mode so far
11226 best_mode_index = mode_index;
11227
11228 if (ref_frame == INTRA_FRAME) {
11229 /* required for left and above block mv */
11230 mbmi->mv[0].as_int = 0;
11231 } else {
11232 best_pred_sse = x->pred_sse[ref_frame];
11233 }
11234
11235 rd_cost->rate = rate2;
11236#if CONFIG_SUPERTX
11237 if (x->skip)
11238 *returnrate_nocoef = rate2;
11239 else
11240 *returnrate_nocoef = rate2 - rate_y - rate_uv;
Yaowu Xuf883b422016-08-30 14:01:10 -070011241 *returnrate_nocoef -= av1_cost_bit(
11242 av1_get_skip_prob(cm, xd), disable_skip || skippable || this_skip2);
11243 *returnrate_nocoef -= av1_cost_bit(av1_get_intra_inter_prob(cm, xd),
11244 mbmi->ref_frame[0] != INTRA_FRAME);
Yue Chencb60b182016-10-13 15:18:22 -070011245#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yue Chen52c51732017-07-11 15:08:30 -070011246#if CONFIG_WARPED_MOTION
11247 set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
11248#endif
Yaowu Xu41a36de2017-03-23 15:55:03 -070011249#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
11250 MODE_INFO *const mi = xd->mi[0];
Sarah Parker19234cc2017-03-10 16:43:25 -080011251 const MOTION_MODE motion_allowed = motion_mode_allowed(
Sarah Parker0eea89f2017-07-11 11:56:36 -070011252#if CONFIG_GLOBAL_MOTION
Sarah Parker19234cc2017-03-10 16:43:25 -080011253 0, xd->global_motion,
Sarah Parker0eea89f2017-07-11 11:56:36 -070011254#endif // CONFIG_GLOBAL_MOTION
Yue Chen52c51732017-07-11 15:08:30 -070011255#if CONFIG_WARPED_MOTION
11256 xd,
11257#endif
Sarah Parker19234cc2017-03-10 16:43:25 -080011258 mi);
Sarah Parker19234cc2017-03-10 16:43:25 -080011259 if (motion_allowed == WARPED_CAUSAL)
Yue Chenbdc8dab2017-07-26 12:05:47 -070011260 *returnrate_nocoef -= x->motion_mode_cost[bsize][mbmi->motion_mode];
Sarah Parker19234cc2017-03-10 16:43:25 -080011261 else if (motion_allowed == OBMC_CAUSAL)
Yue Chenb23d00a2017-07-28 17:01:21 -070011262 *returnrate_nocoef -= x->motion_mode_cost1[bsize][mbmi->motion_mode];
Yaowu Xu41a36de2017-03-23 15:55:03 -070011263#else
Yue Chenbdc8dab2017-07-26 12:05:47 -070011264 *returnrate_nocoef -= x->motion_mode_cost[bsize][mbmi->motion_mode];
Yue Chen69f18e12016-09-08 14:48:15 -070011265#endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
Yue Chencb60b182016-10-13 15:18:22 -070011266#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070011267#endif // CONFIG_SUPERTX
11268 rd_cost->dist = distortion2;
11269 rd_cost->rdcost = this_rd;
11270 best_rd = this_rd;
11271 best_mbmode = *mbmi;
11272 best_skip2 = this_skip2;
11273 best_mode_skippable = skippable;
Yaowu Xuf883b422016-08-30 14:01:10 -070011274 best_rate_y = rate_y + av1_cost_bit(av1_get_skip_prob(cm, xd),
11275 this_skip2 || skippable);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011276 best_rate_uv = rate_uv;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011277#if CONFIG_VAR_TX
11278 for (i = 0; i < MAX_MB_PLANE; ++i)
11279 memcpy(ctx->blk_skip[i], x->blk_skip[i],
11280 sizeof(uint8_t) * ctx->num_4x4_blk);
Fergus Simpson4063a682017-02-28 16:52:22 -080011281#endif // CONFIG_VAR_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -070011282 }
11283 }
Yushin Cho8e75e8b2017-09-12 16:33:28 -070011284
Yaowu Xuc27fc142016-08-22 16:08:15 -070011285 /* keep record of best compound/single-only prediction */
11286 if (!disable_skip && ref_frame != INTRA_FRAME) {
11287 int64_t single_rd, hybrid_rd, single_rate, hybrid_rate;
11288
11289 if (cm->reference_mode == REFERENCE_MODE_SELECT) {
11290 single_rate = rate2 - compmode_cost;
11291 hybrid_rate = rate2;
11292 } else {
11293 single_rate = rate2;
11294 hybrid_rate = rate2 + compmode_cost;
11295 }
11296
Urvang Joshi70006e42017-06-14 16:08:55 -070011297 single_rd = RDCOST(x->rdmult, single_rate, distortion2);
11298 hybrid_rd = RDCOST(x->rdmult, hybrid_rate, distortion2);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011299
11300 if (!comp_pred) {
11301 if (single_rd < best_pred_rd[SINGLE_REFERENCE])
11302 best_pred_rd[SINGLE_REFERENCE] = single_rd;
11303 } else {
11304 if (single_rd < best_pred_rd[COMPOUND_REFERENCE])
11305 best_pred_rd[COMPOUND_REFERENCE] = single_rd;
11306 }
11307 if (hybrid_rd < best_pred_rd[REFERENCE_MODE_SELECT])
11308 best_pred_rd[REFERENCE_MODE_SELECT] = hybrid_rd;
11309 }
11310
Yaowu Xuc27fc142016-08-22 16:08:15 -070011311 if (x->skip && !comp_pred) break;
11312 }
11313
11314 if (xd->lossless[mbmi->segment_id] == 0 && best_mode_index >= 0 &&
11315 ((sf->tx_type_search.fast_inter_tx_type_search == 1 &&
11316 is_inter_mode(best_mbmode.mode)) ||
11317 (sf->tx_type_search.fast_intra_tx_type_search == 1 &&
11318 !is_inter_mode(best_mbmode.mode)))) {
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011319 int skip_blk = 0;
11320 RD_STATS rd_stats_y, rd_stats_uv;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011321
11322 x->use_default_inter_tx_type = 0;
11323 x->use_default_intra_tx_type = 0;
11324
11325 *mbmi = best_mbmode;
11326
11327 set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
11328
11329 // Select prediction reference frames.
11330 for (i = 0; i < MAX_MB_PLANE; i++) {
11331 xd->plane[i].pre[0] = yv12_mb[mbmi->ref_frame[0]][i];
11332 if (has_second_ref(mbmi))
11333 xd->plane[i].pre[1] = yv12_mb[mbmi->ref_frame[1]][i];
11334 }
11335
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011336#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070011337 // Single ref compound mode
11338 if (!has_second_ref(mbmi) && is_inter_singleref_comp_mode(mbmi->mode)) {
11339 xd->block_refs[1] = xd->block_refs[0];
11340 for (i = 0; i < MAX_MB_PLANE; i++)
11341 xd->plane[i].pre[1] = xd->plane[i].pre[0];
11342 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011343#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070011344
Yaowu Xuc27fc142016-08-22 16:08:15 -070011345 if (is_inter_mode(mbmi->mode)) {
Jingning Hanc44009c2017-05-06 11:36:49 -070011346 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, NULL, bsize);
Yue Chencb60b182016-10-13 15:18:22 -070011347#if CONFIG_MOTION_VAR
Sarah Parker19234cc2017-03-10 16:43:25 -080011348 if (mbmi->motion_mode == OBMC_CAUSAL) {
Fergus Simpson073c6f32017-02-17 12:13:48 -080011349 av1_build_obmc_inter_prediction(
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080011350 cm, xd, mi_row, mi_col, args.above_pred_buf, args.above_pred_stride,
11351 args.left_pred_buf, args.left_pred_stride);
Sarah Parker19234cc2017-03-10 16:43:25 -080011352 }
Yue Chencb60b182016-10-13 15:18:22 -070011353#endif // CONFIG_MOTION_VAR
Yaowu Xuf883b422016-08-30 14:01:10 -070011354 av1_subtract_plane(x, bsize, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011355#if CONFIG_VAR_TX
11356 if (cm->tx_mode == TX_MODE_SELECT || xd->lossless[mbmi->segment_id]) {
Angie Chiangb5dda482016-11-02 16:19:58 -070011357 select_tx_type_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
Hui Su1ddf2312017-08-19 15:21:34 -070011358 assert(rd_stats_y.rate != INT_MAX);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011359 } else {
11360 int idx, idy;
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011361 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011362 for (idy = 0; idy < xd->n8_h; ++idy)
11363 for (idx = 0; idx < xd->n8_w; ++idx)
11364 mbmi->inter_tx_size[idy][idx] = mbmi->tx_size;
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011365 memset(x->blk_skip[0], rd_stats_y.skip,
Yaowu Xuc27fc142016-08-22 16:08:15 -070011366 sizeof(uint8_t) * xd->n8_h * xd->n8_w * 4);
11367 }
11368
Angie Chiangb5dda482016-11-02 16:19:58 -070011369 inter_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011370#else
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011371 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
Angie Chiang284d7772016-11-08 11:06:45 -080011372 super_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011373#endif // CONFIG_VAR_TX
11374 } else {
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011375 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
Angie Chiang284d7772016-11-08 11:06:45 -080011376 super_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011377 }
11378
Urvang Joshi70006e42017-06-14 16:08:55 -070011379 if (RDCOST(x->rdmult, rd_stats_y.rate + rd_stats_uv.rate,
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011380 (rd_stats_y.dist + rd_stats_uv.dist)) >
Urvang Joshi70006e42017-06-14 16:08:55 -070011381 RDCOST(x->rdmult, 0, (rd_stats_y.sse + rd_stats_uv.sse))) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011382 skip_blk = 1;
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011383 rd_stats_y.rate = av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
11384 rd_stats_uv.rate = 0;
11385 rd_stats_y.dist = rd_stats_y.sse;
11386 rd_stats_uv.dist = rd_stats_uv.sse;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011387 } else {
11388 skip_blk = 0;
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011389 rd_stats_y.rate += av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011390 }
11391
Urvang Joshi70006e42017-06-14 16:08:55 -070011392 if (RDCOST(x->rdmult, best_rate_y + best_rate_uv, rd_cost->dist) >
11393 RDCOST(x->rdmult, rd_stats_y.rate + rd_stats_uv.rate,
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011394 (rd_stats_y.dist + rd_stats_uv.dist))) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011395#if CONFIG_VAR_TX
11396 int idx, idy;
Fergus Simpson4063a682017-02-28 16:52:22 -080011397#endif // CONFIG_VAR_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -070011398 best_mbmode.tx_type = mbmi->tx_type;
11399 best_mbmode.tx_size = mbmi->tx_size;
11400#if CONFIG_VAR_TX
11401 for (idy = 0; idy < xd->n8_h; ++idy)
11402 for (idx = 0; idx < xd->n8_w; ++idx)
11403 best_mbmode.inter_tx_size[idy][idx] = mbmi->inter_tx_size[idy][idx];
11404
11405 for (i = 0; i < MAX_MB_PLANE; ++i)
11406 memcpy(ctx->blk_skip[i], x->blk_skip[i],
11407 sizeof(uint8_t) * ctx->num_4x4_blk);
Jingning Hane67b38a2016-11-04 10:30:00 -070011408
11409 best_mbmode.min_tx_size = mbmi->min_tx_size;
Fergus Simpson4063a682017-02-28 16:52:22 -080011410#endif // CONFIG_VAR_TX
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011411 rd_cost->rate +=
11412 (rd_stats_y.rate + rd_stats_uv.rate - best_rate_y - best_rate_uv);
11413 rd_cost->dist = rd_stats_y.dist + rd_stats_uv.dist;
Urvang Joshi70006e42017-06-14 16:08:55 -070011414 rd_cost->rdcost = RDCOST(x->rdmult, rd_cost->rate, rd_cost->dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011415 best_skip2 = skip_blk;
11416 }
11417 }
11418
11419 // Only try palette mode when the best mode so far is an intra mode.
hui su9bc1d8d2017-03-24 12:36:03 -070011420 if (try_palette && !is_inter_mode(best_mbmode.mode)) {
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011421 int rate2 = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011422#if CONFIG_SUPERTX
11423 int best_rate_nocoef;
Fergus Simpson4063a682017-02-28 16:52:22 -080011424#endif // CONFIG_SUPERTX
Urvang Joshi451e0f22017-01-31 11:18:31 -080011425 int64_t distortion2 = 0, best_rd_palette = best_rd, this_rd,
11426 best_model_rd_palette = INT64_MAX;
Urvang Joshi626591d2016-10-24 14:13:55 -070011427 int skippable = 0, rate_overhead_palette = 0;
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011428 RD_STATS rd_stats_y;
hui sude0c70a2017-01-09 17:12:17 -080011429 TX_SIZE uv_tx;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011430 uint8_t *const best_palette_color_map =
11431 x->palette_buffer->best_palette_color_map;
11432 uint8_t *const color_map = xd->plane[0].color_index_map;
Urvang Joshi451e0f22017-01-31 11:18:31 -080011433 MB_MODE_INFO best_mbmi_palette = best_mbmode;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011434
11435 mbmi->mode = DC_PRED;
Luc Trudeaud6d9eee2017-07-12 12:36:50 -040011436 mbmi->uv_mode = UV_DC_PRED;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011437 mbmi->ref_frame[0] = INTRA_FRAME;
Emil Keyder01770b32017-01-20 18:03:11 -050011438 mbmi->ref_frame[1] = NONE_FRAME;
Urvang Joshi626591d2016-10-24 14:13:55 -070011439 rate_overhead_palette = rd_pick_palette_intra_sby(
Urvang Joshi451e0f22017-01-31 11:18:31 -080011440 cpi, x, bsize, palette_ctx, intra_mode_cost[DC_PRED],
11441 &best_mbmi_palette, best_palette_color_map, &best_rd_palette,
11442 &best_model_rd_palette, NULL, NULL, NULL, NULL);
hui sude0c70a2017-01-09 17:12:17 -080011443 if (pmi->palette_size[0] == 0) goto PALETTE_EXIT;
11444 memcpy(color_map, best_palette_color_map,
11445 rows * cols * sizeof(best_palette_color_map[0]));
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011446 super_block_yrd(cpi, x, &rd_stats_y, bsize, best_rd);
11447 if (rd_stats_y.rate == INT_MAX) goto PALETTE_EXIT;
Debargha Mukherjee2f123402016-08-30 17:43:38 -070011448 uv_tx = uv_txsize_lookup[bsize][mbmi->tx_size][xd->plane[1].subsampling_x]
11449 [xd->plane[1].subsampling_y];
Yaowu Xuc27fc142016-08-22 16:08:15 -070011450 if (rate_uv_intra[uv_tx] == INT_MAX) {
Luc Trudeau9d4cbb82017-07-27 17:01:32 -040011451 choose_intra_uv_mode(cpi, x, bsize, uv_tx, &rate_uv_intra[uv_tx],
Urvang Joshi368fbc92016-10-17 16:31:34 -070011452 &rate_uv_tokenonly[uv_tx], &dist_uvs[uv_tx],
11453 &skip_uvs[uv_tx], &mode_uv[uv_tx]);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011454 pmi_uv[uv_tx] = *pmi;
11455#if CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011456 uv_angle_delta[uv_tx] = mbmi->angle_delta[1];
11457#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -070011458#if CONFIG_FILTER_INTRA
11459 filter_intra_mode_info_uv[uv_tx] = mbmi->filter_intra_mode_info;
11460#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011461 }
11462 mbmi->uv_mode = mode_uv[uv_tx];
11463 pmi->palette_size[1] = pmi_uv[uv_tx].palette_size[1];
hui sude0c70a2017-01-09 17:12:17 -080011464 if (pmi->palette_size[1] > 0) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011465 memcpy(pmi->palette_colors + PALETTE_MAX_SIZE,
11466 pmi_uv[uv_tx].palette_colors + PALETTE_MAX_SIZE,
11467 2 * PALETTE_MAX_SIZE * sizeof(pmi->palette_colors[0]));
hui sude0c70a2017-01-09 17:12:17 -080011468 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070011469#if CONFIG_EXT_INTRA
11470 mbmi->angle_delta[1] = uv_angle_delta[uv_tx];
Yaowu Xuc27fc142016-08-22 16:08:15 -070011471#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -070011472#if CONFIG_FILTER_INTRA
11473 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] =
11474 filter_intra_mode_info_uv[uv_tx].use_filter_intra_mode[1];
11475 if (filter_intra_mode_info_uv[uv_tx].use_filter_intra_mode[1]) {
11476 mbmi->filter_intra_mode_info.filter_intra_mode[1] =
11477 filter_intra_mode_info_uv[uv_tx].filter_intra_mode[1];
11478 }
11479#endif // CONFIG_FILTER_INTRA
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011480 skippable = rd_stats_y.skip && skip_uvs[uv_tx];
11481 distortion2 = rd_stats_y.dist + dist_uvs[uv_tx];
11482 rate2 = rd_stats_y.rate + rate_overhead_palette + rate_uv_intra[uv_tx];
Yaowu Xuc27fc142016-08-22 16:08:15 -070011483 rate2 += ref_costs_single[INTRA_FRAME];
11484
11485 if (skippable) {
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011486 rate2 -= (rd_stats_y.rate + rate_uv_tokenonly[uv_tx]);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011487#if CONFIG_SUPERTX
11488 best_rate_nocoef = rate2;
Fergus Simpson4063a682017-02-28 16:52:22 -080011489#endif // CONFIG_SUPERTX
Yaowu Xuf883b422016-08-30 14:01:10 -070011490 rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011491 } else {
11492#if CONFIG_SUPERTX
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011493 best_rate_nocoef = rate2 - (rd_stats_y.rate + rate_uv_tokenonly[uv_tx]);
Fergus Simpson4063a682017-02-28 16:52:22 -080011494#endif // CONFIG_SUPERTX
Yaowu Xuf883b422016-08-30 14:01:10 -070011495 rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011496 }
Urvang Joshi70006e42017-06-14 16:08:55 -070011497 this_rd = RDCOST(x->rdmult, rate2, distortion2);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011498 if (this_rd < best_rd) {
11499 best_mode_index = 3;
11500 mbmi->mv[0].as_int = 0;
11501 rd_cost->rate = rate2;
11502#if CONFIG_SUPERTX
11503 *returnrate_nocoef = best_rate_nocoef;
Fergus Simpson4063a682017-02-28 16:52:22 -080011504#endif // CONFIG_SUPERTX
Yaowu Xuc27fc142016-08-22 16:08:15 -070011505 rd_cost->dist = distortion2;
11506 rd_cost->rdcost = this_rd;
11507 best_rd = this_rd;
11508 best_mbmode = *mbmi;
11509 best_skip2 = 0;
11510 best_mode_skippable = skippable;
11511 }
11512 }
11513PALETTE_EXIT:
11514
hui su5db97432016-10-14 16:10:14 -070011515#if CONFIG_FILTER_INTRA
11516 // TODO(huisu): filter-intra is turned off in lossless mode for now to
Yaowu Xuc27fc142016-08-22 16:08:15 -070011517 // avoid a unit test failure
Urvang Joshic6300aa2017-06-01 14:46:23 -070011518 if (!xd->lossless[mbmi->segment_id] && pmi->palette_size[0] == 0 &&
Urvang Joshib100db72016-10-12 16:28:56 -070011519 !dc_skipped && best_mode_index >= 0 &&
11520 best_intra_rd < (best_rd + (best_rd >> 3))) {
hui su5db97432016-10-14 16:10:14 -070011521 pick_filter_intra_interframe(
Luc Trudeau9d4cbb82017-07-27 17:01:32 -040011522 cpi, x, bsize, mi_row, mi_col, rate_uv_intra, rate_uv_tokenonly,
Jingning Han18c53c82017-02-17 14:49:57 -080011523 dist_uvs, skip_uvs, mode_uv, filter_intra_mode_info_uv,
hui su5db97432016-10-14 16:10:14 -070011524#if CONFIG_EXT_INTRA
11525 uv_angle_delta,
11526#endif // CONFIG_EXT_INTRA
Urvang Joshic6300aa2017-06-01 14:46:23 -070011527 pmi_uv, palette_ctx, 0, ref_costs_single, &best_rd, &best_intra_rd,
11528 &best_intra_mode, &best_mode_index, &best_skip2, &best_mode_skippable,
Yaowu Xuc27fc142016-08-22 16:08:15 -070011529#if CONFIG_SUPERTX
11530 returnrate_nocoef,
11531#endif // CONFIG_SUPERTX
11532 best_pred_rd, &best_mbmode, rd_cost);
11533 }
hui su5db97432016-10-14 16:10:14 -070011534#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011535
Zoe Liu85b66462017-04-20 14:28:19 -070011536// The inter modes' rate costs are not calculated precisely in some cases.
11537// Therefore, sometimes, NEWMV is chosen instead of NEARESTMV, NEARMV, and
11538// ZEROMV. Here, checks are added for those cases, and the mode decisions
11539// are corrected.
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011540#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070011541// NOTE: For SR_NEW_NEWMV, no need to check as the two mvs from the same ref
11542// are surely different from each other.
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011543#endif // CONFIG_COMPOUND_SINGLEREF
11544 if (best_mbmode.mode == NEWMV || best_mbmode.mode == NEW_NEWMV) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011545 const MV_REFERENCE_FRAME refs[2] = { best_mbmode.ref_frame[0],
11546 best_mbmode.ref_frame[1] };
11547 int comp_pred_mode = refs[1] > INTRA_FRAME;
Sarah Parkere5299862016-08-16 14:57:37 -070011548 int_mv zeromv[2];
Yaowu Xuf883b422016-08-30 14:01:10 -070011549 const uint8_t rf_type = av1_ref_frame_type(best_mbmode.ref_frame);
Sarah Parkere5299862016-08-16 14:57:37 -070011550#if CONFIG_GLOBAL_MOTION
Debargha Mukherjeefebb59c2017-03-02 12:23:45 -080011551 zeromv[0].as_int = gm_get_motion_vector(&cm->global_motion[refs[0]],
11552 cm->allow_high_precision_mv, bsize,
RogerZhou3b635242017-09-19 10:06:46 -070011553 mi_col, mi_row, 0
11554#if CONFIG_AMVR
11555 ,
11556 cm->cur_frame_mv_precision_level
11557#endif
11558 )
Debargha Mukherjeefebb59c2017-03-02 12:23:45 -080011559 .as_int;
RogerZhou3b635242017-09-19 10:06:46 -070011560 zeromv[1].as_int =
11561 comp_pred_mode
11562 ? gm_get_motion_vector(&cm->global_motion[refs[1]],
11563 cm->allow_high_precision_mv, bsize, mi_col,
11564 mi_row, 0
11565#if CONFIG_AMVR
11566 ,
11567 cm->cur_frame_mv_precision_level
11568#endif
11569 )
11570 .as_int
11571 : 0;
Sarah Parkere5299862016-08-16 14:57:37 -070011572#else
11573 zeromv[0].as_int = 0;
11574 zeromv[1].as_int = 0;
11575#endif // CONFIG_GLOBAL_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070011576 if (!comp_pred_mode) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011577 int ref_set = (mbmi_ext->ref_mv_count[rf_type] >= 2)
Yaowu Xuf883b422016-08-30 14:01:10 -070011578 ? AOMMIN(2, mbmi_ext->ref_mv_count[rf_type] - 2)
Yaowu Xuc27fc142016-08-22 16:08:15 -070011579 : INT_MAX;
11580
11581 for (i = 0; i <= ref_set && ref_set != INT_MAX; ++i) {
11582 int_mv cur_mv = mbmi_ext->ref_mv_stack[rf_type][i + 1].this_mv;
11583 if (cur_mv.as_int == best_mbmode.mv[0].as_int) {
11584 best_mbmode.mode = NEARMV;
11585 best_mbmode.ref_mv_idx = i;
11586 }
11587 }
11588
11589 if (frame_mv[NEARESTMV][refs[0]].as_int == best_mbmode.mv[0].as_int)
11590 best_mbmode.mode = NEARESTMV;
Sarah Parkere5299862016-08-16 14:57:37 -070011591 else if (best_mbmode.mv[0].as_int == zeromv[0].as_int)
Yaowu Xuc27fc142016-08-22 16:08:15 -070011592 best_mbmode.mode = ZEROMV;
11593 } else {
11594 int_mv nearestmv[2];
11595 int_mv nearmv[2];
11596
Yaowu Xuc27fc142016-08-22 16:08:15 -070011597 if (mbmi_ext->ref_mv_count[rf_type] > 1) {
11598 nearmv[0] = mbmi_ext->ref_mv_stack[rf_type][1].this_mv;
11599 nearmv[1] = mbmi_ext->ref_mv_stack[rf_type][1].comp_mv;
11600 } else {
11601 nearmv[0] = frame_mv[NEARMV][refs[0]];
11602 nearmv[1] = frame_mv[NEARMV][refs[1]];
11603 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070011604 if (mbmi_ext->ref_mv_count[rf_type] >= 1) {
11605 nearestmv[0] = mbmi_ext->ref_mv_stack[rf_type][0].this_mv;
11606 nearestmv[1] = mbmi_ext->ref_mv_stack[rf_type][0].comp_mv;
11607 } else {
11608 nearestmv[0] = frame_mv[NEARESTMV][refs[0]];
11609 nearestmv[1] = frame_mv[NEARESTMV][refs[1]];
11610 }
11611
11612 if (nearestmv[0].as_int == best_mbmode.mv[0].as_int &&
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011613 nearestmv[1].as_int == best_mbmode.mv[1].as_int) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011614 best_mbmode.mode = NEAREST_NEARESTMV;
David Barker404b2e82017-03-27 13:07:47 +010011615 } else {
11616 int ref_set = (mbmi_ext->ref_mv_count[rf_type] >= 2)
11617 ? AOMMIN(2, mbmi_ext->ref_mv_count[rf_type] - 2)
11618 : INT_MAX;
11619
11620 for (i = 0; i <= ref_set && ref_set != INT_MAX; ++i) {
11621 nearmv[0] = mbmi_ext->ref_mv_stack[rf_type][i + 1].this_mv;
11622 nearmv[1] = mbmi_ext->ref_mv_stack[rf_type][i + 1].comp_mv;
11623
Debargha Mukherjeebb6e1342017-04-17 16:05:04 -070011624 // Try switching to the NEAR_NEARMV mode
11625 if (nearmv[0].as_int == best_mbmode.mv[0].as_int &&
David Barker404b2e82017-03-27 13:07:47 +010011626 nearmv[1].as_int == best_mbmode.mv[1].as_int) {
11627 best_mbmode.mode = NEAR_NEARMV;
11628 best_mbmode.ref_mv_idx = i;
11629 }
11630 }
11631
David Barker3dfba992017-04-03 16:10:09 +010011632 if (best_mbmode.mode == NEW_NEWMV &&
David Barker404b2e82017-03-27 13:07:47 +010011633 best_mbmode.mv[0].as_int == zeromv[0].as_int &&
11634 best_mbmode.mv[1].as_int == zeromv[1].as_int)
11635 best_mbmode.mode = ZERO_ZEROMV;
11636 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070011637 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070011638 }
11639
David Barker9620bcd2017-03-22 14:46:42 +000011640 // Make sure that the ref_mv_idx is only nonzero when we're
11641 // using a mode which can support ref_mv_idx
11642 if (best_mbmode.ref_mv_idx != 0 &&
Zoe Liu85b66462017-04-20 14:28:19 -070011643#if CONFIG_COMPOUND_SINGLEREF
11644 !(best_mbmode.mode == NEWMV || best_mbmode.mode == SR_NEW_NEWMV ||
11645 best_mbmode.mode == NEW_NEWMV ||
Yushin Cho67dda512017-07-25 14:58:22 -070011646 have_nearmv_in_inter_mode(best_mbmode.mode)))
Zoe Liu85b66462017-04-20 14:28:19 -070011647#else // !CONFIG_COMPOUND_SINGLEREF
David Barker3dfba992017-04-03 16:10:09 +010011648 !(best_mbmode.mode == NEWMV || best_mbmode.mode == NEW_NEWMV ||
Yushin Cho67dda512017-07-25 14:58:22 -070011649 have_nearmv_in_inter_mode(best_mbmode.mode)))
Zoe Liu85b66462017-04-20 14:28:19 -070011650#endif // CONFIG_COMPOUND_SINGLEREF
Yushin Cho67dda512017-07-25 14:58:22 -070011651 {
David Barker9620bcd2017-03-22 14:46:42 +000011652 best_mbmode.ref_mv_idx = 0;
11653 }
11654
Rupert Swarbrick799ff702017-10-04 17:37:52 +010011655 if (best_mbmode.ref_frame[0] > INTRA_FRAME &&
11656 best_mbmode.ref_frame[1] <= INTRA_FRAME) {
Jingning Han731af492016-11-17 11:53:23 -080011657 int8_t ref_frame_type = av1_ref_frame_type(best_mbmode.ref_frame);
11658 int16_t mode_ctx = mbmi_ext->mode_context[ref_frame_type];
David Barker68e6e862016-11-24 15:10:15 +000011659 if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET)) {
Rupert Swarbrick799ff702017-10-04 17:37:52 +010011660 int_mv zeromv;
David Barker68e6e862016-11-24 15:10:15 +000011661#if CONFIG_GLOBAL_MOTION
Rupert Swarbrick799ff702017-10-04 17:37:52 +010011662 const MV_REFERENCE_FRAME ref = best_mbmode.ref_frame[0];
11663 zeromv.as_int = gm_get_motion_vector(&cm->global_motion[ref],
11664 cm->allow_high_precision_mv, bsize,
11665 mi_col, mi_row, 0
RogerZhou3b635242017-09-19 10:06:46 -070011666#if CONFIG_AMVR
Rupert Swarbrick799ff702017-10-04 17:37:52 +010011667 ,
11668 cm->cur_frame_mv_precision_level
RogerZhou3b635242017-09-19 10:06:46 -070011669#endif
Rupert Swarbrick799ff702017-10-04 17:37:52 +010011670 )
11671 .as_int;
RogerZhou3b635242017-09-19 10:06:46 -070011672#else
Rupert Swarbrick799ff702017-10-04 17:37:52 +010011673 zeromv.as_int = 0;
David Barkercdcac6d2016-12-01 17:04:16 +000011674#endif // CONFIG_GLOBAL_MOTION
Rupert Swarbrick799ff702017-10-04 17:37:52 +010011675 if (best_mbmode.mv[0].as_int == zeromv.as_int) {
David Barkercdcac6d2016-12-01 17:04:16 +000011676 best_mbmode.mode = ZEROMV;
11677 }
David Barker68e6e862016-11-24 15:10:15 +000011678 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070011679 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070011680
11681 if (best_mode_index < 0 || best_rd >= best_rd_so_far) {
11682 rd_cost->rate = INT_MAX;
11683 rd_cost->rdcost = INT64_MAX;
11684 return;
11685 }
11686
Rupert Swarbrick27e90292017-09-28 17:46:50 +010011687 assert((cm->interp_filter == SWITCHABLE) ||
11688 (cm->interp_filter ==
11689 av1_extract_interp_filter(best_mbmode.interp_filters, 0)) ||
11690 !is_inter_block(&best_mbmode));
Yaowu Xuc27fc142016-08-22 16:08:15 -070011691#if CONFIG_DUAL_FILTER
11692 assert((cm->interp_filter == SWITCHABLE) ||
Rupert Swarbrick27e90292017-09-28 17:46:50 +010011693 (cm->interp_filter ==
11694 av1_extract_interp_filter(best_mbmode.interp_filters, 1)) ||
Yaowu Xuc27fc142016-08-22 16:08:15 -070011695 !is_inter_block(&best_mbmode));
Fergus Simpson4063a682017-02-28 16:52:22 -080011696#endif // CONFIG_DUAL_FILTER
Yaowu Xuc27fc142016-08-22 16:08:15 -070011697
11698 if (!cpi->rc.is_src_frame_alt_ref)
Yaowu Xuf883b422016-08-30 14:01:10 -070011699 av1_update_rd_thresh_fact(cm, tile_data->thresh_freq_fact,
11700 sf->adaptive_rd_thresh, bsize, best_mode_index);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011701
11702 // macroblock modes
11703 *mbmi = best_mbmode;
11704 x->skip |= best_skip2;
11705
Yue Chen19e7aa82016-11-30 14:05:39 -080011706// Note: this section is needed since the mode may have been forced to
11707// ZEROMV by the all-zero mode handling of ref-mv.
11708#if CONFIG_GLOBAL_MOTION
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011709 if (mbmi->mode == ZEROMV || mbmi->mode == ZERO_ZEROMV) {
Sarah Parker19234cc2017-03-10 16:43:25 -080011710#if CONFIG_WARPED_MOTION || CONFIG_MOTION_VAR
11711 // Correct the motion mode for ZEROMV
Sarah Parker0eea89f2017-07-11 11:56:36 -070011712 const MOTION_MODE last_motion_mode_allowed =
Yue Chen52c51732017-07-11 15:08:30 -070011713 motion_mode_allowed(0, xd->global_motion,
11714#if CONFIG_WARPED_MOTION
11715 xd,
11716#endif
11717 xd->mi[0]);
Sarah Parker19234cc2017-03-10 16:43:25 -080011718 if (mbmi->motion_mode > last_motion_mode_allowed)
11719 mbmi->motion_mode = last_motion_mode_allowed;
11720#endif // CONFIG_WARPED_MOTION || CONFIG_MOTION_VAR
11721
11722 // Correct the interpolation filter for ZEROMV
Yue Chen19e7aa82016-11-30 14:05:39 -080011723 if (is_nontrans_global_motion(xd)) {
Rupert Swarbrick27e90292017-09-28 17:46:50 +010011724 mbmi->interp_filters = av1_broadcast_interp_filter(
11725 av1_unswitchable_filter(cm->interp_filter));
Yue Chen19e7aa82016-11-30 14:05:39 -080011726 }
11727 }
11728#endif // CONFIG_GLOBAL_MOTION
11729
Yaowu Xuc27fc142016-08-22 16:08:15 -070011730 for (i = 0; i < 1 + has_second_ref(mbmi); ++i) {
11731 if (mbmi->mode != NEWMV)
11732 mbmi->pred_mv[i].as_int = mbmi->mv[i].as_int;
11733 else
11734 mbmi->pred_mv[i].as_int = mbmi_ext->ref_mvs[mbmi->ref_frame[i]][0].as_int;
11735 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070011736
11737 for (i = 0; i < REFERENCE_MODES; ++i) {
11738 if (best_pred_rd[i] == INT64_MAX)
11739 best_pred_diff[i] = INT_MIN;
11740 else
11741 best_pred_diff[i] = best_rd - best_pred_rd[i];
11742 }
11743
11744 x->skip |= best_mode_skippable;
11745
11746 assert(best_mode_index >= 0);
11747
11748 store_coding_context(x, ctx, best_mode_index, best_pred_diff,
11749 best_mode_skippable);
11750
Urvang Joshic9e71d42017-08-09 18:58:33 -070011751 if (pmi->palette_size[1] > 0) {
11752 assert(try_palette);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011753 restore_uv_color_map(cpi, x);
11754 }
11755}
11756
Urvang Joshi52648442016-10-13 17:27:51 -070011757void av1_rd_pick_inter_mode_sb_seg_skip(const AV1_COMP *cpi,
11758 TileDataEnc *tile_data, MACROBLOCK *x,
David Barker45390c12017-02-20 14:44:40 +000011759 int mi_row, int mi_col,
Angie Chiang2a2a7dd2017-04-25 16:08:47 -070011760 RD_STATS *rd_cost, BLOCK_SIZE bsize,
Yaowu Xuf883b422016-08-30 14:01:10 -070011761 PICK_MODE_CONTEXT *ctx,
11762 int64_t best_rd_so_far) {
Urvang Joshi52648442016-10-13 17:27:51 -070011763 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011764 MACROBLOCKD *const xd = &x->e_mbd;
11765 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
11766 unsigned char segment_id = mbmi->segment_id;
11767 const int comp_pred = 0;
11768 int i;
11769 int64_t best_pred_diff[REFERENCE_MODES];
11770 unsigned int ref_costs_single[TOTAL_REFS_PER_FRAME];
Zoe Liuc082bbc2017-05-17 13:31:37 -070011771#if CONFIG_EXT_COMP_REFS
11772 unsigned int ref_costs_comp[TOTAL_REFS_PER_FRAME][TOTAL_REFS_PER_FRAME];
11773#else
Yaowu Xuc27fc142016-08-22 16:08:15 -070011774 unsigned int ref_costs_comp[TOTAL_REFS_PER_FRAME];
Zoe Liuc082bbc2017-05-17 13:31:37 -070011775#endif // CONFIG_EXT_COMP_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -070011776 aom_prob comp_mode_p;
James Zern7b9407a2016-05-18 23:48:05 -070011777 InterpFilter best_filter = SWITCHABLE;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011778 int64_t this_rd = INT64_MAX;
11779 int rate2 = 0;
11780 const int64_t distortion2 = 0;
David Barker45390c12017-02-20 14:44:40 +000011781 (void)mi_row;
11782 (void)mi_col;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011783
11784 estimate_ref_frame_costs(cm, xd, segment_id, ref_costs_single, ref_costs_comp,
11785 &comp_mode_p);
11786
11787 for (i = 0; i < TOTAL_REFS_PER_FRAME; ++i) x->pred_sse[i] = INT_MAX;
11788 for (i = LAST_FRAME; i < TOTAL_REFS_PER_FRAME; ++i)
11789 x->pred_mv_sad[i] = INT_MAX;
11790
11791 rd_cost->rate = INT_MAX;
11792
11793 assert(segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP));
11794
11795 mbmi->palette_mode_info.palette_size[0] = 0;
11796 mbmi->palette_mode_info.palette_size[1] = 0;
Urvang Joshib100db72016-10-12 16:28:56 -070011797
hui su5db97432016-10-14 16:10:14 -070011798#if CONFIG_FILTER_INTRA
11799 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] = 0;
11800 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] = 0;
11801#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011802 mbmi->mode = ZEROMV;
Yue Chencb60b182016-10-13 15:18:22 -070011803 mbmi->motion_mode = SIMPLE_TRANSLATION;
Luc Trudeaud6d9eee2017-07-12 12:36:50 -040011804 mbmi->uv_mode = UV_DC_PRED;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011805 mbmi->ref_frame[0] = LAST_FRAME;
Emil Keyder01770b32017-01-20 18:03:11 -050011806 mbmi->ref_frame[1] = NONE_FRAME;
Sarah Parkere5299862016-08-16 14:57:37 -070011807#if CONFIG_GLOBAL_MOTION
11808 mbmi->mv[0].as_int =
Sarah Parkerae7c4582017-02-28 16:30:30 -080011809 gm_get_motion_vector(&cm->global_motion[mbmi->ref_frame[0]],
RogerZhou3b635242017-09-19 10:06:46 -070011810 cm->allow_high_precision_mv, bsize, mi_col, mi_row, 0
11811#if CONFIG_AMVR
11812 ,
11813 cm->cur_frame_mv_precision_level
11814#endif
11815 )
David Barkercdcac6d2016-12-01 17:04:16 +000011816 .as_int;
Sarah Parkere5299862016-08-16 14:57:37 -070011817#else // CONFIG_GLOBAL_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070011818 mbmi->mv[0].as_int = 0;
Sarah Parkere5299862016-08-16 14:57:37 -070011819#endif // CONFIG_GLOBAL_MOTION
Jingning Han64088952016-07-11 11:24:24 -070011820 mbmi->tx_size = max_txsize_lookup[bsize];
Yaowu Xuee775b12016-10-18 10:00:21 -070011821 x->skip = 1;
Sarah Parkere5299862016-08-16 14:57:37 -070011822
Yaowu Xuc27fc142016-08-22 16:08:15 -070011823 mbmi->ref_mv_idx = 0;
11824 mbmi->pred_mv[0].as_int = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011825
Yue Chendead17d2017-04-20 16:19:39 -070011826 mbmi->motion_mode = SIMPLE_TRANSLATION;
11827#if CONFIG_MOTION_VAR
11828 av1_count_overlappable_neighbors(cm, xd, mi_row, mi_col);
11829#endif
Yue Chenf3e1ead2017-04-21 14:05:51 -070011830#if CONFIG_WARPED_MOTION
11831 if (is_motion_variation_allowed_bsize(bsize) && !has_second_ref(mbmi)) {
11832 int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
Yunqing Wang1bc82862017-06-28 15:49:48 -070011833#if WARPED_MOTION_SORT_SAMPLES
11834 int pts_mv[SAMPLES_ARRAY_SIZE];
11835 mbmi->num_proj_ref[0] =
11836 findSamples(cm, xd, mi_row, mi_col, pts, pts_inref, pts_mv);
11837 // Rank the samples by motion vector difference
11838 if (mbmi->num_proj_ref[0] > 1)
11839 mbmi->num_proj_ref[0] = sortSamples(pts_mv, &mbmi->mv[0].as_mv, pts,
11840 pts_inref, mbmi->num_proj_ref[0]);
11841#else
Yue Chenf3e1ead2017-04-21 14:05:51 -070011842 mbmi->num_proj_ref[0] = findSamples(cm, xd, mi_row, mi_col, pts, pts_inref);
Yunqing Wang1bc82862017-06-28 15:49:48 -070011843#endif // WARPED_MOTION_SORT_SAMPLES
Yue Chenf3e1ead2017-04-21 14:05:51 -070011844 }
11845#endif
Yue Chendead17d2017-04-20 16:19:39 -070011846
Debargha Mukherjee0df711f2017-05-02 16:00:20 -070011847 set_default_interp_filters(mbmi, cm->interp_filter);
11848
11849 if (cm->interp_filter != SWITCHABLE) {
11850 best_filter = cm->interp_filter;
11851 } else {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011852 best_filter = EIGHTTAP_REGULAR;
Debargha Mukherjee0df711f2017-05-02 16:00:20 -070011853 if (av1_is_interp_needed(xd) && av1_is_interp_search_needed(xd) &&
Yaowu Xuc27fc142016-08-22 16:08:15 -070011854 x->source_variance >= cpi->sf.disable_filter_search_var_thresh) {
11855 int rs;
11856 int best_rs = INT_MAX;
11857 for (i = 0; i < SWITCHABLE_FILTERS; ++i) {
Rupert Swarbrick27e90292017-09-28 17:46:50 +010011858 mbmi->interp_filters = av1_broadcast_interp_filter(i);
Yue Chenb23d00a2017-07-28 17:01:21 -070011859 rs = av1_get_switchable_rate(cm, x, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011860 if (rs < best_rs) {
11861 best_rs = rs;
Rupert Swarbrick27e90292017-09-28 17:46:50 +010011862 best_filter = av1_extract_interp_filter(mbmi->interp_filters, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011863 }
11864 }
11865 }
11866 }
Rupert Swarbrick27e90292017-09-28 17:46:50 +010011867 // Set the appropriate filter
11868 mbmi->interp_filters = av1_broadcast_interp_filter(best_filter);
Yue Chenb23d00a2017-07-28 17:01:21 -070011869 rate2 += av1_get_switchable_rate(cm, x, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011870
11871 if (cm->reference_mode == REFERENCE_MODE_SELECT)
Yaowu Xuf883b422016-08-30 14:01:10 -070011872 rate2 += av1_cost_bit(comp_mode_p, comp_pred);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011873
11874 // Estimate the reference frame signaling cost and add it
11875 // to the rolling cost variable.
11876 rate2 += ref_costs_single[LAST_FRAME];
Urvang Joshi70006e42017-06-14 16:08:55 -070011877 this_rd = RDCOST(x->rdmult, rate2, distortion2);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011878
11879 rd_cost->rate = rate2;
11880 rd_cost->dist = distortion2;
11881 rd_cost->rdcost = this_rd;
Yushin Cho8e75e8b2017-09-12 16:33:28 -070011882
Yaowu Xuc27fc142016-08-22 16:08:15 -070011883 if (this_rd >= best_rd_so_far) {
11884 rd_cost->rate = INT_MAX;
11885 rd_cost->rdcost = INT64_MAX;
11886 return;
11887 }
11888
Yaowu Xuc27fc142016-08-22 16:08:15 -070011889 assert((cm->interp_filter == SWITCHABLE) ||
Rupert Swarbrick27e90292017-09-28 17:46:50 +010011890 (cm->interp_filter ==
11891 av1_extract_interp_filter(mbmi->interp_filters, 0)));
Yaowu Xuc27fc142016-08-22 16:08:15 -070011892
Yaowu Xuf883b422016-08-30 14:01:10 -070011893 av1_update_rd_thresh_fact(cm, tile_data->thresh_freq_fact,
11894 cpi->sf.adaptive_rd_thresh, bsize, THR_ZEROMV);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011895
Yaowu Xuf883b422016-08-30 14:01:10 -070011896 av1_zero(best_pred_diff);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011897
11898 store_coding_context(x, ctx, THR_ZEROMV, best_pred_diff, 0);
11899}
11900
Yue Chencb60b182016-10-13 15:18:22 -070011901#if CONFIG_MOTION_VAR
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010011902
11903struct calc_target_weighted_pred_ctxt {
11904 const MACROBLOCK *x;
11905 const uint8_t *tmp;
11906 int tmp_stride;
11907 int overlap;
11908};
11909
11910static INLINE void calc_target_weighted_pred_above(MACROBLOCKD *xd,
11911 int rel_mi_col,
11912 uint8_t nb_mi_width,
11913 MODE_INFO *nb_mi,
11914 void *fun_ctxt) {
11915 (void)nb_mi;
11916
11917 struct calc_target_weighted_pred_ctxt *ctxt =
11918 (struct calc_target_weighted_pred_ctxt *)fun_ctxt;
11919
11920#if CONFIG_HIGHBITDEPTH
11921 const int is_hbd = (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) ? 1 : 0;
11922#else
11923 const int is_hbd = 0;
11924#endif // CONFIG_HIGHBITDEPTH
11925
11926 const int bw = xd->n8_w << MI_SIZE_LOG2;
11927 const uint8_t *const mask1d = av1_get_obmc_mask(ctxt->overlap);
11928
11929 int32_t *wsrc = ctxt->x->wsrc_buf + (rel_mi_col * MI_SIZE);
11930 int32_t *mask = ctxt->x->mask_buf + (rel_mi_col * MI_SIZE);
11931 const uint8_t *tmp = ctxt->tmp + rel_mi_col * MI_SIZE;
11932
11933 if (!is_hbd) {
11934 for (int row = 0; row < ctxt->overlap; ++row) {
11935 const uint8_t m0 = mask1d[row];
11936 const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
11937 for (int col = 0; col < nb_mi_width * MI_SIZE; ++col) {
11938 wsrc[col] = m1 * tmp[col];
11939 mask[col] = m0;
11940 }
11941 wsrc += bw;
11942 mask += bw;
11943 tmp += ctxt->tmp_stride;
11944 }
11945#if CONFIG_HIGHBITDEPTH
11946 } else {
11947 const uint16_t *tmp16 = CONVERT_TO_SHORTPTR(tmp);
11948
11949 for (int row = 0; row < ctxt->overlap; ++row) {
11950 const uint8_t m0 = mask1d[row];
11951 const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
11952 for (int col = 0; col < nb_mi_width * MI_SIZE; ++col) {
11953 wsrc[col] = m1 * tmp16[col];
11954 mask[col] = m0;
11955 }
11956 wsrc += bw;
11957 mask += bw;
11958 tmp16 += ctxt->tmp_stride;
11959 }
11960#endif // CONFIG_HIGHBITDEPTH
11961 }
11962}
11963
11964static INLINE void calc_target_weighted_pred_left(MACROBLOCKD *xd,
11965 int rel_mi_row,
11966 uint8_t nb_mi_height,
11967 MODE_INFO *nb_mi,
11968 void *fun_ctxt) {
11969 (void)nb_mi;
11970
11971 struct calc_target_weighted_pred_ctxt *ctxt =
11972 (struct calc_target_weighted_pred_ctxt *)fun_ctxt;
11973
11974#if CONFIG_HIGHBITDEPTH
11975 const int is_hbd = (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) ? 1 : 0;
11976#else
11977 const int is_hbd = 0;
11978#endif // CONFIG_HIGHBITDEPTH
11979
11980 const int bw = xd->n8_w << MI_SIZE_LOG2;
11981 const uint8_t *const mask1d = av1_get_obmc_mask(ctxt->overlap);
11982
11983 int32_t *wsrc = ctxt->x->wsrc_buf + (rel_mi_row * MI_SIZE * bw);
11984 int32_t *mask = ctxt->x->mask_buf + (rel_mi_row * MI_SIZE * bw);
11985 const uint8_t *tmp = ctxt->tmp + (rel_mi_row * MI_SIZE * ctxt->tmp_stride);
11986
11987 if (!is_hbd) {
11988 for (int row = 0; row < nb_mi_height * MI_SIZE; ++row) {
11989 for (int col = 0; col < ctxt->overlap; ++col) {
11990 const uint8_t m0 = mask1d[col];
11991 const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
11992 wsrc[col] = (wsrc[col] >> AOM_BLEND_A64_ROUND_BITS) * m0 +
11993 (tmp[col] << AOM_BLEND_A64_ROUND_BITS) * m1;
11994 mask[col] = (mask[col] >> AOM_BLEND_A64_ROUND_BITS) * m0;
11995 }
11996 wsrc += bw;
11997 mask += bw;
11998 tmp += ctxt->tmp_stride;
11999 }
12000#if CONFIG_HIGHBITDEPTH
12001 } else {
12002 const uint16_t *tmp16 = CONVERT_TO_SHORTPTR(tmp);
12003
12004 for (int row = 0; row < nb_mi_height * MI_SIZE; ++row) {
12005 for (int col = 0; col < ctxt->overlap; ++col) {
12006 const uint8_t m0 = mask1d[col];
12007 const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
12008 wsrc[col] = (wsrc[col] >> AOM_BLEND_A64_ROUND_BITS) * m0 +
12009 (tmp16[col] << AOM_BLEND_A64_ROUND_BITS) * m1;
12010 mask[col] = (mask[col] >> AOM_BLEND_A64_ROUND_BITS) * m0;
12011 }
12012 wsrc += bw;
12013 mask += bw;
12014 tmp16 += ctxt->tmp_stride;
12015 }
12016#endif // CONFIG_HIGHBITDEPTH
12017 }
12018}
12019
Yaowu Xuf883b422016-08-30 14:01:10 -070012020// This function has a structure similar to av1_build_obmc_inter_prediction
Yaowu Xuc27fc142016-08-22 16:08:15 -070012021//
12022// The OBMC predictor is computed as:
12023//
12024// PObmc(x,y) =
Yaowu Xuf883b422016-08-30 14:01:10 -070012025// AOM_BLEND_A64(Mh(x),
12026// AOM_BLEND_A64(Mv(y), P(x,y), PAbove(x,y)),
Yaowu Xuc27fc142016-08-22 16:08:15 -070012027// PLeft(x, y))
12028//
Yaowu Xuf883b422016-08-30 14:01:10 -070012029// Scaling up by AOM_BLEND_A64_MAX_ALPHA ** 2 and omitting the intermediate
Yaowu Xuc27fc142016-08-22 16:08:15 -070012030// rounding, this can be written as:
12031//
Yaowu Xuf883b422016-08-30 14:01:10 -070012032// AOM_BLEND_A64_MAX_ALPHA * AOM_BLEND_A64_MAX_ALPHA * Pobmc(x,y) =
Yaowu Xuc27fc142016-08-22 16:08:15 -070012033// Mh(x) * Mv(y) * P(x,y) +
12034// Mh(x) * Cv(y) * Pabove(x,y) +
Yaowu Xuf883b422016-08-30 14:01:10 -070012035// AOM_BLEND_A64_MAX_ALPHA * Ch(x) * PLeft(x, y)
Yaowu Xuc27fc142016-08-22 16:08:15 -070012036//
12037// Where :
12038//
Yaowu Xuf883b422016-08-30 14:01:10 -070012039// Cv(y) = AOM_BLEND_A64_MAX_ALPHA - Mv(y)
12040// Ch(y) = AOM_BLEND_A64_MAX_ALPHA - Mh(y)
Yaowu Xuc27fc142016-08-22 16:08:15 -070012041//
12042// This function computes 'wsrc' and 'mask' as:
12043//
12044// wsrc(x, y) =
Yaowu Xuf883b422016-08-30 14:01:10 -070012045// AOM_BLEND_A64_MAX_ALPHA * AOM_BLEND_A64_MAX_ALPHA * src(x, y) -
Yaowu Xuc27fc142016-08-22 16:08:15 -070012046// Mh(x) * Cv(y) * Pabove(x,y) +
Yaowu Xuf883b422016-08-30 14:01:10 -070012047// AOM_BLEND_A64_MAX_ALPHA * Ch(x) * PLeft(x, y)
Yaowu Xuc27fc142016-08-22 16:08:15 -070012048//
12049// mask(x, y) = Mh(x) * Mv(y)
12050//
12051// These can then be used to efficiently approximate the error for any
12052// predictor P in the context of the provided neighbouring predictors by
12053// computing:
12054//
12055// error(x, y) =
Yaowu Xuf883b422016-08-30 14:01:10 -070012056// wsrc(x, y) - mask(x, y) * P(x, y) / (AOM_BLEND_A64_MAX_ALPHA ** 2)
Yaowu Xuc27fc142016-08-22 16:08:15 -070012057//
Yaowu Xuf883b422016-08-30 14:01:10 -070012058static void calc_target_weighted_pred(const AV1_COMMON *cm, const MACROBLOCK *x,
Yaowu Xuc27fc142016-08-22 16:08:15 -070012059 const MACROBLOCKD *xd, int mi_row,
12060 int mi_col, const uint8_t *above,
12061 int above_stride, const uint8_t *left,
Yue Chene9638cc2016-10-10 12:37:54 -070012062 int left_stride) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070012063 const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
Jingning Hanff6ee6a2016-12-07 09:55:21 -080012064 const int bw = xd->n8_w << MI_SIZE_LOG2;
12065 const int bh = xd->n8_h << MI_SIZE_LOG2;
Yue Chene9638cc2016-10-10 12:37:54 -070012066 int32_t *mask_buf = x->mask_buf;
12067 int32_t *wsrc_buf = x->wsrc_buf;
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012068
Yaowu Xuf883b422016-08-30 14:01:10 -070012069 const int src_scale = AOM_BLEND_A64_MAX_ALPHA * AOM_BLEND_A64_MAX_ALPHA;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020012070#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070012071 const int is_hbd = (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) ? 1 : 0;
12072#else
12073 const int is_hbd = 0;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020012074#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070012075
12076 // plane 0 should not be subsampled
12077 assert(xd->plane[0].subsampling_x == 0);
12078 assert(xd->plane[0].subsampling_y == 0);
12079
Yaowu Xuf883b422016-08-30 14:01:10 -070012080 av1_zero_array(wsrc_buf, bw * bh);
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012081 for (int i = 0; i < bw * bh; ++i) mask_buf[i] = AOM_BLEND_A64_MAX_ALPHA;
Yaowu Xuc27fc142016-08-22 16:08:15 -070012082
12083 // handle above row
12084 if (xd->up_available) {
Jingning Han440d4252017-07-24 14:07:34 -070012085 const int overlap =
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012086 AOMMIN(block_size_high[bsize], block_size_high[BLOCK_64X64]) >> 1;
12087 struct calc_target_weighted_pred_ctxt ctxt = { x, above, above_stride,
12088 overlap };
12089 foreach_overlappable_nb_above(cm, (MACROBLOCKD *)xd, mi_col,
12090 max_neighbor_obmc[b_width_log2_lookup[bsize]],
12091 calc_target_weighted_pred_above, &ctxt);
Yaowu Xuc27fc142016-08-22 16:08:15 -070012092 }
12093
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012094 for (int i = 0; i < bw * bh; ++i) {
Yaowu Xuf883b422016-08-30 14:01:10 -070012095 wsrc_buf[i] *= AOM_BLEND_A64_MAX_ALPHA;
12096 mask_buf[i] *= AOM_BLEND_A64_MAX_ALPHA;
Yaowu Xuc27fc142016-08-22 16:08:15 -070012097 }
12098
12099 // handle left column
12100 if (xd->left_available) {
Jingning Han440d4252017-07-24 14:07:34 -070012101 const int overlap =
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012102 AOMMIN(block_size_wide[bsize], block_size_wide[BLOCK_64X64]) >> 1;
12103 struct calc_target_weighted_pred_ctxt ctxt = { x, left, left_stride,
12104 overlap };
12105 foreach_overlappable_nb_left(cm, (MACROBLOCKD *)xd, mi_row,
12106 max_neighbor_obmc[b_height_log2_lookup[bsize]],
12107 calc_target_weighted_pred_left, &ctxt);
Yaowu Xuc27fc142016-08-22 16:08:15 -070012108 }
12109
12110 if (!is_hbd) {
12111 const uint8_t *src = x->plane[0].src.buf;
12112
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012113 for (int row = 0; row < bh; ++row) {
12114 for (int col = 0; col < bw; ++col) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070012115 wsrc_buf[col] = src[col] * src_scale - wsrc_buf[col];
12116 }
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012117 wsrc_buf += bw;
Yaowu Xuc27fc142016-08-22 16:08:15 -070012118 src += x->plane[0].src.stride;
12119 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020012120#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070012121 } else {
12122 const uint16_t *src = CONVERT_TO_SHORTPTR(x->plane[0].src.buf);
12123
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012124 for (int row = 0; row < bh; ++row) {
12125 for (int col = 0; col < bw; ++col) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070012126 wsrc_buf[col] = src[col] * src_scale - wsrc_buf[col];
12127 }
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012128 wsrc_buf += bw;
Yaowu Xuc27fc142016-08-22 16:08:15 -070012129 src += x->plane[0].src.stride;
12130 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020012131#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070012132 }
12133}
Yue Chenf27b1602017-01-13 11:11:43 -080012134
12135#if CONFIG_NCOBMC
12136void av1_check_ncobmc_rd(const struct AV1_COMP *cpi, struct macroblock *x,
12137 int mi_row, int mi_col) {
12138 const AV1_COMMON *const cm = &cpi->common;
12139 MACROBLOCKD *const xd = &x->e_mbd;
12140 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
12141 MB_MODE_INFO backup_mbmi;
12142 BLOCK_SIZE bsize = mbmi->sb_type;
12143 int ref, skip_blk, backup_skip = x->skip;
12144 int64_t rd_causal;
12145 RD_STATS rd_stats_y, rd_stats_uv;
12146 int rate_skip0 = av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
12147 int rate_skip1 = av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
12148
12149 // Recompute the best causal predictor and rd
12150 mbmi->motion_mode = SIMPLE_TRANSLATION;
12151 set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
12152 for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) {
12153 YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi, mbmi->ref_frame[ref]);
12154 assert(cfg != NULL);
12155 av1_setup_pre_planes(xd, ref, cfg, mi_row, mi_col,
12156 &xd->block_refs[ref]->sf);
12157 }
Jingning Han91d9a792017-04-18 12:01:52 -070012158 av1_setup_dst_planes(x->e_mbd.plane, bsize,
12159 get_frame_new_buffer(&cpi->common), mi_row, mi_col);
Yue Chenf27b1602017-01-13 11:11:43 -080012160
Jingning Hanc44009c2017-05-06 11:36:49 -070012161 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, NULL, bsize);
Yue Chenf27b1602017-01-13 11:11:43 -080012162
12163 av1_subtract_plane(x, bsize, 0);
Wei-Ting Linba5f1872017-07-06 12:26:09 -070012164#if CONFIG_VAR_TX
12165 if (cm->tx_mode == TX_MODE_SELECT && !xd->lossless[mbmi->segment_id]) {
12166 select_tx_type_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12167 } else {
12168 int idx, idy;
12169 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12170 for (idy = 0; idy < xd->n8_h; ++idy)
12171 for (idx = 0; idx < xd->n8_w; ++idx)
12172 mbmi->inter_tx_size[idy][idx] = mbmi->tx_size;
12173 memset(x->blk_skip[0], rd_stats_y.skip,
12174 sizeof(uint8_t) * xd->n8_h * xd->n8_w * 4);
12175 }
12176 inter_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
12177#else
Yue Chenf27b1602017-01-13 11:11:43 -080012178 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12179 super_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
Wei-Ting Linba5f1872017-07-06 12:26:09 -070012180#endif
Yue Chenf27b1602017-01-13 11:11:43 -080012181 assert(rd_stats_y.rate != INT_MAX && rd_stats_uv.rate != INT_MAX);
12182 if (rd_stats_y.skip && rd_stats_uv.skip) {
12183 rd_stats_y.rate = rate_skip1;
12184 rd_stats_uv.rate = 0;
12185 rd_stats_y.dist = rd_stats_y.sse;
12186 rd_stats_uv.dist = rd_stats_uv.sse;
12187 skip_blk = 0;
Urvang Joshi70006e42017-06-14 16:08:55 -070012188 } else if (RDCOST(x->rdmult,
Yue Chenf27b1602017-01-13 11:11:43 -080012189 (rd_stats_y.rate + rd_stats_uv.rate + rate_skip0),
12190 (rd_stats_y.dist + rd_stats_uv.dist)) >
Urvang Joshi70006e42017-06-14 16:08:55 -070012191 RDCOST(x->rdmult, rate_skip1,
Yue Chenf27b1602017-01-13 11:11:43 -080012192 (rd_stats_y.sse + rd_stats_uv.sse))) {
12193 rd_stats_y.rate = rate_skip1;
12194 rd_stats_uv.rate = 0;
12195 rd_stats_y.dist = rd_stats_y.sse;
12196 rd_stats_uv.dist = rd_stats_uv.sse;
12197 skip_blk = 1;
12198 } else {
12199 rd_stats_y.rate += rate_skip0;
12200 skip_blk = 0;
12201 }
12202 backup_skip = skip_blk;
12203 backup_mbmi = *mbmi;
Urvang Joshi70006e42017-06-14 16:08:55 -070012204 rd_causal = RDCOST(x->rdmult, (rd_stats_y.rate + rd_stats_uv.rate),
Yue Chenf27b1602017-01-13 11:11:43 -080012205 (rd_stats_y.dist + rd_stats_uv.dist));
Urvang Joshi70006e42017-06-14 16:08:55 -070012206 rd_causal +=
12207 RDCOST(x->rdmult, av1_cost_bit(cm->fc->motion_mode_prob[bsize][0], 0), 0);
Yue Chenf27b1602017-01-13 11:11:43 -080012208
12209 // Check non-causal mode
12210 mbmi->motion_mode = OBMC_CAUSAL;
12211 av1_build_ncobmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
12212
12213 av1_subtract_plane(x, bsize, 0);
Wei-Ting Linba5f1872017-07-06 12:26:09 -070012214#if CONFIG_VAR_TX
12215 if (cm->tx_mode == TX_MODE_SELECT && !xd->lossless[mbmi->segment_id]) {
12216 select_tx_type_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12217 } else {
12218 int idx, idy;
12219 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12220 for (idy = 0; idy < xd->n8_h; ++idy)
12221 for (idx = 0; idx < xd->n8_w; ++idx)
12222 mbmi->inter_tx_size[idy][idx] = mbmi->tx_size;
12223 memset(x->blk_skip[0], rd_stats_y.skip,
12224 sizeof(uint8_t) * xd->n8_h * xd->n8_w * 4);
12225 }
12226 inter_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
12227#else
Yue Chenf27b1602017-01-13 11:11:43 -080012228 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12229 super_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
Wei-Ting Linba5f1872017-07-06 12:26:09 -070012230#endif
Yue Chenf27b1602017-01-13 11:11:43 -080012231 assert(rd_stats_y.rate != INT_MAX && rd_stats_uv.rate != INT_MAX);
12232 if (rd_stats_y.skip && rd_stats_uv.skip) {
12233 rd_stats_y.rate = rate_skip1;
12234 rd_stats_uv.rate = 0;
12235 rd_stats_y.dist = rd_stats_y.sse;
12236 rd_stats_uv.dist = rd_stats_uv.sse;
12237 skip_blk = 0;
Urvang Joshi70006e42017-06-14 16:08:55 -070012238 } else if (RDCOST(x->rdmult,
Yue Chenf27b1602017-01-13 11:11:43 -080012239 (rd_stats_y.rate + rd_stats_uv.rate + rate_skip0),
12240 (rd_stats_y.dist + rd_stats_uv.dist)) >
Urvang Joshi70006e42017-06-14 16:08:55 -070012241 RDCOST(x->rdmult, rate_skip1,
Yue Chenf27b1602017-01-13 11:11:43 -080012242 (rd_stats_y.sse + rd_stats_uv.sse))) {
12243 rd_stats_y.rate = rate_skip1;
12244 rd_stats_uv.rate = 0;
12245 rd_stats_y.dist = rd_stats_y.sse;
12246 rd_stats_uv.dist = rd_stats_uv.sse;
12247 skip_blk = 1;
12248 } else {
12249 rd_stats_y.rate += rate_skip0;
12250 skip_blk = 0;
12251 }
12252
12253 if (rd_causal >
clang-format4eafefe2017-09-04 12:51:20 -070012254 RDCOST(x->rdmult,
12255 rd_stats_y.rate + rd_stats_uv.rate +
12256 av1_cost_bit(cm->fc->motion_mode_prob[bsize][0], 1),
Yue Chenf27b1602017-01-13 11:11:43 -080012257 (rd_stats_y.dist + rd_stats_uv.dist))) {
12258 x->skip = skip_blk;
12259 } else {
12260 *mbmi = backup_mbmi;
12261 x->skip = backup_skip;
12262 }
12263}
Fergus Simpson4063a682017-02-28 16:52:22 -080012264#endif // CONFIG_NCOBMC
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012265
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012266int64_t get_prediction_rd_cost(const struct AV1_COMP *cpi, struct macroblock *x,
12267 int mi_row, int mi_col, int *skip_blk,
12268 MB_MODE_INFO *backup_mbmi) {
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012269 const AV1_COMMON *const cm = &cpi->common;
12270 MACROBLOCKD *const xd = &x->e_mbd;
12271 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
12272 BLOCK_SIZE bsize = mbmi->sb_type;
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012273#if CONFIG_NCOBMC_ADAPT_WEIGHT && CONFIG_WARPED_MOTION
12274 const MOTION_MODE motion_allowed = motion_mode_allowed(
12275#if CONFIG_GLOBAL_MOTION
12276 0, xd->global_motion,
12277#endif // CONFIG_GLOBAL_MOTION
12278#if CONFIG_WARPED_MOTION
12279 xd,
12280#endif
12281 xd->mi[0]);
12282#endif // CONFIG_NCOBMC_ADAPT_WEIGHT && CONFIG_WARPED_MOTION
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012283 RD_STATS rd_stats_y, rd_stats_uv;
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012284 int rate_skip0 = av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
12285 int rate_skip1 = av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012286 int64_t this_rd;
12287 int ref;
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012288
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012289#if CONFIG_CB4X4
12290 x->skip_chroma_rd =
12291 !is_chroma_reference(mi_row, mi_col, bsize, xd->plane[1].subsampling_x,
12292 xd->plane[1].subsampling_y);
12293#endif
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012294
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012295 set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
12296 for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) {
12297 YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi, mbmi->ref_frame[ref]);
12298 assert(cfg != NULL);
12299 av1_setup_pre_planes(xd, ref, cfg, mi_row, mi_col,
12300 &xd->block_refs[ref]->sf);
12301 }
12302 av1_setup_dst_planes(x->e_mbd.plane, bsize,
12303 get_frame_new_buffer(&cpi->common), mi_row, mi_col);
12304
12305#if CONFIG_NCOBMC_ADAPT_WEIGHT
12306 if (mbmi->motion_mode != NCOBMC_ADAPT_WEIGHT)
12307#endif
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012308 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, NULL, bsize);
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012309
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012310#if CONFIG_MOTION_VAR
12311 if (mbmi->motion_mode == OBMC_CAUSAL) {
12312#if CONFIG_NCOBMC
12313 av1_build_ncobmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012314#else
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012315 av1_build_obmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012316#endif
12317 }
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012318#endif // CONFIG_MOTION_VAR
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012319
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012320#if CONFIG_NCOBMC_ADAPT_WEIGHT
12321 if (mbmi->motion_mode == NCOBMC_ADAPT_WEIGHT)
12322 for (int plane = 0; plane < MAX_MB_PLANE; ++plane)
12323 get_pred_from_intrpl_buf(xd, mi_row, mi_col, bsize, plane);
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012324#endif
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012325 av1_subtract_plane(x, bsize, 0);
12326
12327#if CONFIG_VAR_TX
12328 if (cm->tx_mode == TX_MODE_SELECT && !xd->lossless[mbmi->segment_id]) {
12329 select_tx_type_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12330 } else {
12331 int idx, idy;
12332 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12333 for (idy = 0; idy < xd->n8_h; ++idy)
12334 for (idx = 0; idx < xd->n8_w; ++idx)
12335 mbmi->inter_tx_size[idy][idx] = mbmi->tx_size;
12336 memset(x->blk_skip[0], rd_stats_y.skip,
12337 sizeof(uint8_t) * xd->n8_h * xd->n8_w * 4);
12338 }
12339 inter_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
12340#else
12341 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12342 super_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
12343#endif
12344 assert(rd_stats_y.rate != INT_MAX && rd_stats_uv.rate != INT_MAX);
12345
12346 if (rd_stats_y.skip && rd_stats_uv.skip) {
12347 rd_stats_y.rate = rate_skip1;
12348 rd_stats_uv.rate = 0;
12349 rd_stats_y.dist = rd_stats_y.sse;
12350 rd_stats_uv.dist = rd_stats_uv.sse;
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012351 *skip_blk = 1;
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012352 } else if (RDCOST(x->rdmult,
12353 (rd_stats_y.rate + rd_stats_uv.rate + rate_skip0),
12354 (rd_stats_y.dist + rd_stats_uv.dist)) >
12355 RDCOST(x->rdmult, rate_skip1,
12356 (rd_stats_y.sse + rd_stats_uv.sse))) {
12357 rd_stats_y.rate = rate_skip1;
12358 rd_stats_uv.rate = 0;
12359 rd_stats_y.dist = rd_stats_y.sse;
12360 rd_stats_uv.dist = rd_stats_uv.sse;
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012361 *skip_blk = 1;
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012362 } else {
12363 rd_stats_y.rate += rate_skip0;
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012364 *skip_blk = 0;
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012365 }
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012366
12367 if (backup_mbmi) *backup_mbmi = *mbmi;
12368
12369 this_rd = RDCOST(x->rdmult, (rd_stats_y.rate + rd_stats_uv.rate),
12370 (rd_stats_y.dist + rd_stats_uv.dist));
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012371#if CONFIG_NCOBMC_ADAPT_WEIGHT && CONFIG_WARPED_MOTION
12372 if (motion_allowed == NCOBMC_ADAPT_WEIGHT) {
12373 assert(mbmi->motion_mode <= NCOBMC_ADAPT_WEIGHT);
12374 this_rd +=
12375 RDCOST(x->rdmult, x->motion_mode_cost2[bsize][mbmi->motion_mode], 0);
12376 } else if (motion_allowed == OBMC_CAUSAL) {
12377 assert(mbmi->motion_mode <= OBMC_CAUSAL);
12378 this_rd +=
12379 RDCOST(x->rdmult, x->motion_mode_cost1[bsize][mbmi->motion_mode], 0);
12380 } else {
12381#endif // CONFIG_NCOBMC_ADAPT_WEIGHT && CONFIG_WARPED_MOTION
12382 this_rd +=
12383 RDCOST(x->rdmult, x->motion_mode_cost[bsize][mbmi->motion_mode], 0);
12384#if CONFIG_NCOBMC_ADAPT_WEIGHT && CONFIG_WARPED_MOTION
12385 }
12386#endif // CONFIG_NCOBMC_ADAPT_WEIGHT && CONFIG_WARPED_MOTION
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012387 return this_rd;
12388}
12389
12390#if CONFIG_NCOBMC_ADAPT_WEIGHT
12391void av1_check_ncobmc_adapt_weight_rd(const struct AV1_COMP *cpi,
12392 struct macroblock *x, int mi_row,
12393 int mi_col) {
12394 MACROBLOCKD *const xd = &x->e_mbd;
12395 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
12396 BLOCK_SIZE bsize = mbmi->sb_type;
12397#if CONFIG_VAR_TX
12398 const int n4 = bsize_to_num_blk(bsize);
12399 uint8_t st_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE * 8];
12400 uint8_t obmc_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE * 8];
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012401 uint8_t ncobmc_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE * 8];
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012402#endif
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012403 MB_MODE_INFO st_mbmi, obmc_mbmi, ncobmc_mbmi;
12404 int st_skip, obmc_skip, ncobmc_skip;
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012405 int64_t st_rd, obmc_rd, ncobmc_rd;
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012406#if CONFIG_WARPED_MOTION
12407 const AV1_COMMON *const cm = &cpi->common;
12408 const int is_warp_motion = mbmi->motion_mode == WARPED_CAUSAL;
12409 const int rs = RDCOST(x->rdmult, av1_get_switchable_rate(cm, x, xd), 0);
12410 MB_MODE_INFO warp_mbmi;
12411 int64_t warp_rd;
12412 int warp_skip;
12413#endif
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012414
12415 // Recompute the rd for the motion mode decided in rd loop
12416 mbmi->motion_mode = SIMPLE_TRANSLATION;
12417 st_rd = get_prediction_rd_cost(cpi, x, mi_row, mi_col, &st_skip, &st_mbmi);
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012418#if CONFIG_WARPED_MOTION
12419 st_rd += rs;
12420#endif
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012421#if CONFIG_VAR_TX
12422 memcpy(st_blk_skip, x->blk_skip[0], sizeof(st_blk_skip[0]) * n4);
12423#endif
12424
12425 mbmi->motion_mode = OBMC_CAUSAL;
12426 obmc_rd =
12427 get_prediction_rd_cost(cpi, x, mi_row, mi_col, &obmc_skip, &obmc_mbmi);
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012428#if CONFIG_WARPED_MOTION
12429 obmc_rd += rs;
12430#endif
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012431#if CONFIG_VAR_TX
12432 memcpy(obmc_blk_skip, x->blk_skip[0], sizeof(obmc_blk_skip[0]) * n4);
12433#endif
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012434
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012435 // Compute the rd cost for ncobmc adaptive weight
12436 mbmi->motion_mode = NCOBMC_ADAPT_WEIGHT;
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012437 ncobmc_rd = get_prediction_rd_cost(cpi, x, mi_row, mi_col, &ncobmc_skip,
12438 &ncobmc_mbmi);
12439#if CONFIG_WARPED_MOTION
12440 ncobmc_rd += rs;
12441#endif
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012442 // Calculate the ncobmc mode costs
12443 {
12444 ADAPT_OVERLAP_BLOCK aob = adapt_overlap_block_lookup[bsize];
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012445 ncobmc_rd +=
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012446 RDCOST(x->rdmult, x->ncobmc_mode_cost[aob][mbmi->ncobmc_mode[0]], 0);
12447 if (mi_size_wide[bsize] != mi_size_high[bsize])
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012448 ncobmc_rd +=
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012449 RDCOST(x->rdmult, x->ncobmc_mode_cost[aob][mbmi->ncobmc_mode[1]], 0);
12450 }
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012451#if CONFIG_VAR_TX
12452 memcpy(ncobmc_blk_skip, x->blk_skip[0], sizeof(ncobmc_blk_skip[0]) * n4);
12453#endif
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012454
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012455#if CONFIG_WARPED_MOTION
12456 if (is_warp_motion) {
12457 mbmi->motion_mode = WARPED_CAUSAL;
12458 warp_rd =
12459 get_prediction_rd_cost(cpi, x, mi_row, mi_col, &warp_skip, &warp_mbmi);
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012460 } else {
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012461 warp_rd = INT64_MAX;
12462 }
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012463#endif
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012464
12465#if CONFIG_WARPED_MOTION
12466 if (AOMMIN(ncobmc_rd, warp_rd) < AOMMIN(st_rd, obmc_rd)) {
12467 if (ncobmc_rd < warp_rd) {
12468 x->skip = ncobmc_skip;
12469 *mbmi = ncobmc_mbmi;
12470#if CONFIG_VAR_TX
12471 memcpy(x->blk_skip[0], ncobmc_blk_skip, sizeof(ncobmc_blk_skip[0]) * n4);
12472#endif
12473 } else {
12474 x->skip = warp_skip;
12475 *mbmi = warp_mbmi;
12476 }
12477#else
12478 if (ncobmc_rd < AOMMIN(st_rd, obmc_rd)) {
12479 x->skip = ncobmc_skip;
12480 *mbmi = ncobmc_mbmi;
12481#if CONFIG_VAR_TX
12482 memcpy(x->blk_skip[0], ncobmc_blk_skip, sizeof(ncobmc_blk_skip[0]) * n4);
12483#endif
12484#endif // CONFIG_WARPED_MOTION
12485 } else {
12486 if (obmc_rd < st_rd) {
12487 *mbmi = obmc_mbmi;
12488 x->skip = obmc_skip;
12489#if CONFIG_VAR_TX
12490 memcpy(x->blk_skip[0], obmc_blk_skip, sizeof(obmc_blk_skip[0]) * n4);
12491#endif
12492 } else {
12493 *mbmi = st_mbmi;
12494 x->skip = st_skip;
12495#if CONFIG_VAR_TX
12496 memcpy(x->blk_skip[0], st_blk_skip, sizeof(st_blk_skip[0]) * n4);
12497#endif
12498 }
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012499 }
12500}
12501
12502int64_t get_ncobmc_error(MACROBLOCKD *xd, int pxl_row, int pxl_col,
12503 BLOCK_SIZE bsize, int plane, struct buf_2d *src) {
12504 const int wide = AOMMIN(mi_size_wide[bsize] * MI_SIZE,
12505 (xd->sb_mi_bd.mi_col_end + 1) * MI_SIZE - pxl_col);
12506 const int high = AOMMIN(mi_size_high[bsize] * MI_SIZE,
12507 (xd->sb_mi_bd.mi_row_end + 1) * MI_SIZE - pxl_row);
12508 const int ss_x = xd->plane[plane].subsampling_x;
12509 const int ss_y = xd->plane[plane].subsampling_y;
12510 int row_offset = (pxl_row - xd->sb_mi_bd.mi_row_begin * MI_SIZE) >> ss_y;
12511 int col_offset = (pxl_col - xd->sb_mi_bd.mi_col_begin * MI_SIZE) >> ss_x;
12512 int dst_stride = xd->ncobmc_pred_buf_stride[plane];
12513 int dst_offset = row_offset * dst_stride + col_offset;
12514 int src_stride = src->stride;
12515
12516 int r, c;
12517 int64_t tmp, error = 0;
12518
12519 for (r = 0; r < (high >> ss_y); ++r) {
12520 for (c = 0; c < (wide >> ss_x); ++c) {
12521 tmp = xd->ncobmc_pred_buf[plane][r * dst_stride + c + dst_offset] -
12522 src->buf[r * src_stride + c];
12523 error += tmp * tmp;
12524 }
12525 }
12526 return error;
12527}
12528
12529int get_ncobmc_mode(const AV1_COMP *const cpi, MACROBLOCK *const x,
12530 MACROBLOCKD *xd, int mi_row, int mi_col, int bsize) {
12531 const AV1_COMMON *const cm = &cpi->common;
12532#if CONFIG_HIGHBITDEPTH
12533 DECLARE_ALIGNED(16, uint8_t, tmp_buf_0[2 * MAX_MB_PLANE * MAX_SB_SQUARE]);
12534 DECLARE_ALIGNED(16, uint8_t, tmp_buf_1[2 * MAX_MB_PLANE * MAX_SB_SQUARE]);
12535 DECLARE_ALIGNED(16, uint8_t, tmp_buf_2[2 * MAX_MB_PLANE * MAX_SB_SQUARE]);
12536 DECLARE_ALIGNED(16, uint8_t, tmp_buf_3[2 * MAX_MB_PLANE * MAX_SB_SQUARE]);
12537#else
12538 DECLARE_ALIGNED(16, uint8_t, tmp_buf_0[MAX_MB_PLANE * MAX_SB_SQUARE]);
12539 DECLARE_ALIGNED(16, uint8_t, tmp_buf_1[MAX_MB_PLANE * MAX_SB_SQUARE]);
12540 DECLARE_ALIGNED(16, uint8_t, tmp_buf_2[MAX_MB_PLANE * MAX_SB_SQUARE]);
12541 DECLARE_ALIGNED(16, uint8_t, tmp_buf_3[MAX_MB_PLANE * MAX_SB_SQUARE]);
12542#endif
12543 uint8_t *pred_buf[4][MAX_MB_PLANE];
12544
12545 // TODO(weitinglin): stride size needs to be fixed for high-bit depth
12546 int pred_stride[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
12547
12548 // target block in pxl
12549 int pxl_row = mi_row << MI_SIZE_LOG2;
12550 int pxl_col = mi_col << MI_SIZE_LOG2;
12551 int64_t error, best_error = INT64_MAX;
12552 int plane, tmp_mode, best_mode = 0;
12553#if CONFIG_HIGHBITDEPTH
12554 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
12555 int len = sizeof(uint16_t);
12556 ASSIGN_ALIGNED_PTRS_HBD(pred_buf[0], tmp_buf_0, MAX_SB_SQUARE, len);
12557 ASSIGN_ALIGNED_PTRS_HBD(pred_buf[1], tmp_buf_0, MAX_SB_SQUARE, len);
12558 ASSIGN_ALIGNED_PTRS_HBD(pred_buf[2], tmp_buf_0, MAX_SB_SQUARE, len);
12559 ASSIGN_ALIGNED_PTRS_HBD(pred_buf[3], tmp_buf_0, MAX_SB_SQUARE, len);
12560 } else {
12561#endif // CONFIG_HIGHBITDEPTH
12562 ASSIGN_ALIGNED_PTRS(pred_buf[0], tmp_buf_0, MAX_SB_SQUARE);
12563 ASSIGN_ALIGNED_PTRS(pred_buf[1], tmp_buf_1, MAX_SB_SQUARE);
12564 ASSIGN_ALIGNED_PTRS(pred_buf[2], tmp_buf_2, MAX_SB_SQUARE);
12565 ASSIGN_ALIGNED_PTRS(pred_buf[3], tmp_buf_3, MAX_SB_SQUARE);
12566#if CONFIG_HIGHBITDEPTH
12567 }
12568#endif
12569
12570 av1_get_ext_blk_preds(cm, xd, bsize, mi_row, mi_col, pred_buf, pred_stride);
12571 av1_get_ori_blk_pred(cm, xd, bsize, mi_row, mi_col, pred_buf[3], pred_stride);
12572
12573 for (tmp_mode = 0; tmp_mode < MAX_NCOBMC_MODES; ++tmp_mode) {
12574 error = 0;
12575 for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
12576 build_ncobmc_intrpl_pred(cm, xd, plane, pxl_row, pxl_col, bsize, pred_buf,
12577 pred_stride, tmp_mode);
12578 error += get_ncobmc_error(xd, pxl_row, pxl_col, bsize, plane,
12579 &x->plane[plane].src);
12580 }
12581 if (error < best_error) {
12582 best_mode = tmp_mode;
12583 best_error = error;
12584 }
12585 }
12586
12587 for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
12588 build_ncobmc_intrpl_pred(cm, xd, plane, pxl_row, pxl_col, bsize, pred_buf,
12589 pred_stride, best_mode);
12590 }
12591
12592 return best_mode;
12593}
12594
12595#endif // CONFIG_NCOBMC_ADAPT_WEIGHT
Yue Chencb60b182016-10-13 15:18:22 -070012596#endif // CONFIG_MOTION_VAR