Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed features. Specifically, intead of using a flag use_largest_txfm as a speed feature, an enum tx_size_search_method is used, of which two of the types are USE_FULL_RD and USE_LARGESTALL. Two other new types are added: USE_LARGESTINTRA (use largest only for intra) USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for inter) (2) Another change is that the framework for deciding transform type is simplified to use a heuristic count based method rather than an rd based method using txfm_cache. In practice the new method is found to work just as well - with derf only -0.01 down. The new method is more compatible with the new framework where certain rd costs are based on full rd and certain others are based on modeled rd or are not computed. In this patch the existing rd based method is still kept for use in the USE_FULL_RD mode. In the other modes, the count based method is used. However the recommendation is to remove it eventually since the benefit is limited, and will remove a lot of complications in the code (3) Finally a bug is fixed with the existing use_largest_txfm speed feature that causes mismatches when the lossless mode and 4x4 WH transform is forced. Results on derf: USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a pretty good compromise) USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction (currently the benefit of modeling is limited for txfm size selection, but keeping this enum as a placeholder) . USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing use_largest_txfm speed feature). Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
This commit is contained in:
Родитель
904070ca64
Коммит
8d3d2b76f3
|
@ -122,13 +122,6 @@ typedef enum {
|
|||
|
||||
#define WHT_UPSCALE_FACTOR 2
|
||||
|
||||
#define TX_SIZE_PROBS 6 // (TX_SIZE_MAX_SB * (TX_SIZE_MAX_SB - 1) / 2)
|
||||
|
||||
#define get_tx_probs(c, b) ((b) < BLOCK_SIZE_MB16X16 ? \
|
||||
(c)->fc.tx_probs_8x8p : \
|
||||
(b) < BLOCK_SIZE_SB32X32 ? \
|
||||
(c)->fc.tx_probs_16x16p : (c)->fc.tx_probs_32x32p)
|
||||
|
||||
/* For keyframes, intra block modes are predicted by the (already decoded)
|
||||
modes for the Y blocks to the left and above us; for interframes, there
|
||||
is a single probability table. */
|
||||
|
|
|
@ -1678,6 +1678,7 @@ static void init_encode_frame_mb_context(VP9_COMP *cpi) {
|
|||
|
||||
static void switch_lossless_mode(VP9_COMP *cpi, int lossless) {
|
||||
if (lossless) {
|
||||
// printf("Switching to lossless\n");
|
||||
cpi->mb.fwd_txm8x4 = vp9_short_walsh8x4;
|
||||
cpi->mb.fwd_txm4x4 = vp9_short_walsh4x4;
|
||||
cpi->mb.e_mbd.inv_txm4x4_1_add = vp9_short_iwalsh4x4_1_add;
|
||||
|
@ -1687,6 +1688,7 @@ static void switch_lossless_mode(VP9_COMP *cpi, int lossless) {
|
|||
cpi->zbin_mode_boost_enabled = 0;
|
||||
cpi->common.txfm_mode = ONLY_4X4;
|
||||
} else {
|
||||
// printf("Not lossless\n");
|
||||
cpi->mb.fwd_txm8x4 = vp9_short_fdct8x4;
|
||||
cpi->mb.fwd_txm4x4 = vp9_short_fdct4x4;
|
||||
cpi->mb.e_mbd.inv_txm4x4_1_add = vp9_short_idct4x4_1_add;
|
||||
|
@ -1695,7 +1697,7 @@ static void switch_lossless_mode(VP9_COMP *cpi, int lossless) {
|
|||
}
|
||||
|
||||
static void switch_txfm_mode(VP9_COMP *cpi) {
|
||||
if (cpi->sf.use_largest_txform &&
|
||||
if (cpi->sf.tx_size_search_method == USE_LARGESTALL &&
|
||||
cpi->common.txfm_mode >= ALLOW_32X32)
|
||||
cpi->common.txfm_mode = ALLOW_32X32;
|
||||
}
|
||||
|
@ -1728,6 +1730,7 @@ static void encode_frame_internal(VP9_COMP *cpi) {
|
|||
|
||||
vp9_zero(cm->fc.switchable_interp_count);
|
||||
vp9_zero(cpi->best_switchable_interp_count);
|
||||
vp9_zero(cpi->txfm_stepdown_count);
|
||||
|
||||
xd->mode_info_context = cm->mi;
|
||||
xd->prev_mode_info_context = cm->prev_mi;
|
||||
|
@ -1930,6 +1933,47 @@ static void reset_skip_txfm_size(VP9_COMP *cpi, TX_SIZE txfm_max) {
|
|||
}
|
||||
}
|
||||
|
||||
static int get_frame_type(VP9_COMP *cpi) {
|
||||
int frame_type;
|
||||
if (cpi->common.frame_type == KEY_FRAME)
|
||||
frame_type = 0;
|
||||
else if (cpi->is_src_frame_alt_ref && cpi->refresh_golden_frame)
|
||||
frame_type = 3;
|
||||
else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)
|
||||
frame_type = 1;
|
||||
else
|
||||
frame_type = 2;
|
||||
return frame_type;
|
||||
}
|
||||
|
||||
static void select_txfm_mode(VP9_COMP *cpi) {
|
||||
if (cpi->oxcf.lossless) {
|
||||
cpi->common.txfm_mode = ONLY_4X4;
|
||||
} else if (cpi->common.current_video_frame == 0) {
|
||||
cpi->common.txfm_mode = TX_MODE_SELECT;
|
||||
} else {
|
||||
if (cpi->sf.tx_size_search_method == USE_FULL_RD) {
|
||||
int frame_type = get_frame_type(cpi);
|
||||
cpi->common.txfm_mode =
|
||||
cpi->rd_tx_select_threshes[frame_type][ALLOW_32X32]
|
||||
> cpi->rd_tx_select_threshes[frame_type][TX_MODE_SELECT] ?
|
||||
ALLOW_32X32 : TX_MODE_SELECT;
|
||||
} else if (cpi->sf.tx_size_search_method == USE_LARGESTALL) {
|
||||
cpi->common.txfm_mode = ALLOW_32X32;
|
||||
} else {
|
||||
unsigned int total = 0;
|
||||
int i;
|
||||
for (i = 0; i < TX_SIZE_MAX_SB; ++i)
|
||||
total += cpi->txfm_stepdown_count[i];
|
||||
if (total) {
|
||||
double fraction = (double)cpi->txfm_stepdown_count[0] / total;
|
||||
cpi->common.txfm_mode = fraction > 0.90 ? ALLOW_32X32 : TX_MODE_SELECT;
|
||||
// printf("fraction = %f\n", fraction);
|
||||
} // else keep unchanged
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vp9_encode_frame(VP9_COMP *cpi) {
|
||||
VP9_COMMON * const cm = &cpi->common;
|
||||
|
||||
|
@ -1940,7 +1984,7 @@ void vp9_encode_frame(VP9_COMP *cpi) {
|
|||
// side behaviour is where the ALT ref buffer has oppositie sign bias to
|
||||
// the other two.
|
||||
if ((cm->ref_frame_sign_bias[ALTREF_FRAME]
|
||||
== cm->ref_frame_sign_bias[GOLDEN_FRAME])
|
||||
== cm->ref_frame_sign_bias[GOLDEN_FRAME])
|
||||
|| (cm->ref_frame_sign_bias[ALTREF_FRAME]
|
||||
== cm->ref_frame_sign_bias[LAST_FRAME])) {
|
||||
cm->allow_comp_inter_inter = 0;
|
||||
|
@ -1952,9 +1996,7 @@ void vp9_encode_frame(VP9_COMP *cpi) {
|
|||
}
|
||||
|
||||
if (cpi->sf.RD) {
|
||||
int i, frame_type, pred_type;
|
||||
TXFM_MODE txfm_type;
|
||||
|
||||
int i, pred_type;
|
||||
/*
|
||||
* This code does a single RD pass over the whole frame assuming
|
||||
* either compound, single or hybrid prediction as per whatever has
|
||||
|
@ -1964,26 +2006,19 @@ void vp9_encode_frame(VP9_COMP *cpi) {
|
|||
* that for subsequent frames.
|
||||
* It does the same analysis for transform size selection also.
|
||||
*/
|
||||
if (cpi->common.frame_type == KEY_FRAME)
|
||||
frame_type = 0;
|
||||
else if (cpi->is_src_frame_alt_ref && cpi->refresh_golden_frame)
|
||||
frame_type = 3;
|
||||
else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)
|
||||
frame_type = 1;
|
||||
else
|
||||
frame_type = 2;
|
||||
int frame_type = get_frame_type(cpi);
|
||||
|
||||
/* prediction (compound, single or hybrid) mode selection */
|
||||
if (frame_type == 3 || !cm->allow_comp_inter_inter)
|
||||
pred_type = SINGLE_PREDICTION_ONLY;
|
||||
else if (cpi->rd_prediction_type_threshes[frame_type][1]
|
||||
> cpi->rd_prediction_type_threshes[frame_type][0]
|
||||
&& cpi->rd_prediction_type_threshes[frame_type][1]
|
||||
> cpi->rd_prediction_type_threshes[frame_type][2]
|
||||
&& check_dual_ref_flags(cpi) && cpi->static_mb_pct == 100)
|
||||
> cpi->rd_prediction_type_threshes[frame_type][0]
|
||||
&& cpi->rd_prediction_type_threshes[frame_type][1]
|
||||
> cpi->rd_prediction_type_threshes[frame_type][2]
|
||||
&& check_dual_ref_flags(cpi) && cpi->static_mb_pct == 100)
|
||||
pred_type = COMP_PREDICTION_ONLY;
|
||||
else if (cpi->rd_prediction_type_threshes[frame_type][0]
|
||||
> cpi->rd_prediction_type_threshes[frame_type][2])
|
||||
> cpi->rd_prediction_type_threshes[frame_type][2])
|
||||
pred_type = SINGLE_PREDICTION_ONLY;
|
||||
else
|
||||
pred_type = HYBRID_PREDICTION;
|
||||
|
@ -1992,43 +2027,10 @@ void vp9_encode_frame(VP9_COMP *cpi) {
|
|||
|
||||
cpi->mb.e_mbd.lossless = 0;
|
||||
if (cpi->oxcf.lossless) {
|
||||
txfm_type = ONLY_4X4;
|
||||
cpi->mb.e_mbd.lossless = 1;
|
||||
} else
|
||||
#if 0
|
||||
/* FIXME (rbultje): this code is disabled until we support cost updates
|
||||
* while a frame is being encoded; the problem is that each time we
|
||||
* "revert" to 4x4 only (or even 8x8 only), the coefficient probabilities
|
||||
* for 16x16 (and 8x8) start lagging behind, thus leading to them lagging
|
||||
* further behind and not being chosen for subsequent frames either. This
|
||||
* is essentially a local minimum problem that we can probably fix by
|
||||
* estimating real costs more closely within a frame, perhaps by re-
|
||||
* calculating costs on-the-fly as frame encoding progresses. */
|
||||
if (cpi->rd_tx_select_threshes[frame_type][TX_MODE_SELECT] >
|
||||
cpi->rd_tx_select_threshes[frame_type][ONLY_4X4] &&
|
||||
cpi->rd_tx_select_threshes[frame_type][TX_MODE_SELECT] >
|
||||
cpi->rd_tx_select_threshes[frame_type][ALLOW_16X16] &&
|
||||
cpi->rd_tx_select_threshes[frame_type][TX_MODE_SELECT] >
|
||||
cpi->rd_tx_select_threshes[frame_type][ALLOW_8X8]) {
|
||||
txfm_type = TX_MODE_SELECT;
|
||||
} else if (cpi->rd_tx_select_threshes[frame_type][ONLY_4X4] >
|
||||
cpi->rd_tx_select_threshes[frame_type][ALLOW_8X8]
|
||||
&& cpi->rd_tx_select_threshes[frame_type][ONLY_4X4] >
|
||||
cpi->rd_tx_select_threshes[frame_type][ALLOW_16X16]
|
||||
) {
|
||||
txfm_type = ONLY_4X4;
|
||||
} else if (cpi->rd_tx_select_threshes[frame_type][ALLOW_16X16] >=
|
||||
cpi->rd_tx_select_threshes[frame_type][ALLOW_8X8]) {
|
||||
txfm_type = ALLOW_16X16;
|
||||
} else
|
||||
txfm_type = ALLOW_8X8;
|
||||
#else
|
||||
txfm_type =
|
||||
cpi->rd_tx_select_threshes[frame_type][ALLOW_32X32]
|
||||
> cpi->rd_tx_select_threshes[frame_type][TX_MODE_SELECT] ?
|
||||
ALLOW_32X32 : TX_MODE_SELECT;
|
||||
#endif
|
||||
cpi->common.txfm_mode = txfm_type;
|
||||
}
|
||||
|
||||
select_txfm_mode(cpi);
|
||||
cpi->common.comp_pred_mode = pred_type;
|
||||
encode_frame_internal(cpi);
|
||||
|
||||
|
@ -2043,7 +2045,7 @@ void vp9_encode_frame(VP9_COMP *cpi) {
|
|||
int diff;
|
||||
if (i == TX_MODE_SELECT)
|
||||
pd -= RDCOST(cpi->mb.rdmult, cpi->mb.rddiv,
|
||||
2048 * (TX_SIZE_MAX_SB - 1), 0);
|
||||
2048 * (TX_SIZE_MAX_SB - 1), 0);
|
||||
diff = (int) (pd / cpi->common.MBs);
|
||||
cpi->rd_tx_select_threshes[frame_type][i] += diff;
|
||||
cpi->rd_tx_select_threshes[frame_type][i] /= 2;
|
||||
|
@ -2102,7 +2104,7 @@ void vp9_encode_frame(VP9_COMP *cpi) {
|
|||
cpi->common.txfm_mode = ALLOW_8X8;
|
||||
reset_skip_txfm_size(cpi, TX_8X8);
|
||||
} else if (count8x8_8x8p == 0 && count16x16_16x16p == 0
|
||||
&& count8x8_lp == 0 && count16x16_lp == 0 && count32x32 == 0) {
|
||||
&& count8x8_lp == 0 && count16x16_lp == 0 && count32x32 == 0) {
|
||||
cpi->common.txfm_mode = ONLY_4X4;
|
||||
reset_skip_txfm_size(cpi, TX_4X4);
|
||||
} else if (count8x8_lp == 0 && count16x16_lp == 0 && count4x4 == 0) {
|
||||
|
|
|
@ -701,7 +701,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
|
|||
sf->comp_inter_joint_search_thresh = BLOCK_SIZE_AB4X4;
|
||||
sf->adaptive_rd_thresh = 0;
|
||||
sf->use_lastframe_partitioning = 0;
|
||||
sf->use_largest_txform = 0;
|
||||
sf->tx_size_search_method = USE_FULL_RD;
|
||||
sf->use_8tap_always = 0;
|
||||
sf->use_avoid_tested_higherror = 0;
|
||||
sf->skip_lots_of_modes = 0;
|
||||
|
@ -744,17 +744,15 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
|
|||
if (speed == 1) {
|
||||
sf->comp_inter_joint_search_thresh = BLOCK_SIZE_TYPES;
|
||||
sf->less_rectangular_check = 1;
|
||||
sf->use_largest_txform = !(cpi->common.frame_type == KEY_FRAME ||
|
||||
cpi->common.intra_only ||
|
||||
cpi->common.show_frame == 0);
|
||||
|
||||
sf->tx_size_search_method = ((cpi->common.frame_type == KEY_FRAME ||
|
||||
cpi->common.intra_only ||
|
||||
cpi->common.show_frame == 0) ?
|
||||
USE_FULL_RD :
|
||||
USE_LARGESTINTRA);
|
||||
sf->disable_splitmv =
|
||||
(MIN(cpi->common.width, cpi->common.height) >= 720)? 1 : 0;
|
||||
}
|
||||
if (speed == 2) {
|
||||
sf->use_largest_txform = !(cpi->common.frame_type == KEY_FRAME ||
|
||||
cpi->common.intra_only ||
|
||||
cpi->common.show_frame == 0);
|
||||
sf->adjust_thresholds_by_speed = 1;
|
||||
sf->less_rectangular_check = 1;
|
||||
sf->comp_inter_joint_search_thresh = BLOCK_SIZE_TYPES;
|
||||
|
@ -763,15 +761,30 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
|
|||
sf->use_lastframe_partitioning = 1;
|
||||
sf->adjust_partitioning_from_last_frame = 1;
|
||||
sf->last_partitioning_redo_frequency = 3;
|
||||
sf->tx_size_search_method = ((cpi->common.frame_type == KEY_FRAME ||
|
||||
cpi->common.intra_only ||
|
||||
cpi->common.show_frame == 0) ?
|
||||
USE_FULL_RD :
|
||||
USE_LARGESTALL);
|
||||
}
|
||||
if (speed == 3) {
|
||||
sf->comp_inter_joint_search_thresh = BLOCK_SIZE_TYPES;
|
||||
sf->partition_by_variance = 1;
|
||||
sf->tx_size_search_method = ((cpi->common.frame_type == KEY_FRAME ||
|
||||
cpi->common.intra_only ||
|
||||
cpi->common.show_frame == 0) ?
|
||||
USE_FULL_RD :
|
||||
USE_LARGESTALL);
|
||||
}
|
||||
if (speed == 4) {
|
||||
sf->comp_inter_joint_search_thresh = BLOCK_SIZE_TYPES;
|
||||
sf->use_one_partition_size_always = 1;
|
||||
sf->always_this_block_size = BLOCK_SIZE_MB16X16;
|
||||
sf->tx_size_search_method = ((cpi->common.frame_type == KEY_FRAME ||
|
||||
cpi->common.intra_only ||
|
||||
cpi->common.show_frame == 0) ?
|
||||
USE_FULL_RD :
|
||||
USE_LARGESTALL);
|
||||
}
|
||||
/*
|
||||
if (speed == 2) {
|
||||
|
@ -788,7 +801,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
|
|||
}
|
||||
*/
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
}; /* switch */
|
||||
|
||||
|
|
|
@ -200,6 +200,13 @@ typedef enum {
|
|||
HEX = 2
|
||||
} SEARCH_METHODS;
|
||||
|
||||
typedef enum {
|
||||
USE_FULL_RD = 0,
|
||||
USE_LARGESTINTRA,
|
||||
USE_LARGESTINTRA_MODELINTER,
|
||||
USE_LARGESTALL
|
||||
} TX_SIZE_SEARCH_METHOD;
|
||||
|
||||
typedef struct {
|
||||
int RD;
|
||||
SEARCH_METHODS search_method;
|
||||
|
@ -219,7 +226,7 @@ typedef struct {
|
|||
int adaptive_rd_thresh;
|
||||
int skip_encode_sb;
|
||||
int use_lastframe_partitioning;
|
||||
int use_largest_txform;
|
||||
TX_SIZE_SEARCH_METHOD tx_size_search_method;
|
||||
int use_8tap_always;
|
||||
int use_avoid_tested_higherror;
|
||||
int skip_lots_of_modes;
|
||||
|
@ -589,6 +596,8 @@ typedef struct VP9_COMP {
|
|||
[VP9_SWITCHABLE_FILTERS];
|
||||
unsigned int best_switchable_interp_count[VP9_SWITCHABLE_FILTERS];
|
||||
|
||||
unsigned int txfm_stepdown_count[TX_SIZE_MAX_SB];
|
||||
|
||||
int initial_width;
|
||||
int initial_height;
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче