/* * Copyright (c) 2016, Alliance for Open Media. All rights reserved. * * This source code is subject to the terms of the BSD 2 Clause License and * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License * was not distributed with this source code in the LICENSE file, you can * obtain it at www.aomedia.org/license/software. If the Alliance for Open * Media Patent License 1.0 was not distributed with this source code in the * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
typedefstruct InterModeSearchState {
int64_t best_rd;
int64_t best_skip_rd[2];
MB_MODE_INFO best_mbmode; int best_rate_y; int best_rate_uv; int best_mode_skippable; int best_skip2;
THR_MODES best_mode_index; int num_available_refs;
int64_t dist_refs[REF_FRAMES]; int dist_order_refs[REF_FRAMES];
int64_t mode_threshold[MAX_MODES];
int64_t best_intra_rd; unsignedint best_pred_sse;
/*! * \brief Keep track of best intra rd for use in compound mode.
*/
int64_t best_pred_rd[REFERENCE_MODES]; // Save a set of single_newmv for each checked ref_mv.
int_mv single_newmv[MAX_REF_MV_SEARCH][REF_FRAMES]; int single_newmv_rate[MAX_REF_MV_SEARCH][REF_FRAMES]; int single_newmv_valid[MAX_REF_MV_SEARCH][REF_FRAMES];
int64_t modelled_rd[MB_MODE_COUNT][MAX_REF_MV_SEARCH][REF_FRAMES]; // The rd of simple translation in single inter modes
int64_t simple_rd[MB_MODE_COUNT][MAX_REF_MV_SEARCH][REF_FRAMES];
int64_t best_single_rd[REF_FRAMES];
PREDICTION_MODE best_single_mode[REF_FRAMES];
// Single search results by [directions][modes][reference frames]
SingleInterModeState single_state[2][SINGLE_INTER_MODE_NUM][FWD_REFS]; int single_state_cnt[2][SINGLE_INTER_MODE_NUM];
SingleInterModeState single_state_modelled[2][SINGLE_INTER_MODE_NUM]
[FWD_REFS]; int single_state_modelled_cnt[2][SINGLE_INTER_MODE_NUM];
MV_REFERENCE_FRAME single_rd_order[2][SINGLE_INTER_MODE_NUM][FWD_REFS];
IntraModeSearchState intra_search_state;
RD_STATS best_y_rdcost;
} InterModeSearchState; /*!\endcond */
staticint compare_rd_idx_pair(constvoid *a, constvoid *b) { if (((RdIdxPair *)a)->rd == ((RdIdxPair *)b)->rd) { // To avoid inconsistency in qsort() ordering when two elements are equal, // using idx as tie breaker. Refer aomedia:2928 if (((RdIdxPair *)a)->idx == ((RdIdxPair *)b)->idx) return 0; elseif (((RdIdxPair *)a)->idx > ((RdIdxPair *)b)->idx) return 1; else return -1;
} elseif (((const RdIdxPair *)a)->rd > ((const RdIdxPair *)b)->rd) { return 1;
} else { return -1;
}
}
staticinlinevoid inter_modes_info_sort(const InterModesInfo *inter_modes_info,
RdIdxPair *rd_idx_pair_arr) { if (inter_modes_info->num == 0) { return;
} for (int i = 0; i < inter_modes_info->num; ++i) {
rd_idx_pair_arr[i].idx = i;
rd_idx_pair_arr[i].rd = inter_modes_info->est_rd_arr[i];
}
qsort(rd_idx_pair_arr, inter_modes_info->num, sizeof(rd_idx_pair_arr[0]),
compare_rd_idx_pair);
}
// Similar to get_horver_correlation, but also takes into account first // row/column, when computing horizontal/vertical correlation. void av1_get_horver_correlation_full_c(const int16_t *diff, int stride, int width, int height, float *hcorr, float *vcorr) { // The following notation is used: // x - current pixel // y - left neighbor pixel // z - top neighbor pixel
int64_t x_sum = 0, x2_sum = 0, xy_sum = 0, xz_sum = 0;
int64_t x_firstrow = 0, x_finalrow = 0, x_firstcol = 0, x_finalcol = 0;
int64_t x2_firstrow = 0, x2_finalrow = 0, x2_firstcol = 0, x2_finalcol = 0;
// First, process horizontal correlation on just the first row
x_sum += diff[0];
x2_sum += diff[0] * diff[0];
x_firstrow += diff[0];
x2_firstrow += diff[0] * diff[0]; for (int j = 1; j < width; ++j) { const int16_t x = diff[j]; const int16_t y = diff[j - 1];
x_sum += x;
x_firstrow += x;
x2_sum += x * x;
x2_firstrow += x * x;
xy_sum += x * y;
}
// Process vertical correlation in the first column
x_firstcol += diff[0];
x2_firstcol += diff[0] * diff[0]; for (int i = 1; i < height; ++i) { const int16_t x = diff[i * stride]; const int16_t z = diff[(i - 1) * stride];
x_sum += x;
x_firstcol += x;
x2_sum += x * x;
x2_firstcol += x * x;
xz_sum += x * z;
}
// Now process horiz and vert correlation through the rest unit for (int i = 1; i < height; ++i) { for (int j = 1; j < width; ++j) { const int16_t x = diff[i * stride + j]; const int16_t y = diff[i * stride + j - 1]; const int16_t z = diff[(i - 1) * stride + j];
x_sum += x;
x2_sum += x * x;
xy_sum += x * y;
xz_sum += x * z;
}
}
// Determine cost of a single ref frame, where frame types are represented // by a tree: // Level 0: add cost whether this ref is a forward or backward ref
ref_costs_single[LAST_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][0];
ref_costs_single[LAST2_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][0];
ref_costs_single[LAST3_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][0];
ref_costs_single[GOLDEN_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][0];
ref_costs_single[BWDREF_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][1];
ref_costs_single[ALTREF2_FRAME] +=
mode_costs->single_ref_cost[ctx_p1][0][1];
ref_costs_single[ALTREF_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][1];
// Level 1: if this ref is forward ref, // add cost whether it is last/last2 or last3/golden
ref_costs_single[LAST_FRAME] += mode_costs->single_ref_cost[ctx_p3][2][0];
ref_costs_single[LAST2_FRAME] += mode_costs->single_ref_cost[ctx_p3][2][0];
ref_costs_single[LAST3_FRAME] += mode_costs->single_ref_cost[ctx_p3][2][1];
ref_costs_single[GOLDEN_FRAME] += mode_costs->single_ref_cost[ctx_p3][2][1];
// Level 1: if this ref is backward ref // then add cost whether this ref is altref or backward ref
ref_costs_single[BWDREF_FRAME] += mode_costs->single_ref_cost[ctx_p2][1][0];
ref_costs_single[ALTREF2_FRAME] +=
mode_costs->single_ref_cost[ctx_p2][1][0];
ref_costs_single[ALTREF_FRAME] += mode_costs->single_ref_cost[ctx_p2][1][1];
// Level 2: further add cost whether this ref is last or last2
ref_costs_single[LAST_FRAME] += mode_costs->single_ref_cost[ctx_p4][3][0];
ref_costs_single[LAST2_FRAME] += mode_costs->single_ref_cost[ctx_p4][3][1];
// Level 2: last3 or golden
ref_costs_single[LAST3_FRAME] += mode_costs->single_ref_cost[ctx_p5][4][0];
ref_costs_single[GOLDEN_FRAME] += mode_costs->single_ref_cost[ctx_p5][4][1];
// cost: if one ref frame is forward ref, the other ref is backward ref int ref0, ref1; for (ref0 = LAST_FRAME; ref0 <= GOLDEN_FRAME; ++ref0) { for (ref1 = BWDREF_FRAME; ref1 <= ALTREF_FRAME; ++ref1) {
ref_costs_comp[ref0][ref1] =
ref_bicomp_costs[ref0] + ref_bicomp_costs[ref1];
}
}
// Take a snapshot of the coding context so it can be // restored if we decide to encode this way
ctx->rd_stats.skip_txfm = x->txfm_search_info.skip_txfm;
ctx->skippable = skippable; #if CONFIG_INTERNAL_STATS
ctx->best_mode_index = mode_index; #endif// CONFIG_INTERNAL_STATS
ctx->mic = *xd->mi[0];
av1_copy_mbmi_ext_to_mbmi_ext_frame(&ctx->mbmi_ext_best, &x->mbmi_ext,
av1_ref_frame_type(xd->mi[0]->ref_frame));
}
if (scaled_ref_frame) { // Setup pred block based on scaled reference, because av1_mv_pred() doesn't // support scaling.
av1_setup_pred_block(xd, yv12_mb[ref_frame], scaled_ref_frame, NULL, NULL,
num_planes);
} else {
av1_setup_pred_block(xd, yv12_mb[ref_frame], yv12, sf, sf, num_planes);
}
// Gets an initial list of candidate vectors from neighbours and orders them
av1_find_mv_refs(cm, xd, mbmi, ref_frame, mbmi_ext->ref_mv_count,
xd->ref_mv_stack, xd->weight, NULL, mbmi_ext->global_mvs,
mbmi_ext->mode_context); // TODO(Ravi): Populate mbmi_ext->ref_mv_stack[ref_frame][4] and // mbmi_ext->weight[ref_frame][4] inside av1_find_mv_refs.
av1_copy_usable_ref_mv_stack_and_weight(xd, mbmi_ext, ref_frame); // Further refinement that is encode side only to test the top few candidates // in full and choose the best as the center point for subsequent searches. // The current implementation doesn't support scaling.
av1_mv_pred(cpi, x, yv12_mb[ref_frame][0].buf, yv12_mb[ref_frame][0].stride,
ref_frame, block_size);
// Go back to unscaled reference. if (scaled_ref_frame) { // We had temporarily setup pred block based on scaled reference above. Go // back to unscaled reference now, for subsequent use.
av1_setup_pred_block(xd, yv12_mb[ref_frame], yv12, sf, sf, num_planes);
}
}
// TODO(jingning): this mv clamping function should be block size dependent. staticinlinevoid clamp_mv2(MV *mv, const MACROBLOCKD *xd) { const SubpelMvLimits mv_limits = { xd->mb_to_left_edge - LEFT_TOP_MARGIN,
xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
xd->mb_to_top_edge - LEFT_TOP_MARGIN,
xd->mb_to_bottom_edge +
RIGHT_BOTTOM_MARGIN };
clamp_mv(mv, &mv_limits);
}
/* If the current mode shares the same mv with other modes with higher cost,
* skip this mode. */ staticint skip_repeated_mv(const AV1_COMMON *const cm, const MACROBLOCK *const x,
PREDICTION_MODE this_mode, const MV_REFERENCE_FRAME ref_frames[2],
InterModeSearchState *search_state) { constint is_comp_pred = ref_frames[1] > INTRA_FRAME; const uint8_t ref_frame_type = av1_ref_frame_type(ref_frames); const MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext; constint ref_mv_count = mbmi_ext->ref_mv_count[ref_frame_type];
PREDICTION_MODE compare_mode = MB_MODE_COUNT; if (!is_comp_pred) { if (this_mode == NEARMV) { if (ref_mv_count == 0) { // NEARMV has the same motion vector as NEARESTMV
compare_mode = NEARESTMV;
} if (ref_mv_count == 1 &&
cm->global_motion[ref_frames[0]].wmtype <= TRANSLATION) { // NEARMV has the same motion vector as GLOBALMV
compare_mode = GLOBALMV;
}
} if (this_mode == GLOBALMV) { if (ref_mv_count == 0 &&
cm->global_motion[ref_frames[0]].wmtype <= TRANSLATION) { // GLOBALMV has the same motion vector as NEARESTMV
compare_mode = NEARESTMV;
} if (ref_mv_count == 1) { // GLOBALMV has the same motion vector as NEARMV
compare_mode = NEARMV;
}
}
if (compare_mode != MB_MODE_COUNT) { // Use modelled_rd to check whether compare mode was searched if (search_state->modelled_rd[compare_mode][0][ref_frames[0]] !=
INT64_MAX) { const int16_t mode_ctx =
av1_mode_context_analyzer(mbmi_ext->mode_context, ref_frames); constint compare_cost =
cost_mv_ref(&x->mode_costs, compare_mode, mode_ctx); constint this_cost = cost_mv_ref(&x->mode_costs, this_mode, mode_ctx);
// Only skip if the mode cost is larger than compare mode cost if (this_cost > compare_cost) {
search_state->modelled_rd[this_mode][0][ref_frames[0]] =
search_state->modelled_rd[compare_mode][0][ref_frames[0]]; return 1;
}
}
}
} return 0;
}
// To use single newmv directly for compound modes, need to clamp the mv to the // valid mv range. Without this, encoder would generate out of range mv, and // this is seen in 8k encoding. staticinlinevoid clamp_mv_in_range(MACROBLOCK *const x, int_mv *mv, int ref_idx) { const int_mv ref_mv = av1_get_ref_mv(x, ref_idx);
SubpelMvLimits mv_limits;
// Return after single_newmv is set. if (mode_info[mbmi->ref_mv_idx].skip) return INT64_MAX;
}
return 0;
}
staticinlinevoid update_mode_start_end_index( const AV1_COMP *const cpi, const MB_MODE_INFO *const mbmi, int *mode_index_start, int *mode_index_end, int last_motion_mode_allowed, int interintra_allowed, int eval_motion_mode) {
*mode_index_start = (int)SIMPLE_TRANSLATION;
*mode_index_end = (int)last_motion_mode_allowed + interintra_allowed; if (cpi->sf.winner_mode_sf.motion_mode_for_winner_cand) { if (!eval_motion_mode) {
*mode_index_end = (int)SIMPLE_TRANSLATION;
} else { // Set the start index appropriately to process motion modes other than // simple translation
*mode_index_start = 1;
}
} if (cpi->sf.inter_sf.extra_prune_warped && mbmi->bsize > BLOCK_16X16)
*mode_index_end = SIMPLE_TRANSLATION;
}
/*!\brief AV1 motion mode search * * \ingroup inter_mode_search * Function to search over and determine the motion mode. It will update * mbmi->motion_mode to one of SIMPLE_TRANSLATION, OBMC_CAUSAL, or * WARPED_CAUSAL and determine any necessary side information for the selected * motion mode. It will also perform the full transform search, unless the * input parameter do_tx_search indicates to do an estimation of the RD rather * than an RD corresponding to a full transform search. It will return the * RD for the final motion_mode. * Do the RD search for a given inter mode and compute all information relevant * to the input mode. It will compute the best MV, * compound parameters (if the mode is a compound mode) and interpolation filter * parameters. * * \param[in] cpi Top-level encoder structure. * \param[in] tile_data Pointer to struct holding adaptive * data/contexts/models for the tile during * encoding. * \param[in] x Pointer to struct holding all the data for * the current macroblock. * \param[in] bsize Current block size. * \param[in,out] rd_stats Struct to keep track of the overall RD * information. * \param[in,out] rd_stats_y Struct to keep track of the RD information * for only the Y plane. * \param[in,out] rd_stats_uv Struct to keep track of the RD information * for only the UV planes. * \param[in] args HandleInterModeArgs struct holding * miscellaneous arguments for inter mode * search. See the documentation for this * struct for a description of each member. * \param[in] ref_best_rd Best RD found so far for this block. * It is used for early termination of this * search if the RD exceeds this value. * \param[in,out] ref_skip_rd A length 2 array, where skip_rd[0] is the * best total RD for a skip mode so far, and * skip_rd[1] is the best RD for a skip mode so * far in luma. This is used as a speed feature * to skip the transform search if the computed * skip RD for the current mode is not better * than the best skip_rd so far. * \param[in,out] rate_mv The rate associated with the motion vectors. * This will be modified if a motion search is * done in the motion mode search. * \param[in,out] orig_dst A prediction buffer to hold a computed * prediction. This will eventually hold the * final prediction, and the tmp_dst info will * be copied here. * \param[in,out] best_est_rd Estimated RD for motion mode search if * do_tx_search (see below) is 0. * \param[in] do_tx_search Parameter to indicate whether or not to do * a full transform search. This will compute * an estimated RD for the modes without the * transform search and later perform the full * transform search on the best candidates. * \param[in] inter_modes_info InterModesInfo struct to hold inter mode * information to perform a full transform * search only on winning candidates searched * with an estimate for transform coding RD. * \param[in] eval_motion_mode Boolean whether or not to evaluate motion * motion modes other than SIMPLE_TRANSLATION. * \param[out] yrd Stores the rdcost corresponding to encoding * the luma plane. * \return Returns INT64_MAX if the determined motion mode is invalid and the * current motion mode being tested should be skipped. It returns 0 if the * motion mode search is a success.
*/ static int64_t motion_mode_rd( const AV1_COMP *const cpi, TileDataEnc *tile_data, MACROBLOCK *const x,
BLOCK_SIZE bsize, RD_STATS *rd_stats, RD_STATS *rd_stats_y,
RD_STATS *rd_stats_uv, HandleInterModeArgs *const args, int64_t ref_best_rd,
int64_t *ref_skip_rd, int *rate_mv, const BUFFER_SET *orig_dst,
int64_t *best_est_rd, int do_tx_search, InterModesInfo *inter_modes_info, int eval_motion_mode, int64_t *yrd) { const AV1_COMMON *const cm = &cpi->common; const FeatureFlags *const features = &cm->features;
TxfmSearchInfo *txfm_info = &x->txfm_search_info; constint num_planes = av1_num_planes(cm);
MACROBLOCKD *xd = &x->e_mbd;
MB_MODE_INFO *mbmi = xd->mi[0]; constint is_comp_pred = has_second_ref(mbmi); const PREDICTION_MODE this_mode = mbmi->mode; constint rate2_nocoeff = rd_stats->rate; int best_xskip_txfm = 0;
RD_STATS best_rd_stats, best_rd_stats_y, best_rd_stats_uv;
uint8_t best_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE];
uint8_t best_tx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE]; constint rate_mv0 = *rate_mv; constint interintra_allowed = cm->seq_params->enable_interintra_compound &&
is_interintra_allowed(mbmi) &&
mbmi->compound_idx;
WARP_SAMPLE_INFO *const warp_sample_info =
&x->warp_sample_info[mbmi->ref_frame[0]]; int *pts0 = warp_sample_info->pts; int *pts_inref0 = warp_sample_info->pts_inref;
assert(mbmi->ref_frame[1] != INTRA_FRAME); const MV_REFERENCE_FRAME ref_frame_1 = mbmi->ref_frame[1];
av1_invalid_rd_stats(&best_rd_stats);
mbmi->num_proj_ref = 1; // assume num_proj_ref >=1
MOTION_MODE last_motion_mode_allowed = SIMPLE_TRANSLATION;
*yrd = INT64_MAX; if (features->switchable_motion_mode) { // Determine which motion modes to search if more than SIMPLE_TRANSLATION // is allowed.
last_motion_mode_allowed = motion_mode_allowed(
xd->global_motion, xd, mbmi, features->allow_warped_motion);
}
if (last_motion_mode_allowed == WARPED_CAUSAL) { // Collect projection samples used in least squares approximation of // the warped motion parameters if WARPED_CAUSAL is going to be searched. if (warp_sample_info->num < 0) {
warp_sample_info->num = av1_findSamples(cm, xd, pts0, pts_inref0);
}
mbmi->num_proj_ref = warp_sample_info->num;
} constint total_samples = mbmi->num_proj_ref; if (total_samples == 0) { // Do not search WARPED_CAUSAL if there are no samples to use to determine // warped parameters.
last_motion_mode_allowed = OBMC_CAUSAL;
}
// Modify the start and end index according to speed features. For example, // if SIMPLE_TRANSLATION has already been searched according to // the motion_mode_for_winner_cand speed feature, update the mode_index_start // to avoid searching it again.
update_mode_start_end_index(cpi, mbmi, &mode_index_start, &mode_index_end,
last_motion_mode_allowed, interintra_allowed,
eval_motion_mode); // Main function loop. This loops over all of the possible motion modes and // computes RD to determine the best one. This process includes computing // any necessary side information for the motion mode and performing the // transform search. for (int mode_index = mode_index_start; mode_index <= mode_index_end;
mode_index++) { if (args->skip_motion_mode && mode_index) continue; int tmp_rate2 = rate2_nocoeff; constint is_interintra_mode = mode_index > (int)last_motion_mode_allowed; int tmp_rate_mv = rate_mv0;
*mbmi = base_mbmi; if (is_interintra_mode) { // Only use SIMPLE_TRANSLATION for interintra
mbmi->motion_mode = SIMPLE_TRANSLATION;
} else {
mbmi->motion_mode = (MOTION_MODE)mode_index;
assert(mbmi->ref_frame[1] != INTRA_FRAME);
}
// Do not search OBMC if the probability of selecting it is below a // predetermined threshold for this update_type and block size. const FRAME_UPDATE_TYPE update_type =
get_frame_update_type(&cpi->ppi->gf_group, cpi->gf_frame_index); int use_actual_frame_probs = 1; int prune_obmc; #if CONFIG_FPMT_TEST
use_actual_frame_probs =
(cpi->ppi->fpmt_unit_test_cfg == PARALLEL_SIMULATION_ENCODE) ? 0 : 1; if (!use_actual_frame_probs) {
prune_obmc = cpi->ppi->temp_frame_probs.obmc_probs[update_type][bsize] <
cpi->sf.inter_sf.prune_obmc_prob_thresh;
} #endif if (use_actual_frame_probs) {
prune_obmc = cpi->ppi->frame_probs.obmc_probs[update_type][bsize] <
cpi->sf.inter_sf.prune_obmc_prob_thresh;
} if ((!cpi->oxcf.motion_mode_cfg.enable_obmc || prune_obmc) &&
mbmi->motion_mode == OBMC_CAUSAL) continue;
if (mbmi->motion_mode == SIMPLE_TRANSLATION && !is_interintra_mode) { // SIMPLE_TRANSLATION mode: no need to recalculate. // The prediction is calculated before motion_mode_rd() is called in // handle_inter_mode()
} elseif (mbmi->motion_mode == OBMC_CAUSAL) { const uint32_t cur_mv = mbmi->mv[0].as_int; // OBMC_CAUSAL not allowed for compound prediction
assert(!is_comp_pred); if (have_newmv_in_inter_mode(this_mode)) {
av1_single_motion_search(cpi, x, bsize, 0, &tmp_rate_mv, INT_MAX, NULL,
&mbmi->mv[0], NULL);
tmp_rate2 = rate2_nocoeff - rate_mv0 + tmp_rate_mv;
} if ((mbmi->mv[0].as_int != cur_mv) || eval_motion_mode) { // Build the predictor according to the current motion vector if it has // not already been built
av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, orig_dst, bsize,
0, av1_num_planes(cm) - 1);
} // Build the inter predictor by blending the predictor corresponding to // this MV, and the neighboring blocks using the OBMC model
av1_build_obmc_inter_prediction(
cm, xd, args->above_pred_buf, args->above_pred_stride,
args->left_pred_buf, args->left_pred_stride); #if !CONFIG_REALTIME_ONLY
} elseif (mbmi->motion_mode == WARPED_CAUSAL) { int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
mbmi->motion_mode = WARPED_CAUSAL;
mbmi->wm_params.wmtype = DEFAULT_WMTYPE;
mbmi->interp_filters =
av1_broadcast_interp_filter(av1_unswitchable_filter(interp_filter));
memcpy(pts, pts0, total_samples * 2 * sizeof(*pts0));
memcpy(pts_inref, pts_inref0, total_samples * 2 * sizeof(*pts_inref0)); // Select the samples according to motion vector difference if (mbmi->num_proj_ref > 1) {
mbmi->num_proj_ref = av1_selectSamples(
&mbmi->mv[0].as_mv, pts, pts_inref, mbmi->num_proj_ref, bsize);
}
// Compute the warped motion parameters with a least squares fit // using the collected samples if (!av1_find_projection(mbmi->num_proj_ref, pts, pts_inref, bsize,
mbmi->mv[0].as_mv.row, mbmi->mv[0].as_mv.col,
&mbmi->wm_params, mi_row, mi_col)) {
assert(!is_comp_pred); if (have_newmv_in_inter_mode(this_mode)) { // Refine MV for NEWMV mode const int_mv mv0 = mbmi->mv[0]; const WarpedMotionParams wm_params0 = mbmi->wm_params; constint num_proj_ref0 = mbmi->num_proj_ref;
// Refine MV in a small range.
av1_refine_warped_mv(xd, cm, &ms_params, bsize, pts0, pts_inref0,
total_samples, cpi->sf.mv_sf.warp_search_method,
cpi->sf.mv_sf.warp_search_iters);
if (mv0.as_int != mbmi->mv[0].as_int) { // Keep the refined MV and WM parameters.
tmp_rate_mv = av1_mv_bit_cost(
&mbmi->mv[0].as_mv, &ref_mv.as_mv, x->mv_costs->nmv_joint_cost,
x->mv_costs->mv_cost_stack, MV_COST_WEIGHT);
tmp_rate2 = rate2_nocoeff - rate_mv0 + tmp_rate_mv;
} else { // Restore the old MV and WM parameters.
mbmi->mv[0] = mv0;
mbmi->wm_params = wm_params0;
mbmi->num_proj_ref = num_proj_ref0;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.