interp_search.c (35032B)
1 /* 2 * Copyright (c) 2020, Alliance for Open Media. All rights reserved. 3 * 4 * 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. 10 */ 11 12 #include "av1/common/filter.h" 13 #include "av1/common/pred_common.h" 14 #include "av1/encoder/interp_search.h" 15 #include "av1/encoder/model_rd.h" 16 #include "av1/encoder/rdopt_utils.h" 17 #include "av1/encoder/reconinter_enc.h" 18 19 // return mv_diff 20 static inline int is_interp_filter_good_match( 21 const INTERPOLATION_FILTER_STATS *st, MB_MODE_INFO *const mi, 22 int skip_level) { 23 const int is_comp = has_second_ref(mi); 24 int i; 25 26 for (i = 0; i < 1 + is_comp; ++i) { 27 if (st->ref_frames[i] != mi->ref_frame[i]) return INT_MAX; 28 } 29 30 if (skip_level == 1 && is_comp) { 31 if (st->comp_type != mi->interinter_comp.type) return INT_MAX; 32 if (st->compound_idx != mi->compound_idx) return INT_MAX; 33 } 34 35 int mv_diff = 0; 36 for (i = 0; i < 1 + is_comp; ++i) { 37 mv_diff += abs(st->mv[i].as_mv.row - mi->mv[i].as_mv.row) + 38 abs(st->mv[i].as_mv.col - mi->mv[i].as_mv.col); 39 } 40 return mv_diff; 41 } 42 43 static inline int save_interp_filter_search_stat( 44 MB_MODE_INFO *const mbmi, int64_t rd, unsigned int pred_sse, 45 INTERPOLATION_FILTER_STATS *interp_filter_stats, 46 int interp_filter_stats_idx) { 47 if (interp_filter_stats_idx < MAX_INTERP_FILTER_STATS) { 48 INTERPOLATION_FILTER_STATS stat = { mbmi->interp_filters, 49 { mbmi->mv[0], mbmi->mv[1] }, 50 { mbmi->ref_frame[0], 51 mbmi->ref_frame[1] }, 52 mbmi->interinter_comp.type, 53 mbmi->compound_idx, 54 rd, 55 pred_sse }; 56 interp_filter_stats[interp_filter_stats_idx] = stat; 57 interp_filter_stats_idx++; 58 } 59 return interp_filter_stats_idx; 60 } 61 62 static inline int find_interp_filter_in_stats( 63 MB_MODE_INFO *const mbmi, INTERPOLATION_FILTER_STATS *interp_filter_stats, 64 int interp_filter_stats_idx, int skip_level) { 65 // [skip_levels][single or comp] 66 const int thr[2][2] = { { 0, 0 }, { 3, 7 } }; 67 const int is_comp = has_second_ref(mbmi); 68 69 // Find good enough match. 70 // TODO(yunqing): Separate single-ref mode and comp mode stats for fast 71 // search. 72 int best = INT_MAX; 73 int match = -1; 74 for (int j = 0; j < interp_filter_stats_idx; ++j) { 75 const INTERPOLATION_FILTER_STATS *st = &interp_filter_stats[j]; 76 const int mv_diff = is_interp_filter_good_match(st, mbmi, skip_level); 77 // Exact match is found. 78 if (mv_diff == 0) { 79 match = j; 80 break; 81 } else if (mv_diff < best && mv_diff <= thr[skip_level - 1][is_comp]) { 82 best = mv_diff; 83 match = j; 84 } 85 } 86 87 if (match != -1) { 88 mbmi->interp_filters = interp_filter_stats[match].filters; 89 return match; 90 } 91 return -1; // no match result found 92 } 93 94 static int find_interp_filter_match( 95 MB_MODE_INFO *const mbmi, const AV1_COMP *const cpi, 96 const InterpFilter assign_filter, const int need_search, 97 INTERPOLATION_FILTER_STATS *interp_filter_stats, 98 int interp_filter_stats_idx) { 99 int match_found_idx = -1; 100 if (cpi->sf.interp_sf.use_interp_filter && need_search) 101 match_found_idx = find_interp_filter_in_stats( 102 mbmi, interp_filter_stats, interp_filter_stats_idx, 103 cpi->sf.interp_sf.use_interp_filter); 104 105 if (!need_search || match_found_idx == -1) 106 set_default_interp_filters(mbmi, assign_filter); 107 return match_found_idx; 108 } 109 110 static inline int get_switchable_rate(MACROBLOCK *const x, 111 const int_interpfilters filters, 112 const int ctx[2], int dual_filter) { 113 const InterpFilter filter0 = filters.as_filters.y_filter; 114 int inter_filter_cost = 115 x->mode_costs.switchable_interp_costs[ctx[0]][filter0]; 116 if (dual_filter) { 117 const InterpFilter filter1 = filters.as_filters.x_filter; 118 inter_filter_cost += x->mode_costs.switchable_interp_costs[ctx[1]][filter1]; 119 } 120 return SWITCHABLE_INTERP_RATE_FACTOR * inter_filter_cost; 121 } 122 123 // Build inter predictor and calculate model rd 124 // for a given plane. 125 static inline void interp_model_rd_eval( 126 MACROBLOCK *const x, const AV1_COMP *const cpi, BLOCK_SIZE bsize, 127 const BUFFER_SET *const orig_dst, int plane_from, int plane_to, 128 RD_STATS *rd_stats, int is_skip_build_pred) { 129 const AV1_COMMON *cm = &cpi->common; 130 MACROBLOCKD *const xd = &x->e_mbd; 131 RD_STATS tmp_rd_stats; 132 av1_init_rd_stats(&tmp_rd_stats); 133 134 // Skip inter predictor if the predictor is already available. 135 if (!is_skip_build_pred) { 136 const int mi_row = xd->mi_row; 137 const int mi_col = xd->mi_col; 138 av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, orig_dst, bsize, 139 plane_from, plane_to); 140 } 141 142 model_rd_sb_fn[cpi->sf.rt_sf.use_simple_rd_model 143 ? MODELRD_LEGACY 144 : MODELRD_TYPE_INTERP_FILTER]( 145 cpi, bsize, x, xd, plane_from, plane_to, &tmp_rd_stats.rate, 146 &tmp_rd_stats.dist, &tmp_rd_stats.skip_txfm, &tmp_rd_stats.sse, NULL, 147 NULL, NULL); 148 149 av1_merge_rd_stats(rd_stats, &tmp_rd_stats); 150 } 151 152 // calculate the rdcost of given interpolation_filter 153 static inline int64_t interpolation_filter_rd( 154 MACROBLOCK *const x, const AV1_COMP *const cpi, 155 const TileDataEnc *tile_data, BLOCK_SIZE bsize, 156 const BUFFER_SET *const orig_dst, int64_t *const rd, 157 RD_STATS *rd_stats_luma, RD_STATS *rd_stats, int *const switchable_rate, 158 const BUFFER_SET *dst_bufs[2], int filter_idx, const int switchable_ctx[2], 159 const int skip_pred) { 160 const AV1_COMMON *cm = &cpi->common; 161 const InterpSearchFlags *interp_search_flags = &cpi->interp_search_flags; 162 const int num_planes = av1_num_planes(cm); 163 MACROBLOCKD *const xd = &x->e_mbd; 164 MB_MODE_INFO *const mbmi = xd->mi[0]; 165 RD_STATS this_rd_stats_luma, this_rd_stats; 166 167 // Initialize rd_stats structures to default values. 168 av1_init_rd_stats(&this_rd_stats_luma); 169 this_rd_stats = *rd_stats_luma; 170 const int_interpfilters last_best = mbmi->interp_filters; 171 mbmi->interp_filters = filter_sets[filter_idx]; 172 const int tmp_rs = 173 get_switchable_rate(x, mbmi->interp_filters, switchable_ctx, 174 cm->seq_params->enable_dual_filter); 175 176 int64_t min_rd = RDCOST(x->rdmult, tmp_rs, 0); 177 if (min_rd > *rd) { 178 mbmi->interp_filters = last_best; 179 return 0; 180 } 181 182 (void)tile_data; 183 184 assert(skip_pred != 2); 185 assert((rd_stats_luma->rate >= 0) && (rd_stats->rate >= 0)); 186 assert((rd_stats_luma->dist >= 0) && (rd_stats->dist >= 0)); 187 assert((rd_stats_luma->sse >= 0) && (rd_stats->sse >= 0)); 188 assert((rd_stats_luma->skip_txfm == 0) || (rd_stats_luma->skip_txfm == 1)); 189 assert((rd_stats->skip_txfm == 0) || (rd_stats->skip_txfm == 1)); 190 assert((skip_pred >= 0) && 191 (skip_pred <= interp_search_flags->default_interp_skip_flags)); 192 193 // When skip_txfm pred is equal to default_interp_skip_flags, 194 // skip both luma and chroma MC. 195 // For mono-chrome images: 196 // num_planes = 1 and cpi->default_interp_skip_flags = 1, 197 // skip_pred = 1: skip both luma and chroma 198 // skip_pred = 0: Evaluate luma and as num_planes=1, 199 // skip chroma evaluation 200 int tmp_skip_pred = 201 (skip_pred == interp_search_flags->default_interp_skip_flags) 202 ? INTERP_SKIP_LUMA_SKIP_CHROMA 203 : skip_pred; 204 205 switch (tmp_skip_pred) { 206 case INTERP_EVAL_LUMA_EVAL_CHROMA: 207 // skip_pred = 0: Evaluate both luma and chroma. 208 // Luma MC 209 interp_model_rd_eval(x, cpi, bsize, orig_dst, AOM_PLANE_Y, AOM_PLANE_Y, 210 &this_rd_stats_luma, 0); 211 this_rd_stats = this_rd_stats_luma; 212 #if CONFIG_COLLECT_RD_STATS == 3 213 RD_STATS rd_stats_y; 214 av1_pick_recursive_tx_size_type_yrd(cpi, x, &rd_stats_y, bsize, 215 INT64_MAX); 216 PrintPredictionUnitStats(cpi, tile_data, x, &rd_stats_y, bsize); 217 #endif // CONFIG_COLLECT_RD_STATS == 3 218 AOM_FALLTHROUGH_INTENDED; 219 case INTERP_SKIP_LUMA_EVAL_CHROMA: 220 // skip_pred = 1: skip luma evaluation (retain previous best luma stats) 221 // and do chroma evaluation. 222 for (int plane = 1; plane < num_planes; ++plane) { 223 int64_t tmp_rd = 224 RDCOST(x->rdmult, tmp_rs + this_rd_stats.rate, this_rd_stats.dist); 225 if (tmp_rd >= *rd) { 226 mbmi->interp_filters = last_best; 227 return 0; 228 } 229 interp_model_rd_eval(x, cpi, bsize, orig_dst, plane, plane, 230 &this_rd_stats, 0); 231 } 232 break; 233 case INTERP_SKIP_LUMA_SKIP_CHROMA: 234 // both luma and chroma evaluation is skipped 235 this_rd_stats = *rd_stats; 236 break; 237 case INTERP_EVAL_INVALID: 238 default: assert(0); return 0; 239 } 240 int64_t tmp_rd = 241 RDCOST(x->rdmult, tmp_rs + this_rd_stats.rate, this_rd_stats.dist); 242 243 if (tmp_rd < *rd) { 244 *rd = tmp_rd; 245 *switchable_rate = tmp_rs; 246 if (skip_pred != interp_search_flags->default_interp_skip_flags) { 247 if (skip_pred == INTERP_EVAL_LUMA_EVAL_CHROMA) { 248 // Overwrite the data as current filter is the best one 249 *rd_stats_luma = this_rd_stats_luma; 250 *rd_stats = this_rd_stats; 251 // As luma MC data is computed, no need to recompute after the search 252 x->recalc_luma_mc_data = 0; 253 } else if (skip_pred == INTERP_SKIP_LUMA_EVAL_CHROMA) { 254 // As luma MC data is not computed, update of luma data can be skipped 255 *rd_stats = this_rd_stats; 256 // As luma MC data is not recomputed and current filter is the best, 257 // indicate the possibility of recomputing MC data 258 // If current buffer contains valid MC data, toggle to indicate that 259 // luma MC data needs to be recomputed 260 x->recalc_luma_mc_data ^= 1; 261 } 262 swap_dst_buf(xd, dst_bufs, num_planes); 263 } 264 return 1; 265 } 266 mbmi->interp_filters = last_best; 267 return 0; 268 } 269 270 static inline INTERP_PRED_TYPE is_pred_filter_search_allowed( 271 const AV1_COMP *const cpi, MACROBLOCKD *xd, BLOCK_SIZE bsize, 272 int_interpfilters *af, int_interpfilters *lf) { 273 const AV1_COMMON *cm = &cpi->common; 274 const MB_MODE_INFO *const above_mbmi = xd->above_mbmi; 275 const MB_MODE_INFO *const left_mbmi = xd->left_mbmi; 276 const int bsl = mi_size_wide_log2[bsize]; 277 int is_horiz_eq = 0, is_vert_eq = 0; 278 279 if (above_mbmi && is_inter_block(above_mbmi)) 280 *af = above_mbmi->interp_filters; 281 282 if (left_mbmi && is_inter_block(left_mbmi)) *lf = left_mbmi->interp_filters; 283 284 if (af->as_filters.x_filter != INTERP_INVALID) 285 is_horiz_eq = af->as_filters.x_filter == lf->as_filters.x_filter; 286 if (af->as_filters.y_filter != INTERP_INVALID) 287 is_vert_eq = af->as_filters.y_filter == lf->as_filters.y_filter; 288 289 INTERP_PRED_TYPE pred_filter_type = (is_vert_eq << 1) + is_horiz_eq; 290 const int mi_row = xd->mi_row; 291 const int mi_col = xd->mi_col; 292 int pred_filter_enable = 293 cpi->sf.interp_sf.cb_pred_filter_search 294 ? (((mi_row + mi_col) >> bsl) + 295 get_chessboard_index(cm->current_frame.frame_number)) & 296 0x1 297 : 0; 298 pred_filter_enable &= is_horiz_eq || is_vert_eq; 299 // pred_filter_search = 0: pred_filter is disabled 300 // pred_filter_search = 1: pred_filter is enabled and only horz pred matching 301 // pred_filter_search = 2: pred_filter is enabled and only vert pred matching 302 // pred_filter_search = 3: pred_filter is enabled and 303 // both vert, horz pred matching 304 return pred_filter_enable * pred_filter_type; 305 } 306 307 static DUAL_FILTER_TYPE find_best_interp_rd_facade( 308 MACROBLOCK *const x, const AV1_COMP *const cpi, 309 const TileDataEnc *tile_data, BLOCK_SIZE bsize, 310 const BUFFER_SET *const orig_dst, int64_t *const rd, RD_STATS *rd_stats_y, 311 RD_STATS *rd_stats, int *const switchable_rate, 312 const BUFFER_SET *dst_bufs[2], const int switchable_ctx[2], 313 const int skip_pred, uint16_t allow_interp_mask, int is_w4_or_h4) { 314 int tmp_skip_pred = skip_pred; 315 DUAL_FILTER_TYPE best_filt_type = REG_REG; 316 317 // If no filter are set to be evaluated, return from function 318 if (allow_interp_mask == 0x0) return best_filt_type; 319 // For block width or height is 4, skip the pred evaluation of SHARP_SHARP 320 tmp_skip_pred = is_w4_or_h4 321 ? cpi->interp_search_flags.default_interp_skip_flags 322 : skip_pred; 323 324 // Loop over the all filter types and evaluate for only allowed filter types 325 for (int filt_type = SHARP_SHARP; filt_type >= REG_REG; --filt_type) { 326 const int is_filter_allowed = 327 get_interp_filter_allowed_mask(allow_interp_mask, filt_type); 328 if (is_filter_allowed) 329 if (interpolation_filter_rd(x, cpi, tile_data, bsize, orig_dst, rd, 330 rd_stats_y, rd_stats, switchable_rate, 331 dst_bufs, filt_type, switchable_ctx, 332 tmp_skip_pred)) 333 best_filt_type = filt_type; 334 tmp_skip_pred = skip_pred; 335 } 336 return best_filt_type; 337 } 338 339 static inline void pred_dual_interp_filter_rd( 340 MACROBLOCK *const x, const AV1_COMP *const cpi, 341 const TileDataEnc *tile_data, BLOCK_SIZE bsize, 342 const BUFFER_SET *const orig_dst, int64_t *const rd, RD_STATS *rd_stats_y, 343 RD_STATS *rd_stats, int *const switchable_rate, 344 const BUFFER_SET *dst_bufs[2], const int switchable_ctx[2], 345 const int skip_pred, INTERP_PRED_TYPE pred_filt_type, int_interpfilters *af, 346 int_interpfilters *lf) { 347 (void)lf; 348 assert(pred_filt_type > INTERP_HORZ_NEQ_VERT_NEQ); 349 assert(pred_filt_type < INTERP_PRED_TYPE_ALL); 350 uint16_t allowed_interp_mask = 0; 351 352 if (pred_filt_type == INTERP_HORZ_EQ_VERT_NEQ) { 353 // pred_filter_search = 1: Only horizontal filter is matching 354 allowed_interp_mask = 355 av1_interp_dual_filt_mask[pred_filt_type - 1][af->as_filters.x_filter]; 356 } else if (pred_filt_type == INTERP_HORZ_NEQ_VERT_EQ) { 357 // pred_filter_search = 2: Only vertical filter is matching 358 allowed_interp_mask = 359 av1_interp_dual_filt_mask[pred_filt_type - 1][af->as_filters.y_filter]; 360 } else { 361 // pred_filter_search = 3: Both horizontal and vertical filter are matching 362 int filt_type = 363 af->as_filters.x_filter + af->as_filters.y_filter * SWITCHABLE_FILTERS; 364 set_interp_filter_allowed_mask(&allowed_interp_mask, filt_type); 365 } 366 // REG_REG is already been evaluated in the beginning 367 reset_interp_filter_allowed_mask(&allowed_interp_mask, REG_REG); 368 find_best_interp_rd_facade(x, cpi, tile_data, bsize, orig_dst, rd, rd_stats_y, 369 rd_stats, switchable_rate, dst_bufs, 370 switchable_ctx, skip_pred, allowed_interp_mask, 0); 371 } 372 // Evaluate dual filter type 373 // a) Using above, left block interp filter 374 // b) Find the best horizontal filter and 375 // then evaluate corresponding vertical filters. 376 static inline void fast_dual_interp_filter_rd( 377 MACROBLOCK *const x, const AV1_COMP *const cpi, 378 const TileDataEnc *tile_data, BLOCK_SIZE bsize, 379 const BUFFER_SET *const orig_dst, int64_t *const rd, RD_STATS *rd_stats_y, 380 RD_STATS *rd_stats, int *const switchable_rate, 381 const BUFFER_SET *dst_bufs[2], const int switchable_ctx[2], 382 const int skip_hor, const int skip_ver) { 383 const InterpSearchFlags *interp_search_flags = &cpi->interp_search_flags; 384 MACROBLOCKD *const xd = &x->e_mbd; 385 MB_MODE_INFO *const mbmi = xd->mi[0]; 386 INTERP_PRED_TYPE pred_filter_type = INTERP_HORZ_NEQ_VERT_NEQ; 387 int_interpfilters af = av1_broadcast_interp_filter(INTERP_INVALID); 388 int_interpfilters lf = af; 389 390 if (!have_newmv_in_inter_mode(mbmi->mode)) { 391 pred_filter_type = is_pred_filter_search_allowed(cpi, xd, bsize, &af, &lf); 392 } 393 394 if (pred_filter_type) { 395 pred_dual_interp_filter_rd(x, cpi, tile_data, bsize, orig_dst, rd, 396 rd_stats_y, rd_stats, switchable_rate, dst_bufs, 397 switchable_ctx, (skip_hor & skip_ver), 398 pred_filter_type, &af, &lf); 399 } else { 400 const int bw = block_size_wide[bsize]; 401 const int bh = block_size_high[bsize]; 402 int best_dual_mode = 0; 403 int skip_pred = 404 bw <= 4 ? interp_search_flags->default_interp_skip_flags : skip_hor; 405 // TODO(any): Make use of find_best_interp_rd_facade() 406 // if speed impact is negligible 407 for (int i = (SWITCHABLE_FILTERS - 1); i >= 1; --i) { 408 if (interpolation_filter_rd(x, cpi, tile_data, bsize, orig_dst, rd, 409 rd_stats_y, rd_stats, switchable_rate, 410 dst_bufs, i, switchable_ctx, skip_pred)) { 411 best_dual_mode = i; 412 } 413 skip_pred = skip_hor; 414 } 415 // From best of horizontal EIGHTTAP_REGULAR modes, check vertical modes 416 skip_pred = 417 bh <= 4 ? interp_search_flags->default_interp_skip_flags : skip_ver; 418 for (int i = (best_dual_mode + (SWITCHABLE_FILTERS * 2)); 419 i >= (best_dual_mode + SWITCHABLE_FILTERS); i -= SWITCHABLE_FILTERS) { 420 interpolation_filter_rd(x, cpi, tile_data, bsize, orig_dst, rd, 421 rd_stats_y, rd_stats, switchable_rate, dst_bufs, 422 i, switchable_ctx, skip_pred); 423 skip_pred = skip_ver; 424 } 425 } 426 } 427 428 // Find the best interp filter if dual_interp_filter = 0 429 static inline void find_best_non_dual_interp_filter( 430 MACROBLOCK *const x, const AV1_COMP *const cpi, 431 const TileDataEnc *tile_data, BLOCK_SIZE bsize, 432 const BUFFER_SET *const orig_dst, int64_t *const rd, RD_STATS *rd_stats_y, 433 RD_STATS *rd_stats, int *const switchable_rate, 434 const BUFFER_SET *dst_bufs[2], const int switchable_ctx[2], 435 const int skip_ver, const int skip_hor) { 436 const InterpSearchFlags *interp_search_flags = &cpi->interp_search_flags; 437 int8_t i; 438 MACROBLOCKD *const xd = &x->e_mbd; 439 MB_MODE_INFO *const mbmi = xd->mi[0]; 440 441 uint16_t interp_filter_search_mask = 442 interp_search_flags->interp_filter_search_mask; 443 444 if (cpi->sf.interp_sf.adaptive_interp_filter_search == 2) { 445 const FRAME_UPDATE_TYPE update_type = 446 get_frame_update_type(&cpi->ppi->gf_group, cpi->gf_frame_index); 447 const int ctx0 = av1_get_pred_context_switchable_interp(xd, 0); 448 const int ctx1 = av1_get_pred_context_switchable_interp(xd, 1); 449 int use_actual_frame_probs = 1; 450 const int *switchable_interp_p0; 451 const int *switchable_interp_p1; 452 #if CONFIG_FPMT_TEST 453 use_actual_frame_probs = 454 (cpi->ppi->fpmt_unit_test_cfg == PARALLEL_SIMULATION_ENCODE) ? 0 : 1; 455 if (!use_actual_frame_probs) { 456 switchable_interp_p0 = (int *)cpi->ppi->temp_frame_probs 457 .switchable_interp_probs[update_type][ctx0]; 458 switchable_interp_p1 = (int *)cpi->ppi->temp_frame_probs 459 .switchable_interp_probs[update_type][ctx1]; 460 } 461 #endif 462 if (use_actual_frame_probs) { 463 switchable_interp_p0 = 464 cpi->ppi->frame_probs.switchable_interp_probs[update_type][ctx0]; 465 switchable_interp_p1 = 466 cpi->ppi->frame_probs.switchable_interp_probs[update_type][ctx1]; 467 } 468 static const int thr[7] = { 0, 8, 8, 8, 8, 0, 8 }; 469 const int thresh = thr[update_type]; 470 for (i = 0; i < SWITCHABLE_FILTERS; i++) { 471 // For non-dual case, the 2 dir's prob should be identical. 472 assert(switchable_interp_p0[i] == switchable_interp_p1[i]); 473 if (switchable_interp_p0[i] < thresh && 474 switchable_interp_p1[i] < thresh) { 475 DUAL_FILTER_TYPE filt_type = i + SWITCHABLE_FILTERS * i; 476 reset_interp_filter_allowed_mask(&interp_filter_search_mask, filt_type); 477 } 478 479 if (cpi->oxcf.algo_cfg.sharpness == 3 && i == EIGHTTAP_SMOOTH) { 480 DUAL_FILTER_TYPE filt_type = i + SWITCHABLE_FILTERS * i; 481 reset_interp_filter_allowed_mask(&interp_filter_search_mask, filt_type); 482 } 483 } 484 } 485 486 // Regular filter evaluation should have been done and hence the same should 487 // be the winner 488 assert(x->e_mbd.mi[0]->interp_filters.as_int == filter_sets[0].as_int); 489 if ((skip_hor & skip_ver) != interp_search_flags->default_interp_skip_flags) { 490 INTERP_PRED_TYPE pred_filter_type = INTERP_HORZ_NEQ_VERT_NEQ; 491 int_interpfilters af = av1_broadcast_interp_filter(INTERP_INVALID); 492 int_interpfilters lf = af; 493 494 pred_filter_type = is_pred_filter_search_allowed(cpi, xd, bsize, &af, &lf); 495 if (pred_filter_type) { 496 assert(af.as_filters.x_filter != INTERP_INVALID); 497 int filter_idx = SWITCHABLE * af.as_filters.x_filter; 498 // This assert tells that (filter_x == filter_y) for non-dual filter case 499 assert(filter_sets[filter_idx].as_filters.x_filter == 500 filter_sets[filter_idx].as_filters.y_filter); 501 if (cpi->sf.interp_sf.adaptive_interp_filter_search && 502 !(get_interp_filter_allowed_mask(interp_filter_search_mask, 503 filter_idx))) { 504 return; 505 } 506 if (filter_idx) { 507 interpolation_filter_rd(x, cpi, tile_data, bsize, orig_dst, rd, 508 rd_stats_y, rd_stats, switchable_rate, dst_bufs, 509 filter_idx, switchable_ctx, 510 (skip_hor & skip_ver)); 511 } 512 return; 513 } 514 } 515 // Reuse regular filter's modeled rd data for sharp filter for following 516 // cases 517 // 1) When bsize is 4x4 518 // 2) When block width is 4 (i.e. 4x8/4x16 blocks) and MV in vertical 519 // direction is full-pel 520 // 3) When block height is 4 (i.e. 8x4/16x4 blocks) and MV in horizontal 521 // direction is full-pel 522 // TODO(any): Optimize cases 2 and 3 further if luma MV in relavant direction 523 // alone is full-pel 524 525 if ((bsize == BLOCK_4X4) || 526 (block_size_wide[bsize] == 4 && 527 skip_ver == interp_search_flags->default_interp_skip_flags) || 528 (block_size_high[bsize] == 4 && 529 skip_hor == interp_search_flags->default_interp_skip_flags)) { 530 int skip_pred = skip_hor & skip_ver; 531 uint16_t allowed_interp_mask = 0; 532 533 // REG_REG filter type is evaluated beforehand, hence skip it 534 set_interp_filter_allowed_mask(&allowed_interp_mask, SHARP_SHARP); 535 set_interp_filter_allowed_mask(&allowed_interp_mask, SMOOTH_SMOOTH); 536 if (cpi->sf.interp_sf.adaptive_interp_filter_search) 537 allowed_interp_mask &= interp_filter_search_mask; 538 539 find_best_interp_rd_facade(x, cpi, tile_data, bsize, orig_dst, rd, 540 rd_stats_y, rd_stats, switchable_rate, dst_bufs, 541 switchable_ctx, skip_pred, allowed_interp_mask, 542 1); 543 } else { 544 int skip_pred = (skip_hor & skip_ver); 545 for (i = (SWITCHABLE_FILTERS + 1); i < DUAL_FILTER_SET_SIZE; 546 i += (SWITCHABLE_FILTERS + 1)) { 547 // This assert tells that (filter_x == filter_y) for non-dual filter case 548 assert(filter_sets[i].as_filters.x_filter == 549 filter_sets[i].as_filters.y_filter); 550 if (cpi->sf.interp_sf.adaptive_interp_filter_search && 551 !(get_interp_filter_allowed_mask(interp_filter_search_mask, i))) { 552 continue; 553 } 554 interpolation_filter_rd(x, cpi, tile_data, bsize, orig_dst, rd, 555 rd_stats_y, rd_stats, switchable_rate, dst_bufs, 556 i, switchable_ctx, skip_pred); 557 // In first iteration, smooth filter is evaluated. If smooth filter 558 // (which is less sharper) is the winner among regular and smooth filters, 559 // sharp filter evaluation is skipped 560 // TODO(any): Refine this gating based on modelled rd only (i.e., by not 561 // accounting switchable filter rate) 562 if (cpi->sf.interp_sf.skip_sharp_interp_filter_search && 563 skip_pred != interp_search_flags->default_interp_skip_flags) { 564 if (mbmi->interp_filters.as_int == filter_sets[SMOOTH_SMOOTH].as_int) 565 break; 566 } 567 } 568 } 569 } 570 571 static inline void calc_interp_skip_pred_flag(MACROBLOCK *const x, 572 const AV1_COMP *const cpi, 573 int *skip_hor, int *skip_ver) { 574 const AV1_COMMON *cm = &cpi->common; 575 MACROBLOCKD *const xd = &x->e_mbd; 576 MB_MODE_INFO *const mbmi = xd->mi[0]; 577 const int num_planes = av1_num_planes(cm); 578 const int is_compound = has_second_ref(mbmi); 579 assert(is_intrabc_block(mbmi) == 0); 580 for (int ref = 0; ref < 1 + is_compound; ++ref) { 581 const struct scale_factors *const sf = 582 get_ref_scale_factors_const(cm, mbmi->ref_frame[ref]); 583 // TODO(any): Refine skip flag calculation considering scaling 584 if (av1_is_scaled(sf)) { 585 *skip_hor = 0; 586 *skip_ver = 0; 587 break; 588 } 589 const MV mv = mbmi->mv[ref].as_mv; 590 int skip_hor_plane = 0; 591 int skip_ver_plane = 0; 592 for (int plane_idx = 0; plane_idx < AOMMAX(1, (num_planes - 1)); 593 ++plane_idx) { 594 struct macroblockd_plane *const pd = &xd->plane[plane_idx]; 595 const int bw = pd->width; 596 const int bh = pd->height; 597 const MV mv_q4 = clamp_mv_to_umv_border_sb( 598 xd, &mv, bw, bh, pd->subsampling_x, pd->subsampling_y); 599 const int sub_x = (mv_q4.col & SUBPEL_MASK) << SCALE_EXTRA_BITS; 600 const int sub_y = (mv_q4.row & SUBPEL_MASK) << SCALE_EXTRA_BITS; 601 skip_hor_plane |= ((sub_x == 0) << plane_idx); 602 skip_ver_plane |= ((sub_y == 0) << plane_idx); 603 } 604 *skip_hor &= skip_hor_plane; 605 *skip_ver &= skip_ver_plane; 606 // It is not valid that "luma MV is sub-pel, whereas chroma MV is not" 607 assert(*skip_hor != 2); 608 assert(*skip_ver != 2); 609 } 610 // When compond prediction type is compound segment wedge, luma MC and chroma 611 // MC need to go hand in hand as mask generated during luma MC is reuired for 612 // chroma MC. If skip_hor = 0 and skip_ver = 1, mask used for chroma MC during 613 // vertical filter decision may be incorrect as temporary MC evaluation 614 // overwrites the mask. Make skip_ver as 0 for this case so that mask is 615 // populated during luma MC 616 if (is_compound && mbmi->compound_idx == 1 && 617 mbmi->interinter_comp.type == COMPOUND_DIFFWTD) { 618 assert(mbmi->comp_group_idx == 1); 619 if (*skip_hor == 0 && *skip_ver == 1) *skip_ver = 0; 620 } 621 } 622 623 /*!\brief AV1 interpolation filter search 624 * 625 * \ingroup inter_mode_search 626 * 627 * \param[in] cpi Top-level encoder structure. 628 * \param[in] tile_data Pointer to struct holding adaptive 629 * data/contexts/models for the tile during 630 * encoding. 631 * \param[in] x Pointer to struc holding all the data for 632 * the current macroblock. 633 * \param[in] bsize Current block size. 634 * \param[in] tmp_dst A temporary prediction buffer to hold a 635 * computed prediction. 636 * \param[in,out] orig_dst A prediction buffer to hold a computed 637 * prediction. This will eventually hold the 638 * final prediction, and the tmp_dst info will 639 * be copied here. 640 * \param[in,out] rd The RD cost associated with the selected 641 * interpolation filter parameters. 642 * \param[in,out] switchable_rate The rate associated with using a SWITCHABLE 643 * filter mode. 644 * \param[in,out] skip_build_pred Indicates whether or not to build the inter 645 * predictor. If this is 0, the inter predictor 646 * has already been built and thus we can avoid 647 * repeating computation. 648 * \param[in] args HandleInterModeArgs struct holding 649 * miscellaneous arguments for inter mode 650 * search. See the documentation for this 651 * struct for a description of each member. 652 * \param[in] ref_best_rd Best RD found so far for this block. 653 * It is used for early termination of this 654 * search if the RD exceeds this value. 655 * 656 * \return Returns INT64_MAX if the filter parameters are invalid and the 657 * current motion mode being tested should be skipped. It returns 0 if the 658 * parameter search is a success. 659 */ 660 int64_t av1_interpolation_filter_search( 661 MACROBLOCK *const x, const AV1_COMP *const cpi, 662 const TileDataEnc *tile_data, BLOCK_SIZE bsize, 663 const BUFFER_SET *const tmp_dst, const BUFFER_SET *const orig_dst, 664 int64_t *const rd, int *const switchable_rate, int *skip_build_pred, 665 HandleInterModeArgs *args, int64_t ref_best_rd) { 666 const AV1_COMMON *cm = &cpi->common; 667 const InterpSearchFlags *interp_search_flags = &cpi->interp_search_flags; 668 const int num_planes = av1_num_planes(cm); 669 MACROBLOCKD *const xd = &x->e_mbd; 670 MB_MODE_INFO *const mbmi = xd->mi[0]; 671 const int need_search = av1_is_interp_needed(xd); 672 const int ref_frame = xd->mi[0]->ref_frame[0]; 673 RD_STATS rd_stats_luma, rd_stats; 674 675 // Initialization of rd_stats structures with default values 676 av1_init_rd_stats(&rd_stats_luma); 677 av1_init_rd_stats(&rd_stats); 678 679 int match_found_idx = -1; 680 const InterpFilter assign_filter = cm->features.interp_filter; 681 682 match_found_idx = find_interp_filter_match( 683 mbmi, cpi, assign_filter, need_search, args->interp_filter_stats, 684 args->interp_filter_stats_idx); 685 686 if (match_found_idx != -1) { 687 *rd = args->interp_filter_stats[match_found_idx].rd; 688 x->pred_sse[ref_frame] = 689 args->interp_filter_stats[match_found_idx].pred_sse; 690 *skip_build_pred = 0; 691 return 0; 692 } 693 694 int switchable_ctx[2]; 695 switchable_ctx[0] = av1_get_pred_context_switchable_interp(xd, 0); 696 switchable_ctx[1] = av1_get_pred_context_switchable_interp(xd, 1); 697 *switchable_rate = 698 get_switchable_rate(x, mbmi->interp_filters, switchable_ctx, 699 cm->seq_params->enable_dual_filter); 700 701 // Do MC evaluation for default filter_type. 702 // Luma MC 703 interp_model_rd_eval(x, cpi, bsize, orig_dst, AOM_PLANE_Y, AOM_PLANE_Y, 704 &rd_stats_luma, *skip_build_pred); 705 706 #if CONFIG_COLLECT_RD_STATS == 3 707 RD_STATS rd_stats_y; 708 av1_pick_recursive_tx_size_type_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX); 709 PrintPredictionUnitStats(cpi, tile_data, x, &rd_stats_y, bsize); 710 #endif // CONFIG_COLLECT_RD_STATS == 3 711 // Chroma MC 712 if (num_planes > 1) { 713 interp_model_rd_eval(x, cpi, bsize, orig_dst, AOM_PLANE_U, AOM_PLANE_V, 714 &rd_stats, *skip_build_pred); 715 } 716 *skip_build_pred = 1; 717 718 av1_merge_rd_stats(&rd_stats, &rd_stats_luma); 719 720 assert(rd_stats.rate >= 0); 721 722 *rd = RDCOST(x->rdmult, *switchable_rate + rd_stats.rate, rd_stats.dist); 723 x->pred_sse[ref_frame] = (unsigned int)(rd_stats_luma.sse >> 4); 724 725 if (assign_filter != SWITCHABLE || match_found_idx != -1) { 726 return 0; 727 } 728 if (!need_search) { 729 int_interpfilters filters = av1_broadcast_interp_filter(EIGHTTAP_REGULAR); 730 assert(mbmi->interp_filters.as_int == filters.as_int); 731 (void)filters; 732 return 0; 733 } 734 if (args->modelled_rd != NULL) { 735 if (has_second_ref(mbmi)) { 736 const int ref_mv_idx = mbmi->ref_mv_idx; 737 MV_REFERENCE_FRAME *refs = mbmi->ref_frame; 738 const int mode0 = compound_ref0_mode(mbmi->mode); 739 const int mode1 = compound_ref1_mode(mbmi->mode); 740 const int64_t mrd = AOMMIN(args->modelled_rd[mode0][ref_mv_idx][refs[0]], 741 args->modelled_rd[mode1][ref_mv_idx][refs[1]]); 742 if ((*rd >> 1) > mrd && ref_best_rd < INT64_MAX) { 743 return INT64_MAX; 744 } 745 } 746 } 747 748 x->recalc_luma_mc_data = 0; 749 // skip_flag=xx (in binary form) 750 // Setting 0th flag corresonds to skipping luma MC and setting 1st bt 751 // corresponds to skipping chroma MC skip_flag=0 corresponds to "Don't skip 752 // luma and chroma MC" Skip flag=1 corresponds to "Skip Luma MC only" 753 // Skip_flag=2 is not a valid case 754 // skip_flag=3 corresponds to "Skip both luma and chroma MC" 755 int skip_hor = interp_search_flags->default_interp_skip_flags; 756 int skip_ver = interp_search_flags->default_interp_skip_flags; 757 calc_interp_skip_pred_flag(x, cpi, &skip_hor, &skip_ver); 758 759 // do interp_filter search 760 restore_dst_buf(xd, *tmp_dst, num_planes); 761 const BUFFER_SET *dst_bufs[2] = { tmp_dst, orig_dst }; 762 // Evaluate dual interp filters 763 if (cm->seq_params->enable_dual_filter) { 764 if (cpi->sf.interp_sf.use_fast_interpolation_filter_search) { 765 fast_dual_interp_filter_rd(x, cpi, tile_data, bsize, orig_dst, rd, 766 &rd_stats_luma, &rd_stats, switchable_rate, 767 dst_bufs, switchable_ctx, skip_hor, skip_ver); 768 } else { 769 // Use full interpolation filter search 770 uint16_t allowed_interp_mask = ALLOW_ALL_INTERP_FILT_MASK; 771 // REG_REG filter type is evaluated beforehand, so loop is repeated over 772 // REG_SMOOTH to SHARP_SHARP for full interpolation filter search 773 reset_interp_filter_allowed_mask(&allowed_interp_mask, REG_REG); 774 find_best_interp_rd_facade(x, cpi, tile_data, bsize, orig_dst, rd, 775 &rd_stats_luma, &rd_stats, switchable_rate, 776 dst_bufs, switchable_ctx, 777 (skip_hor & skip_ver), allowed_interp_mask, 0); 778 } 779 } else { 780 // Evaluate non-dual interp filters 781 find_best_non_dual_interp_filter( 782 x, cpi, tile_data, bsize, orig_dst, rd, &rd_stats_luma, &rd_stats, 783 switchable_rate, dst_bufs, switchable_ctx, skip_ver, skip_hor); 784 } 785 swap_dst_buf(xd, dst_bufs, num_planes); 786 // Recompute final MC data if required 787 if (x->recalc_luma_mc_data == 1) { 788 // Recomputing final luma MC data is required only if the same was skipped 789 // in either of the directions Condition below is necessary, but not 790 // sufficient 791 assert((skip_hor == 1) || (skip_ver == 1)); 792 const int mi_row = xd->mi_row; 793 const int mi_col = xd->mi_col; 794 av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, orig_dst, bsize, 795 AOM_PLANE_Y, AOM_PLANE_Y); 796 } 797 x->pred_sse[ref_frame] = (unsigned int)(rd_stats_luma.sse >> 4); 798 799 // save search results 800 if (cpi->sf.interp_sf.use_interp_filter) { 801 assert(match_found_idx == -1); 802 args->interp_filter_stats_idx = save_interp_filter_search_stat( 803 mbmi, *rd, x->pred_sse[ref_frame], args->interp_filter_stats, 804 args->interp_filter_stats_idx); 805 } 806 return 0; 807 }