/* * Copyright (c) 2020, 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.
*/
// Reset speed features that works for the baseline encoding, but // blocks the external partition search. void av1_reset_sf_for_ext_part(AV1_COMP *const cpi) {
cpi->sf.inter_sf.prune_ref_frame_for_rect_partitions = 0;
} #endif// CONFIG_PARTITION_SEARCH_ORDER
#if !CONFIG_REALTIME_ONLY // If input |features| is NULL, write tpl stats to file for each super block. // Otherwise, store tpl stats to |features|. // The tpl stats is computed in the unit of tpl_bsize_1d (16x16). // When writing to text file: // The first row contains super block position, super block size, // tpl unit length, number of units in the super block. // The second row contains the intra prediction cost for each unit. // The third row contains the inter prediction cost for each unit. // The forth row contains the motion compensated dependency cost for each unit. staticvoid collect_tpl_stats_sb(const AV1_COMP *const cpi, const BLOCK_SIZE bsize, constint mi_row, constint mi_col,
aom_partition_features_t *features) { const AV1_COMMON *const cm = &cpi->common;
GF_GROUP *gf_group = &cpi->ppi->gf_group; if (gf_group->update_type[cpi->gf_frame_index] == INTNL_OVERLAY_UPDATE ||
gf_group->update_type[cpi->gf_frame_index] == OVERLAY_UPDATE) { return;
}
TplParams *const tpl_data = &cpi->ppi->tpl_data;
TplDepFrame *tpl_frame = &tpl_data->tpl_frame[cpi->gf_frame_index];
TplDepStats *tpl_stats = tpl_frame->tpl_stats_ptr; // If tpl stats is not established, early return if (!tpl_data->ready || gf_group->max_layer_depth_allowed == 0) { if (features != NULL) features->sb_features.tpl_features.available = 0; return;
}
for (int row = 0; row < tx_size_high_unit[tx_size]; row += bsh) { for (int col = 0; col < tx_size_wide_unit[tx_size]; col += bsw) { int offsetr = row; int offsetc = col;
// If there is at least one lossless segment, force the skip for intra // block to be 0, in order to avoid the segment_id to be changed by in // write_segment_id(). if (!cpi->common.seg.segid_preskip && cpi->common.seg.update_map &&
cpi->enc_seg.has_lossless_segment)
mbmi->skip_txfm = 0;
// Check to make sure that the adjustments above have not caused the // rd multiplier to be truncated to 0.
x->rdmult = (x->rdmult > 0) ? x->rdmult : 1;
}
// Set up destination pointers.
av1_setup_dst_planes(xd->plane, bsize, &cm->cur_frame->buf, mi_row, mi_col, 0,
num_planes);
// Set up limit values for MV components. // Mv beyond the range do not produce new/different prediction block.
av1_set_mv_limits(&cm->mi_params, &x->mv_limits, mi_row, mi_col, mi_height,
mi_width, cpi->oxcf.border_in_pixels);
// Set up distance of MB to edge of frame in 1/8th pel units.
assert(!(mi_col & (mi_width - 1)) && !(mi_row & (mi_height - 1)));
set_mi_row_col(xd, tile, mi_row, mi_height, mi_col, mi_width,
cm->mi_params.mi_rows, cm->mi_params.mi_cols);
// Set up source buffers.
av1_setup_src_planes(x, cpi->source, mi_row, mi_col, num_planes, bsize);
// required by av1_append_sub8x8_mvs_for_idx() and av1_find_best_ref_mvs()
xd->tile = *tile;
}
void av1_set_offsets(const AV1_COMP *const cpi, const TileInfo *const tile,
MACROBLOCK *const x, int mi_row, int mi_col,
BLOCK_SIZE bsize) { const AV1_COMMON *const cm = &cpi->common; conststruct segmentation *const seg = &cm->seg;
MACROBLOCKD *const xd = &x->e_mbd;
MB_MODE_INFO *mbmi;
/*!\brief Hybrid intra mode search. * * \ingroup intra_mode_search * \callgraph * \callergraph * This is top level function for mode search for intra frames in non-RD * optimized case. Depending on speed feature and block size it calls * either non-RD or RD optimized intra mode search. * * \param[in] cpi Top-level encoder structure * \param[in] x Pointer to structure holding all the data for the current macroblock * \param[in] rd_cost Struct to keep track of the RD information * \param[in] bsize Current block size * \param[in] ctx Structure to hold snapshot of coding context during the mode picking process * * \remark Nothing is returned. Instead, the MB_MODE_INFO struct inside x * is modified to store information about the best mode computed * in this function. The rd_cost struct is also updated with the RD stats * corresponding to the best mode found.
*/
staticinlinevoid hybrid_intra_mode_search(AV1_COMP *cpi, MACROBLOCK *const x,
RD_STATS *rd_cost, BLOCK_SIZE bsize,
PICK_MODE_CONTEXT *ctx) { int use_rdopt = 0; constint hybrid_intra_pickmode = cpi->sf.rt_sf.hybrid_intra_pickmode; // Use rd pick for intra mode search based on block size and variance. if (hybrid_intra_pickmode && bsize < BLOCK_16X16) { unsignedint var_thresh[3] = { 0, 101, 201 };
assert(hybrid_intra_pickmode <= 3); if (x->source_variance >= var_thresh[hybrid_intra_pickmode - 1])
use_rdopt = 1;
}
// For real time/allintra row-mt enabled multi-threaded encoding with cost // update frequency set to COST_UPD_TILE/COST_UPD_OFF, tile ctxt is not updated // at superblock level. Thus, it is not required for the encoding of top-right // superblock be complete for updating tile ctxt. However, when encoding a block // whose right edge is also the superblock edge, intra and inter mode evaluation // (ref mv list population) require the encoding of the top-right superblock to // be complete. So, here, we delay the waiting of threads until the need for the // data from the top-right superblock region. staticinlinevoid wait_for_top_right_sb(AV1EncRowMultiThreadInfo *enc_row_mt,
AV1EncRowMultiThreadSync *row_mt_sync,
TileInfo *tile_info,
BLOCK_SIZE sb_size, int sb_mi_size_log2, BLOCK_SIZE bsize, int mi_row, int mi_col) { constint sb_size_in_mi = mi_size_wide[sb_size]; constint bw_in_mi = mi_size_wide[bsize]; constint blk_row_in_sb = mi_row & (sb_size_in_mi - 1); constint blk_col_in_sb = mi_col & (sb_size_in_mi - 1); constint top_right_block_in_sb =
(blk_row_in_sb == 0) && (blk_col_in_sb + bw_in_mi >= sb_size_in_mi);
// Don't wait if the block is the not the top-right block in the superblock. if (!top_right_block_in_sb) return;
// Wait for the top-right superblock to finish encoding. constint sb_row_in_tile =
(mi_row - tile_info->mi_row_start) >> sb_mi_size_log2; constint sb_col_in_tile =
(mi_col - tile_info->mi_col_start) >> sb_mi_size_log2;
/*!\brief Interface for AV1 mode search for an individual coding block * * \ingroup partition_search * \callgraph * \callergraph * Searches prediction modes, transform, and coefficient coding modes for an * individual coding block. This function is the top-level interface that * directs the encoder to the proper mode search function, among these * implemented for inter/intra + rd/non-rd + non-skip segment/skip segment. * * \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 structure holding all the data for * the current macroblock * \param[in] mi_row Row coordinate of the block in a step size of * MI_SIZE * \param[in] mi_col Column coordinate of the block in a step size of * MI_SIZE * \param[in] rd_cost Pointer to structure holding rate and distortion * stats for the current block * \param[in] partition Partition mode of the parent block * \param[in] bsize Current block size * \param[in] ctx Pointer to structure holding coding contexts and * chosen modes for the current block * \param[in] best_rd Upper bound of rd cost of a valid partition * * \remark Nothing is returned. Instead, the chosen modes and contexts necessary * for reconstruction are stored in ctx, the rate-distortion stats are stored in * rd_cost. If no valid mode leading to rd_cost <= best_rd, the status will be * signalled by an INT64_MAX rd_cost->rdcost.
*/ staticvoid pick_sb_modes(AV1_COMP *const cpi, TileDataEnc *tile_data,
MACROBLOCK *const x, int mi_row, int mi_col,
RD_STATS *rd_cost, PARTITION_TYPE partition,
BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
RD_STATS best_rd) { if (cpi->sf.part_sf.use_best_rd_for_pruning && best_rd.rdcost < 0) {
ctx->rd_stats.rdcost = INT64_MAX;
ctx->rd_stats.skip_txfm = 0;
av1_invalid_rd_stats(rd_cost); return;
}
// This is only needed for real time/allintra row-mt enabled multi-threaded // encoding with cost update frequency set to COST_UPD_TILE/COST_UPD_OFF.
wait_for_top_right_sb(&cpi->mt_info.enc_row_mt, &tile_data->row_mt_sync,
&tile_data->tile_info, cm->seq_params->sb_size,
cm->seq_params->mib_size_log2, bsize, mi_row, mi_col);
// Sets up the tx_type_map buffer in MACROBLOCKD.
xd->tx_type_map = txfm_info->tx_type_map_;
xd->tx_type_map_stride = mi_size_wide[bsize];
for (i = 0; i < num_planes; ++i) {
p[i].coeff = ctx->coeff[i];
p[i].qcoeff = ctx->qcoeff[i];
p[i].dqcoeff = ctx->dqcoeff[i];
p[i].eobs = ctx->eobs[i];
p[i].txb_entropy_ctx = ctx->txb_entropy_ctx[i];
}
for (i = 0; i < 2; ++i) pd[i].color_index_map = ctx->color_index_map[i];
ctx->skippable = 0; // Set to zero to make sure we do not use the previous encoded frame stats
mbmi->skip_txfm = 0; // Reset skip mode flag.
mbmi->skip_mode = 0;
// Save rdmult before it might be changed, so it can be restored later. constint orig_rdmult = x->rdmult;
setup_block_rdmult(cpi, x, mi_row, mi_col, bsize, aq_mode, mbmi); // Set error per bit for current rdmult
av1_set_error_per_bit(&x->errorperbit, x->rdmult);
av1_rd_cost_update(x->rdmult, &best_rd);
// If set best_rd.rdcost to INT64_MAX, the encoder will not use any previous // rdcost information for the following mode search. // Disabling the feature could get some coding gain, with encoder slowdown. if (!cpi->sf.part_sf.use_best_rd_for_pruning) {
av1_invalid_rd_stats(&best_rd);
}
// Find best coding mode & reconstruct the MB so it is available // as a predictor for MBs that follow in the SB if (frame_is_intra_only(cm)) { #if CONFIG_COLLECT_COMPONENT_TIMING
start_timing(cpi, av1_rd_pick_intra_mode_sb_time); #endif
av1_rd_pick_intra_mode_sb(cpi, x, rd_cost, bsize, ctx, best_rd.rdcost); #if CONFIG_COLLECT_COMPONENT_TIMING
end_timing(cpi, av1_rd_pick_intra_mode_sb_time); #endif
} else { #if CONFIG_COLLECT_COMPONENT_TIMING
start_timing(cpi, av1_rd_pick_inter_mode_sb_time); #endif if (segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
av1_rd_pick_inter_mode_sb_seg_skip(cpi, tile_data, x, mi_row, mi_col,
rd_cost, bsize, ctx, best_rd.rdcost);
} else {
av1_rd_pick_inter_mode(cpi, tile_data, x, rd_cost, bsize, ctx,
best_rd.rdcost);
} #if CONFIG_COLLECT_COMPONENT_TIMING
end_timing(cpi, av1_rd_pick_inter_mode_sb_time); #endif
}
// Examine the resulting rate and for AQ mode 2 make a segment choice. if (rd_cost->rate != INT_MAX && aq_mode == COMPLEXITY_AQ &&
bsize >= BLOCK_16X16) {
av1_caq_select_segment(cpi, x, bsize, mi_row, mi_col, rd_cost->rate);
}
x->rdmult = orig_rdmult;
// TODO(jingning) The rate-distortion optimization flow needs to be // refactored to provide proper exit/return handle. if (rd_cost->rate == INT_MAX) rd_cost->rdcost = INT64_MAX;
if (!seg_ref_active) { #if CONFIG_ENTROPY_STATS
counts->intra_inter[av1_get_intra_inter_context(xd)][inter_block]++; #endif
update_cdf(fc->intra_inter_cdf[av1_get_intra_inter_context(xd)],
inter_block, 2); // If the segment reference feature is enabled we have only a single // reference frame allowed for the segment so exclude it from // the reference frame counts used to work out probabilities. if (inter_block) { const MV_REFERENCE_FRAME ref0 = mbmi->ref_frame[0]; const MV_REFERENCE_FRAME ref1 = mbmi->ref_frame[1]; if (current_frame->reference_mode == REFERENCE_MODE_SELECT) { if (is_comp_ref_allowed(bsize)) { #if CONFIG_ENTROPY_STATS
counts->comp_inter[av1_get_reference_mode_context(xd)]
[has_second_ref(mbmi)]++; #endif// CONFIG_ENTROPY_STATS
update_cdf(av1_get_reference_mode_cdf(xd), has_second_ref(mbmi), 2);
}
}
/*!\brief Reconstructs an individual coding block * * \ingroup partition_search * Reconstructs an individual coding block by applying the chosen modes stored * in ctx, also updates mode counts and entropy models. * * \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] td Pointer to thread data * \param[in] tp Pointer to the starting token * \param[in] mi_row Row coordinate of the block in a step size of MI_SIZE * \param[in] mi_col Column coordinate of the block in a step size of * MI_SIZE * \param[in] dry_run A code indicating whether it is part of the final * pass for reconstructing the superblock * \param[in] bsize Current block size * \param[in] partition Partition mode of the parent block * \param[in] ctx Pointer to structure holding coding contexts and the * chosen modes for the current block * \param[in] rate Pointer to the total rate for the current block * * \remark Nothing is returned. Instead, reconstructions (w/o in-loop filters) * will be updated in the pixel buffers in td->mb.e_mbd. Also, the chosen modes * will be stored in the MB_MODE_INFO buffer td->mb.e_mbd.mi[0].
*/ staticvoid encode_b(const AV1_COMP *const cpi, TileDataEnc *tile_data,
ThreadData *td, TokenExtra **tp, int mi_row, int mi_col,
RUN_TYPE dry_run, BLOCK_SIZE bsize,
PARTITION_TYPE partition, PICK_MODE_CONTEXT *const ctx, int *rate) { const AV1_COMMON *const cm = &cpi->common;
TileInfo *const tile = &tile_data->tile_info;
MACROBLOCK *const x = &td->mb;
MACROBLOCKD *xd = &x->e_mbd; constint subsampling_x = cm->seq_params->subsampling_x; constint subsampling_y = cm->seq_params->subsampling_y;
// delta quant applies to both intra and inter constint super_block_upper_left =
((mi_row & (cm->seq_params->mib_size - 1)) == 0) &&
((mi_col & (cm->seq_params->mib_size - 1)) == 0); const DeltaQInfo *const delta_q_info = &cm->delta_q_info; if (delta_q_info->delta_q_present_flag &&
(bsize != cm->seq_params->sb_size || !mbmi->skip_txfm) &&
super_block_upper_left) {
xd->current_base_qindex = mbmi->current_qindex; if (delta_q_info->delta_lf_present_flag) { if (delta_q_info->delta_lf_multi) { constint frame_lf_count =
av1_num_planes(cm) > 1 ? FRAME_LF_COUNT : FRAME_LF_COUNT - 2; for (int lf_id = 0; lf_id < frame_lf_count; ++lf_id) {
xd->delta_lf[lf_id] = mbmi->delta_lf[lf_id];
}
} else {
xd->delta_lf_from_base = mbmi->delta_lf_from_base;
}
}
}
RD_COUNTS *rdc = &td->rd_counts; if (mbmi->skip_mode) {
assert(!frame_is_intra_only(cm));
rdc->skip_mode_used_flag = 1; if (cm->current_frame.reference_mode == REFERENCE_MODE_SELECT) {
assert(has_second_ref(mbmi));
rdc->compound_ref_used_flag = 1;
}
set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
} else { constint seg_ref_active =
segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_REF_FRAME); if (!seg_ref_active) { // If the segment reference feature is enabled we have only a single // reference frame allowed for the segment so exclude it from // the reference frame counts used to work out probabilities. if (is_inter_block(mbmi)) {
av1_collect_neighbors_ref_counts(xd); if (cm->current_frame.reference_mode == REFERENCE_MODE_SELECT) { if (has_second_ref(mbmi)) { // This flag is also updated for 4x4 blocks
rdc->compound_ref_used_flag = 1;
}
}
set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
}
}
}
if (tile_data->allow_update_cdf) update_stats(&cpi->common, td);
if (mbmi->ref_frame[1] != INTRA_FRAME) { if (motion_allowed >= OBMC_CAUSAL) {
td->rd_counts.obmc_used[bsize][mbmi->motion_mode == OBMC_CAUSAL]++;
} if (motion_allowed == WARPED_CAUSAL) {
td->rd_counts.warped_used[mbmi->motion_mode == WARPED_CAUSAL]++;
}
}
}
}
} // TODO(Ravi/Remya): Move this copy function to a better logical place // This function will copy the best mode information from block // level (x->mbmi_ext) to frame level (cpi->mbmi_ext_info.frame_base). This // frame level buffer (cpi->mbmi_ext_info.frame_base) will be used during // bitstream preparation.
av1_copy_mbmi_ext_to_mbmi_ext_frame(x->mbmi_ext_frame, &x->mbmi_ext,
av1_ref_frame_type(xd->mi[0]->ref_frame));
x->rdmult = origin_mult;
}
/*!\brief Reconstructs a partition (may contain multiple coding blocks) * * \ingroup partition_search * Reconstructs a sub-partition of the superblock by applying the chosen modes * and partition trees stored in pc_tree. * * \param[in] cpi Top-level encoder structure * \param[in] td Pointer to thread data * \param[in] tile_data Pointer to struct holding adaptive * data/contexts/models for the tile during encoding * \param[in] tp Pointer to the starting token * \param[in] mi_row Row coordinate of the block in a step size of MI_SIZE * \param[in] mi_col Column coordinate of the block in a step size of * MI_SIZE * \param[in] dry_run A code indicating whether it is part of the final * pass for reconstructing the superblock * \param[in] bsize Current block size * \param[in] pc_tree Pointer to the PC_TREE node storing the picked * partitions and mode info for the current block * \param[in] rate Pointer to the total rate for the current block * * \remark Nothing is returned. Instead, reconstructions (w/o in-loop filters) * will be updated in the pixel buffers in td->mb.e_mbd.
*/ staticvoid encode_sb(const AV1_COMP *const cpi, ThreadData *td,
TileDataEnc *tile_data, TokenExtra **tp, int mi_row, int mi_col, RUN_TYPE dry_run, BLOCK_SIZE bsize,
PC_TREE *pc_tree, int *rate) {
assert(bsize < BLOCK_SIZES_ALL); const AV1_COMMON *const cm = &cpi->common; const CommonModeInfoParams *const mi_params = &cm->mi_params;
MACROBLOCK *const x = &td->mb;
MACROBLOCKD *const xd = &x->e_mbd;
assert(bsize < BLOCK_SIZES_ALL); constint hbs = mi_size_wide[bsize] / 2;
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.52 Sekunden
(vorverarbeitet)
¤
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.