[libvpx] Update to v1.12.0

This commit is contained in:
Andrey Volk committed 2026-07-10 19:38:46 +03:00
1 parent 287a71dc66
commit b5046d2a76
572 files changed
+52900 -29493

No files matched your search

File diff suppressed because it is too large. Load diff
@@ -21,6 +21,9 @@
// Compute the sum of all pixel differences of this MB.
static INLINE int horizontal_add_s8x16(const int8x16_t v_sum_diff_total) {
#if defined(__aarch64__)
return vaddlvq_s8(v_sum_diff_total);
#else
const int16x8_t fe_dc_ba_98_76_54_32_10 = vpaddlq_s8(v_sum_diff_total);
const int32x4_t fedc_ba98_7654_3210 = vpaddlq_s16(fe_dc_ba_98_76_54_32_10);
const int64x2_t fedcba98_76543210 = vpaddlq_s32(fedc_ba98_7654_3210);
@@ -28,6 +31,7 @@ static INLINE int horizontal_add_s8x16(const int8x16_t v_sum_diff_total) {
vget_low_s64(fedcba98_76543210));
const int sum_diff = vget_lane_s32(vreinterpret_s32_s64(x), 0);
return sum_diff;
#endif
}
// Denoise a 16x1 vector.
@@ -26,12 +26,27 @@
#include "vpx_dsp/arm/mem_neon.h"
#include "vpx_dsp/vpx_dsp_common.h"
static INLINE void calculate_dqcoeff_and_store(const int16x8_t qcoeff,
const int16x8_t dequant,
tran_low_t *dqcoeff) {
const int32x4_t dqcoeff_0 =
vmull_s16(vget_low_s16(qcoeff), vget_low_s16(dequant));
const int32x4_t dqcoeff_1 =
vmull_s16(vget_high_s16(qcoeff), vget_high_s16(dequant));
#if CONFIG_VP9_HIGHBITDEPTH
vst1q_s32(dqcoeff, dqcoeff_0);
vst1q_s32(dqcoeff + 4, dqcoeff_1);
#else
vst1q_s16(dqcoeff, vcombine_s16(vmovn_s32(dqcoeff_0), vmovn_s32(dqcoeff_1)));
#endif // CONFIG_VP9_HIGHBITDEPTH
}
void vp9_quantize_fp_neon(const tran_low_t *coeff_ptr, intptr_t count,
int skip_block, const int16_t *round_ptr,
const int16_t *quant_ptr, tran_low_t *qcoeff_ptr,
tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr,
uint16_t *eob_ptr, const int16_t *scan,
const int16_t *iscan) {
const int16_t *round_ptr, const int16_t *quant_ptr,
tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
const int16_t *dequant_ptr, uint16_t *eob_ptr,
const int16_t *scan, const int16_t *iscan) {
// Quantization pass: All coefficients with index >= zero_flag are
// skippable. Note: zero_flag can be zero.
int i;
@@ -43,8 +58,6 @@ void vp9_quantize_fp_neon(const tran_low_t *coeff_ptr, intptr_t count,
int16x8_t v_dequant = vmovq_n_s16(dequant_ptr[1]);
(void)scan;
(void)skip_block;
assert(!skip_block);
// adjust for dc
v_round = vsetq_lane_s16(round_ptr[0], v_round, 0);
@@ -55,7 +68,8 @@ void vp9_quantize_fp_neon(const tran_low_t *coeff_ptr, intptr_t count,
const int16x8_t v_iscan = vld1q_s16(&iscan[0]);
const int16x8_t v_coeff = load_tran_low_to_s16q(coeff_ptr);
const int16x8_t v_coeff_sign = vshrq_n_s16(v_coeff, 15);
const int16x8_t v_tmp = vabaq_s16(v_round, v_coeff, v_zero);
const int16x8_t v_abs = vabsq_s16(v_coeff);
const int16x8_t v_tmp = vqaddq_s16(v_abs, v_round);
const int32x4_t v_tmp_lo =
vmull_s16(vget_low_s16(v_tmp), vget_low_s16(v_quant));
const int32x4_t v_tmp_hi =
@@ -67,10 +81,9 @@ void vp9_quantize_fp_neon(const tran_low_t *coeff_ptr, intptr_t count,
const int16x8_t v_nz_iscan = vbslq_s16(v_nz_mask, v_zero, v_iscan_plus1);
const int16x8_t v_qcoeff_a = veorq_s16(v_tmp2, v_coeff_sign);
const int16x8_t v_qcoeff = vsubq_s16(v_qcoeff_a, v_coeff_sign);
const int16x8_t v_dqcoeff = vmulq_s16(v_qcoeff, v_dequant);
calculate_dqcoeff_and_store(v_qcoeff, v_dequant, dqcoeff_ptr);
v_eobmax_76543210 = vmaxq_s16(v_eobmax_76543210, v_nz_iscan);
store_s16q_to_tran_low(qcoeff_ptr, v_qcoeff);
store_s16q_to_tran_low(dqcoeff_ptr, v_dqcoeff);
v_round = vmovq_n_s16(round_ptr[1]);
v_quant = vmovq_n_s16(quant_ptr[1]);
v_dequant = vmovq_n_s16(dequant_ptr[1]);
@@ -80,7 +93,8 @@ void vp9_quantize_fp_neon(const tran_low_t *coeff_ptr, intptr_t count,
const int16x8_t v_iscan = vld1q_s16(&iscan[i]);
const int16x8_t v_coeff = load_tran_low_to_s16q(coeff_ptr + i);
const int16x8_t v_coeff_sign = vshrq_n_s16(v_coeff, 15);
const int16x8_t v_tmp = vabaq_s16(v_round, v_coeff, v_zero);
const int16x8_t v_abs = vabsq_s16(v_coeff);
const int16x8_t v_tmp = vqaddq_s16(v_abs, v_round);
const int32x4_t v_tmp_lo =
vmull_s16(vget_low_s16(v_tmp), vget_low_s16(v_quant));
const int32x4_t v_tmp_hi =
@@ -92,10 +106,9 @@ void vp9_quantize_fp_neon(const tran_low_t *coeff_ptr, intptr_t count,
const int16x8_t v_nz_iscan = vbslq_s16(v_nz_mask, v_zero, v_iscan_plus1);
const int16x8_t v_qcoeff_a = veorq_s16(v_tmp2, v_coeff_sign);
const int16x8_t v_qcoeff = vsubq_s16(v_qcoeff_a, v_coeff_sign);
const int16x8_t v_dqcoeff = vmulq_s16(v_qcoeff, v_dequant);
calculate_dqcoeff_and_store(v_qcoeff, v_dequant, dqcoeff_ptr + i);
v_eobmax_76543210 = vmaxq_s16(v_eobmax_76543210, v_nz_iscan);
store_s16q_to_tran_low(qcoeff_ptr + i, v_qcoeff);
store_s16q_to_tran_low(dqcoeff_ptr + i, v_dqcoeff);
}
#ifdef __aarch64__
*eob_ptr = vmaxvq_s16(v_eobmax_76543210);
@@ -122,7 +135,7 @@ static INLINE int32x4_t extract_sign_bit(int32x4_t a) {
}
void vp9_quantize_fp_32x32_neon(const tran_low_t *coeff_ptr, intptr_t count,
int skip_block, const int16_t *round_ptr,
const int16_t *round_ptr,
const int16_t *quant_ptr,
tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
const int16_t *dequant_ptr, uint16_t *eob_ptr,
@@ -146,14 +159,11 @@ void vp9_quantize_fp_32x32_neon(const tran_low_t *coeff_ptr, intptr_t count,
const int16x8_t dequant_mask =
vreinterpretq_s16_u16(vcgeq_s16(coeff_abs, dequant_thresh));
int16x8_t qcoeff = vaddq_s16(coeff_abs, round);
int16x8_t qcoeff = vqaddq_s16(coeff_abs, round);
int32x4_t dqcoeff_0, dqcoeff_1;
int16x8_t dqcoeff;
uint16x8_t eob_max;
(void)scan;
(void)count;
(void)skip_block;
assert(!skip_block);
// coeff * quant_ptr[]) >> 15
qcoeff = vqdmulhq_s16(qcoeff, quant);
@@ -170,13 +180,17 @@ void vp9_quantize_fp_32x32_neon(const tran_low_t *coeff_ptr, intptr_t count,
// Add 1 if negative to round towards zero because the C uses division.
dqcoeff_0 = vaddq_s32(dqcoeff_0, extract_sign_bit(dqcoeff_0));
dqcoeff_1 = vaddq_s32(dqcoeff_1, extract_sign_bit(dqcoeff_1));
dqcoeff = vcombine_s16(vshrn_n_s32(dqcoeff_0, 1), vshrn_n_s32(dqcoeff_1, 1));
#if CONFIG_VP9_HIGHBITDEPTH
vst1q_s32(dqcoeff_ptr, vshrq_n_s32(dqcoeff_0, 1));
vst1q_s32(dqcoeff_ptr + 4, vshrq_n_s32(dqcoeff_1, 1));
#else
store_s16q_to_tran_low(dqcoeff_ptr, vcombine_s16(vshrn_n_s32(dqcoeff_0, 1),
vshrn_n_s32(dqcoeff_1, 1)));
#endif
eob_max = vandq_u16(vtstq_s16(qcoeff, neg_one), v_iscan);
store_s16q_to_tran_low(qcoeff_ptr, qcoeff);
store_s16q_to_tran_low(dqcoeff_ptr, dqcoeff);
iscan += 8;
coeff_ptr += 8;
@@ -200,9 +214,8 @@ void vp9_quantize_fp_32x32_neon(const tran_low_t *coeff_ptr, intptr_t count,
const int16x8_t dequant_mask =
vreinterpretq_s16_u16(vcgeq_s16(coeff_abs, dequant_thresh));
int16x8_t qcoeff = vaddq_s16(coeff_abs, round);
int16x8_t qcoeff = vqaddq_s16(coeff_abs, round);
int32x4_t dqcoeff_0, dqcoeff_1;
int16x8_t dqcoeff;
qcoeff = vqdmulhq_s16(qcoeff, quant);
qcoeff = veorq_s16(qcoeff, coeff_sign);
@@ -215,14 +228,19 @@ void vp9_quantize_fp_32x32_neon(const tran_low_t *coeff_ptr, intptr_t count,
dqcoeff_0 = vaddq_s32(dqcoeff_0, extract_sign_bit(dqcoeff_0));
dqcoeff_1 = vaddq_s32(dqcoeff_1, extract_sign_bit(dqcoeff_1));
dqcoeff =
vcombine_s16(vshrn_n_s32(dqcoeff_0, 1), vshrn_n_s32(dqcoeff_1, 1));
#if CONFIG_VP9_HIGHBITDEPTH
vst1q_s32(dqcoeff_ptr, vshrq_n_s32(dqcoeff_0, 1));
vst1q_s32(dqcoeff_ptr + 4, vshrq_n_s32(dqcoeff_1, 1));
#else
store_s16q_to_tran_low(
dqcoeff_ptr,
vcombine_s16(vshrn_n_s32(dqcoeff_0, 1), vshrn_n_s32(dqcoeff_1, 1)));
#endif
eob_max =
vmaxq_u16(eob_max, vandq_u16(vtstq_s16(qcoeff, neg_one), v_iscan));
store_s16q_to_tran_low(qcoeff_ptr, qcoeff);
store_s16q_to_tran_low(dqcoeff_ptr, dqcoeff);
iscan += 8;
coeff_ptr += 8;
+5 -10
View File
@@ -39,11 +39,10 @@ static INLINE int16x8_t vec_max_across(int16x8_t a) {
}
void vp9_quantize_fp_vsx(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
int skip_block, const int16_t *round_ptr,
const int16_t *quant_ptr, tran_low_t *qcoeff_ptr,
tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr,
uint16_t *eob_ptr, const int16_t *scan,
const int16_t *iscan) {
const int16_t *round_ptr, const int16_t *quant_ptr,
tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
const int16_t *dequant_ptr, uint16_t *eob_ptr,
const int16_t *scan, const int16_t *iscan) {
int16x8_t qcoeff0, qcoeff1, dqcoeff0, dqcoeff1, eob;
bool16x8_t zero_coeff0, zero_coeff1;
@@ -56,8 +55,6 @@ void vp9_quantize_fp_vsx(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
int16x8_t scan1 = vec_vsx_ld(16, iscan);
(void)scan;
(void)skip_block;
assert(!skip_block);
// First set of 8 coeff starts with DC + 7 AC
qcoeff0 = vec_mulhi(vec_vaddshs(vec_abs(coeff0), round), quant);
@@ -165,7 +162,7 @@ static INLINE int16x8_t dequantize_coeff_32(int16x8_t qcoeff,
}
void vp9_quantize_fp_32x32_vsx(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
int skip_block, const int16_t *round_ptr,
const int16_t *round_ptr,
const int16_t *quant_ptr, tran_low_t *qcoeff_ptr,
tran_low_t *dqcoeff_ptr,
const int16_t *dequant_ptr, uint16_t *eob_ptr,
@@ -194,9 +191,7 @@ void vp9_quantize_fp_32x32_vsx(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
int16x8_t abs_coeff1 = vec_abs(coeff1);
(void)scan;
(void)skip_block;
(void)n_coeffs;
assert(!skip_block);
mask0 = vec_cmpge(abs_coeff0, thres);
round = vec_sra(vec_add(round, vec_ones_s16), vec_ones_u16);
+24 -9
View File
@@ -48,6 +48,7 @@ CYCLIC_REFRESH *vp9_cyclic_refresh_alloc(int mi_rows, int mi_cols) {
assert(MAXQ <= 255);
memset(cr->last_coded_q_map, MAXQ, last_coded_q_map_size);
cr->counter_encode_maxq_scene_change = 0;
cr->content_mode = 1;
return cr;
}
@@ -187,7 +188,8 @@ void vp9_cyclic_refresh_update_segment(VP9_COMP *const cpi, MODE_INFO *const mi,
// If this block is labeled for refresh, check if we should reset the
// segment_id.
if (cyclic_refresh_segment_id_boosted(mi->segment_id)) {
if (cpi->sf.use_nonrd_pick_mode &&
cyclic_refresh_segment_id_boosted(mi->segment_id)) {
mi->segment_id = refresh_this_block;
// Reset segment_id if it will be skipped.
if (skip) mi->segment_id = CR_SEGMENT_ID_BASE;
@@ -325,7 +327,8 @@ void vp9_cyclic_refresh_set_golden_update(VP9_COMP *const cpi) {
else
rc->baseline_gf_interval = 40;
if (cpi->oxcf.rc_mode == VPX_VBR) rc->baseline_gf_interval = 20;
if (rc->avg_frame_low_motion < 50 && rc->frames_since_key > 40)
if (rc->avg_frame_low_motion < 50 && rc->frames_since_key > 40 &&
cr->content_mode)
rc->baseline_gf_interval = 10;
}
@@ -387,7 +390,8 @@ static void cyclic_refresh_update_map(VP9_COMP *const cpi) {
? vp9_get_qindex(&cm->seg, CR_SEGMENT_ID_BOOST2, cm->base_qindex)
: vp9_get_qindex(&cm->seg, CR_SEGMENT_ID_BOOST1, cm->base_qindex);
// More aggressive settings for noisy content.
if (cpi->noise_estimate.enabled && cpi->noise_estimate.level >= kMedium) {
if (cpi->noise_estimate.enabled && cpi->noise_estimate.level >= kMedium &&
cr->content_mode) {
consec_zero_mv_thresh = 60;
qindex_thresh =
VPXMAX(vp9_get_qindex(&cm->seg, CR_SEGMENT_ID_BOOST1, cm->base_qindex),
@@ -408,7 +412,7 @@ static void cyclic_refresh_update_map(VP9_COMP *const cpi) {
#if CONFIG_VP9_HIGHBITDEPTH
if (cpi->common.use_highbitdepth) compute_content = 0;
#endif
if (cpi->Last_Source == NULL ||
if (cr->content_mode == 0 || cpi->Last_Source == NULL ||
cpi->Last_Source->y_width != cpi->Source->y_width ||
cpi->Last_Source->y_height != cpi->Source->y_height)
compute_content = 0;
@@ -429,7 +433,8 @@ static void cyclic_refresh_update_map(VP9_COMP *const cpi) {
// reset to 0 later depending on the coding mode.
if (cr->map[bl_index2] == 0) {
count_tot++;
if (cr->last_coded_q_map[bl_index2] > qindex_thresh ||
if (cr->content_mode == 0 ||
cr->last_coded_q_map[bl_index2] > qindex_thresh ||
cpi->consec_zero_mv[bl_index2] < consec_zero_mv_thresh_block) {
sum_map++;
count_sel++;
@@ -488,10 +493,13 @@ void vp9_cyclic_refresh_update_parameters(VP9_COMP *const cpi) {
rc->avg_frame_qindex[INTER_FRAME] < qp_thresh ||
(cpi->use_svc &&
cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame) ||
(!cpi->use_svc && rc->avg_frame_low_motion < thresh_low_motion &&
(!cpi->use_svc && cr->content_mode &&
rc->avg_frame_low_motion < thresh_low_motion &&
rc->frames_since_key > 40) ||
(!cpi->use_svc && rc->avg_frame_qindex[INTER_FRAME] > qp_max_thresh &&
rc->frames_since_key > 20)) {
rc->frames_since_key > 20) ||
(cpi->roi.enabled && cpi->roi.skip[BACKGROUND_SEG_SKIP_ID] &&
rc->frames_since_key > FRAMES_NO_SKIPPING_AFTER_KEY)) {
cr->apply_cyclic_refresh = 0;
return;
}
@@ -510,7 +518,8 @@ void vp9_cyclic_refresh_update_parameters(VP9_COMP *const cpi) {
cr->rate_ratio_qdelta = 3.0;
} else {
cr->rate_ratio_qdelta = 2.0;
if (cpi->noise_estimate.enabled && cpi->noise_estimate.level >= kMedium) {
if (cr->content_mode && cpi->noise_estimate.enabled &&
cpi->noise_estimate.level >= kMedium) {
// Reduce the delta-qp if the estimated source noise is above threshold.
cr->rate_ratio_qdelta = 1.7;
cr->rate_boost_fac = 13;
@@ -527,7 +536,7 @@ void vp9_cyclic_refresh_update_parameters(VP9_COMP *const cpi) {
cr->percent_refresh = (cr->skip_flat_static_blocks) ? 5 : 10;
// Increase the amount of refresh on scene change that is encoded at max Q,
// increase for a few cycles of the refresh period (~100 / percent_refresh).
if (cr->counter_encode_maxq_scene_change < 30)
if (cr->content_mode && cr->counter_encode_maxq_scene_change < 30)
cr->percent_refresh = (cr->skip_flat_static_blocks) ? 10 : 15;
cr->rate_ratio_qdelta = 2.0;
cr->rate_boost_fac = 10;
@@ -574,6 +583,12 @@ void vp9_cyclic_refresh_update_parameters(VP9_COMP *const cpi) {
(double)(cr->actual_num_seg1_blocks + cr->actual_num_seg2_blocks) /
num8x8bl;
cr->weight_segment = weight_segment;
if (cr->content_mode == 0) {
cr->actual_num_seg1_blocks =
cr->percent_refresh * cm->mi_rows * cm->mi_cols / 100;
cr->actual_num_seg2_blocks = 0;
cr->weight_segment = (double)(cr->actual_num_seg1_blocks) / num8x8bl;
}
}
// Setup cyclic background refresh: set delta q and segmentation map.
@@ -70,6 +70,7 @@ struct CYCLIC_REFRESH {
int apply_cyclic_refresh;
int counter_encode_maxq_scene_change;
int skip_flat_static_blocks;
int content_mode;
};
struct VP9_COMP;
+28 -13
View File
@@ -186,6 +186,17 @@ double vp9_log_block_var(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs) {
return log(var + 1.0);
}
#define DEFAULT_E_MIDPOINT 10.0
static int scale_block_energy(VP9_COMP *cpi, unsigned int block_var) {
double energy;
double energy_midpoint;
energy_midpoint =
(cpi->oxcf.pass == 2) ? cpi->twopass.mb_av_energy : DEFAULT_E_MIDPOINT;
energy = log(block_var + 1.0) - energy_midpoint;
return clamp((int)round(energy), ENERGY_MIN, ENERGY_MAX);
}
#undef DEFAULT_E_MIDPOINT
// Get the range of sub block energy values;
void vp9_get_sub_block_energy(VP9_COMP *cpi, MACROBLOCK *mb, int mi_row,
int mi_col, BLOCK_SIZE bsize, int *min_e,
@@ -202,31 +213,35 @@ void vp9_get_sub_block_energy(VP9_COMP *cpi, MACROBLOCK *mb, int mi_row,
*min_e = vp9_block_energy(cpi, mb, bsize);
*max_e = *min_e;
} else {
int energy;
*min_e = ENERGY_MAX;
*max_e = ENERGY_MIN;
unsigned int var;
// Because scale_block_energy is non-decreasing, we can find the min/max
// block variance and scale afterwards. This avoids a costly scaling at
// every iteration.
unsigned int min_var = UINT_MAX;
unsigned int max_var = 0;
for (y = 0; y < ymis; ++y) {
for (x = 0; x < xmis; ++x) {
vp9_setup_src_planes(mb, cpi->Source, mi_row + y, mi_col + x);
energy = vp9_block_energy(cpi, mb, BLOCK_8X8);
*min_e = VPXMIN(*min_e, energy);
*max_e = VPXMAX(*max_e, energy);
vpx_clear_system_state();
var = block_variance(cpi, mb, BLOCK_8X8);
vpx_clear_system_state();
min_var = VPXMIN(min_var, var);
max_var = VPXMAX(max_var, var);
}
}
*min_e = scale_block_energy(cpi, min_var);
*max_e = scale_block_energy(cpi, max_var);
}
// Re-instate source pointers back to what they should have been on entry.
vp9_setup_src_planes(mb, cpi->Source, mi_row, mi_col);
}
#define DEFAULT_E_MIDPOINT 10.0
int vp9_block_energy(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs) {
double energy;
double energy_midpoint;
unsigned int var;
vpx_clear_system_state();
energy_midpoint =
(cpi->oxcf.pass == 2) ? cpi->twopass.mb_av_energy : DEFAULT_E_MIDPOINT;
energy = vp9_log_block_var(cpi, x, bs) - energy_midpoint;
return clamp((int)round(energy), ENERGY_MIN, ENERGY_MAX);
var = block_variance(cpi, x, bs);
vpx_clear_system_state();
return scale_block_energy(cpi, var);
}
+32 -33
View File
@@ -236,11 +236,11 @@ static void write_ref_frames(const VP9_COMMON *cm, const MACROBLOCKD *const xd,
}
}
static void pack_inter_mode_mvs(
VP9_COMP *cpi, const MACROBLOCKD *const xd,
const MB_MODE_INFO_EXT *const mbmi_ext, vpx_writer *w,
unsigned int *const max_mv_magnitude,
int interp_filter_selected[MAX_REF_FRAMES][SWITCHABLE]) {
static void pack_inter_mode_mvs(VP9_COMP *cpi, const MACROBLOCKD *const xd,
const MB_MODE_INFO_EXT *const mbmi_ext,
vpx_writer *w,
unsigned int *const max_mv_magnitude,
int interp_filter_selected[][SWITCHABLE]) {
VP9_COMMON *const cm = &cpi->common;
const nmv_context *nmvc = &cm->fc->nmvc;
const struct segmentation *const seg = &cm->seg;
@@ -373,11 +373,12 @@ static void write_mb_modes_kf(const VP9_COMMON *cm, const MACROBLOCKD *xd,
write_intra_mode(w, mi->uv_mode, vp9_kf_uv_mode_prob[mi->mode]);
}
static void write_modes_b(
VP9_COMP *cpi, MACROBLOCKD *const xd, const TileInfo *const tile,
vpx_writer *w, TOKENEXTRA **tok, const TOKENEXTRA *const tok_end,
int mi_row, int mi_col, unsigned int *const max_mv_magnitude,
int interp_filter_selected[MAX_REF_FRAMES][SWITCHABLE]) {
static void write_modes_b(VP9_COMP *cpi, MACROBLOCKD *const xd,
const TileInfo *const tile, vpx_writer *w,
TOKENEXTRA **tok, const TOKENEXTRA *const tok_end,
int mi_row, int mi_col,
unsigned int *const max_mv_magnitude,
int interp_filter_selected[][SWITCHABLE]) {
const VP9_COMMON *const cm = &cpi->common;
const MB_MODE_INFO_EXT *const mbmi_ext =
cpi->td.mb.mbmi_ext_base + (mi_row * cm->mi_cols + mi_col);
@@ -422,12 +423,12 @@ static void write_partition(const VP9_COMMON *const cm,
}
}
static void write_modes_sb(
VP9_COMP *cpi, MACROBLOCKD *const xd, const TileInfo *const tile,
vpx_writer *w, TOKENEXTRA **tok, const TOKENEXTRA *const tok_end,
int mi_row, int mi_col, BLOCK_SIZE bsize,
unsigned int *const max_mv_magnitude,
int interp_filter_selected[MAX_REF_FRAMES][SWITCHABLE]) {
static void write_modes_sb(VP9_COMP *cpi, MACROBLOCKD *const xd,
const TileInfo *const tile, vpx_writer *w,
TOKENEXTRA **tok, const TOKENEXTRA *const tok_end,
int mi_row, int mi_col, BLOCK_SIZE bsize,
unsigned int *const max_mv_magnitude,
int interp_filter_selected[][SWITCHABLE]) {
const VP9_COMMON *const cm = &cpi->common;
const int bsl = b_width_log2_lookup[bsize];
const int bs = (1 << bsl) / 4;
@@ -485,11 +486,10 @@ static void write_modes_sb(
update_partition_context(xd, mi_row, mi_col, subsize, bsize);
}
static void write_modes(
VP9_COMP *cpi, MACROBLOCKD *const xd, const TileInfo *const tile,
vpx_writer *w, int tile_row, int tile_col,
unsigned int *const max_mv_magnitude,
int interp_filter_selected[MAX_REF_FRAMES][SWITCHABLE]) {
static void write_modes(VP9_COMP *cpi, MACROBLOCKD *const xd,
const TileInfo *const tile, vpx_writer *w, int tile_row,
int tile_col, unsigned int *const max_mv_magnitude,
int interp_filter_selected[][SWITCHABLE]) {
const VP9_COMMON *const cm = &cpi->common;
int mi_row, mi_col, tile_sb_row;
TOKENEXTRA *tok = NULL;
@@ -554,7 +554,7 @@ static void update_coef_probs_common(vpx_writer *const bc, VP9_COMP *cpi,
switch (cpi->sf.use_fast_coef_updates) {
case TWO_LOOP: {
/* dry run to see if there is any update at all needed */
int savings = 0;
int64_t savings = 0;
int update[2] = { 0, 0 };
for (i = 0; i < PLANE_TYPES; ++i) {
for (j = 0; j < REF_TYPES; ++j) {
@@ -563,7 +563,7 @@ static void update_coef_probs_common(vpx_writer *const bc, VP9_COMP *cpi,
for (t = 0; t < entropy_nodes_update; ++t) {
vpx_prob newp = new_coef_probs[i][j][k][l][t];
const vpx_prob oldp = old_coef_probs[i][j][k][l][t];
int s;
int64_t s;
int u = 0;
if (t == PIVOT_NODE)
s = vp9_prob_diff_update_savings_search_model(
@@ -600,7 +600,7 @@ static void update_coef_probs_common(vpx_writer *const bc, VP9_COMP *cpi,
vpx_prob newp = new_coef_probs[i][j][k][l][t];
vpx_prob *oldp = old_coef_probs[i][j][k][l] + t;
const vpx_prob upd = DIFF_UPDATE_PROB;
int s;
int64_t s;
int u = 0;
if (t == PIVOT_NODE)
s = vp9_prob_diff_update_savings_search_model(
@@ -636,7 +636,7 @@ static void update_coef_probs_common(vpx_writer *const bc, VP9_COMP *cpi,
for (t = 0; t < entropy_nodes_update; ++t) {
vpx_prob newp = new_coef_probs[i][j][k][l][t];
vpx_prob *oldp = old_coef_probs[i][j][k][l] + t;
int s;
int64_t s;
int u = 0;
if (t == PIVOT_NODE) {
@@ -963,21 +963,20 @@ void vp9_bitstream_encode_tiles_buffer_dealloc(VP9_COMP *const cpi) {
}
}
static int encode_tiles_buffer_alloc(VP9_COMP *const cpi) {
static void encode_tiles_buffer_alloc(VP9_COMP *const cpi) {
VP9_COMMON *const cm = &cpi->common;
int i;
const size_t worker_data_size =
cpi->num_workers * sizeof(*cpi->vp9_bitstream_worker_data);
cpi->vp9_bitstream_worker_data = vpx_memalign(16, worker_data_size);
CHECK_MEM_ERROR(cm, cpi->vp9_bitstream_worker_data,
vpx_memalign(16, worker_data_size));
memset(cpi->vp9_bitstream_worker_data, 0, worker_data_size);
if (!cpi->vp9_bitstream_worker_data) return 1;
for (i = 1; i < cpi->num_workers; ++i) {
cpi->vp9_bitstream_worker_data[i].dest_size =
cpi->oxcf.width * cpi->oxcf.height;
cpi->vp9_bitstream_worker_data[i].dest =
vpx_malloc(cpi->vp9_bitstream_worker_data[i].dest_size);
if (!cpi->vp9_bitstream_worker_data[i].dest) return 1;
CHECK_MEM_ERROR(cm, cpi->vp9_bitstream_worker_data[i].dest,
vpx_malloc(cpi->vp9_bitstream_worker_data[i].dest_size));
}
return 0;
}
static size_t encode_tiles_mt(VP9_COMP *cpi, uint8_t *data_ptr) {
@@ -992,7 +991,7 @@ static size_t encode_tiles_mt(VP9_COMP *cpi, uint8_t *data_ptr) {
cpi->vp9_bitstream_worker_data[1].dest_size >
(cpi->oxcf.width * cpi->oxcf.height)) {
vp9_bitstream_encode_tiles_buffer_dealloc(cpi);
if (encode_tiles_buffer_alloc(cpi)) return 0;
encode_tiles_buffer_alloc(cpi);
}
while (tile_col < tile_cols) {
+3
View File
@@ -157,6 +157,9 @@ struct macroblock {
// skip forward transform and quantization
uint8_t skip_txfm[MAX_MB_PLANE << 2];
#define SKIP_TXFM_NONE 0
// TODO(chengchen): consider remove SKIP_TXFM_AC_DC from vp9 completely
// since it increases risks of bad perceptual quality.
// https://crbug.com/webm/1729
#define SKIP_TXFM_AC_DC 1
#define SKIP_TXFM_AC_ONLY 2
+2 -3
View File
@@ -29,9 +29,8 @@ extern const uint16_t vp9_prob_cost[256];
#define vp9_cost_bit(prob, bit) vp9_cost_zero((bit) ? 256 - (prob) : (prob))
static INLINE unsigned int cost_branch256(const unsigned int ct[2],
vpx_prob p) {
return ct[0] * vp9_cost_zero(p) + ct[1] * vp9_cost_one(p);
static INLINE uint64_t cost_branch256(const unsigned int ct[2], vpx_prob p) {
return (uint64_t)ct[0] * vp9_cost_zero(p) + (uint64_t)ct[1] * vp9_cost_one(p);
}
static INLINE int treed_cost(vpx_tree tree, const vpx_prob *probs, int bits,
+337 -276
View File
@@ -159,37 +159,6 @@ unsigned int vp9_high_get_sby_perpixel_variance(VP9_COMP *cpi,
}
#endif // CONFIG_VP9_HIGHBITDEPTH
#if !CONFIG_REALTIME_ONLY
static unsigned int get_sby_perpixel_diff_variance(VP9_COMP *cpi,
const struct buf_2d *ref,
int mi_row, int mi_col,
BLOCK_SIZE bs) {
unsigned int sse, var;
uint8_t *last_y;
const YV12_BUFFER_CONFIG *last = get_ref_frame_buffer(cpi, LAST_FRAME);
assert(last != NULL);
last_y =
&last->y_buffer[mi_row * MI_SIZE * last->y_stride + mi_col * MI_SIZE];
var = cpi->fn_ptr[bs].vf(ref->buf, ref->stride, last_y, last->y_stride, &sse);
return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
}
static BLOCK_SIZE get_rd_var_based_fixed_partition(VP9_COMP *cpi, MACROBLOCK *x,
int mi_row, int mi_col) {
unsigned int var = get_sby_perpixel_diff_variance(
cpi, &x->plane[0].src, mi_row, mi_col, BLOCK_64X64);
if (var < 8)
return BLOCK_64X64;
else if (var < 128)
return BLOCK_32X32;
else if (var < 2048)
return BLOCK_16X16;
else
return BLOCK_8X8;
}
#endif // !CONFIG_REALTIME_ONLY
static void set_segment_index(VP9_COMP *cpi, MACROBLOCK *const x, int mi_row,
int mi_col, BLOCK_SIZE bsize, int segment_index) {
VP9_COMMON *const cm = &cpi->common;
@@ -248,8 +217,8 @@ static void set_segment_index(VP9_COMP *cpi, MACROBLOCK *const x, int mi_row,
break;
}
// Set segment index from ROI map if it's enabled.
if (cpi->roi.enabled)
// Set segment index if ROI map or active_map is enabled.
if (cpi->roi.enabled || cpi->active_map.enabled)
mi->segment_id = get_segment_id(cm, map, bsize, mi_row, mi_col);
vp9_init_plane_quantizers(cpi, x);
@@ -649,6 +618,10 @@ static void set_vbp_thresholds(VP9_COMP *cpi, int64_t thresholds[], int q,
thresholds[0] = threshold_base >> 3;
thresholds[1] = threshold_base >> 1;
thresholds[2] = threshold_base << 3;
if (cpi->rc.avg_frame_qindex[INTER_FRAME] > 220)
thresholds[2] = thresholds[2] << 2;
else if (cpi->rc.avg_frame_qindex[INTER_FRAME] > 200)
thresholds[2] = thresholds[2] << 1;
} else if (cm->width < 1280 && cm->height < 720) {
thresholds[1] = (5 * threshold_base) >> 2;
} else if (cm->width < 1920 && cm->height < 1080) {
@@ -811,8 +784,8 @@ static void fill_variance_8x8avg(const uint8_t *s, int sp, const uint8_t *d,
// Check if most of the superblock is skin content, and if so, force split to
// 32x32, and set x->sb_is_skin for use in mode selection.
static int skin_sb_split(VP9_COMP *cpi, MACROBLOCK *x, const int low_res,
int mi_row, int mi_col, int *force_split) {
static int skin_sb_split(VP9_COMP *cpi, const int low_res, int mi_row,
int mi_col, int *force_split) {
VP9_COMMON *const cm = &cpi->common;
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth) return 0;
@@ -824,11 +797,6 @@ static int skin_sb_split(VP9_COMP *cpi, MACROBLOCK *x, const int low_res,
mi_row + 8 < cm->mi_rows)) {
int num_16x16_skin = 0;
int num_16x16_nonskin = 0;
uint8_t *ysignal = x->plane[0].src.buf;
uint8_t *usignal = x->plane[1].src.buf;
uint8_t *vsignal = x->plane[2].src.buf;
int sp = x->plane[0].src.stride;
int spuv = x->plane[1].src.stride;
const int block_index = mi_row * cm->mi_cols + mi_col;
const int bw = num_8x8_blocks_wide_lookup[BLOCK_64X64];
const int bh = num_8x8_blocks_high_lookup[BLOCK_64X64];
@@ -847,13 +815,7 @@ static int skin_sb_split(VP9_COMP *cpi, MACROBLOCK *x, const int low_res,
i = ymis;
break;
}
ysignal += 16;
usignal += 8;
vsignal += 8;
}
ysignal += (sp << 4) - 64;
usignal += (spuv << 3) - 32;
vsignal += (spuv << 3) - 32;
}
if (num_16x16_skin > 12) {
*force_split = 1;
@@ -1208,20 +1170,25 @@ static void update_prev_partition(VP9_COMP *cpi, MACROBLOCK *x, int segment_id,
}
static void chroma_check(VP9_COMP *cpi, MACROBLOCK *x, int bsize,
unsigned int y_sad, int is_key_frame) {
unsigned int y_sad, int is_key_frame,
int scene_change_detected) {
int i;
MACROBLOCKD *xd = &x->e_mbd;
int shift = 2;
if (is_key_frame) return;
// For speed >= 8, avoid the chroma check if y_sad is above threshold.
if (cpi->oxcf.speed >= 8) {
// For speed > 8, avoid the chroma check if y_sad is above threshold.
if (cpi->oxcf.speed > 8) {
if (y_sad > cpi->vbp_thresholds[1] &&
(!cpi->noise_estimate.enabled ||
vp9_noise_estimate_extract_level(&cpi->noise_estimate) < kMedium))
return;
}
if (cpi->oxcf.content == VP9E_CONTENT_SCREEN && scene_change_detected)
shift = 5;
for (i = 1; i <= 2; ++i) {
unsigned int uv_sad = UINT_MAX;
struct macroblock_plane *p = &x->plane[i];
@@ -1234,7 +1201,7 @@ static void chroma_check(VP9_COMP *cpi, MACROBLOCK *x, int bsize,
// TODO(marpan): Investigate if we should lower this threshold if
// superblock is detected as skin.
x->color_sensitivity[i - 1] = uv_sad > (y_sad >> 2);
x->color_sensitivity[i - 1] = uv_sad > (y_sad >> shift);
}
}
@@ -1320,8 +1287,10 @@ static int choose_partitioning(VP9_COMP *cpi, const TileInfo *const tile,
int pixels_wide = 64, pixels_high = 64;
int64_t thresholds[4] = { cpi->vbp_thresholds[0], cpi->vbp_thresholds[1],
cpi->vbp_thresholds[2], cpi->vbp_thresholds[3] };
int force_64_split = cpi->rc.high_source_sad ||
(cpi->use_svc && cpi->svc.high_source_sad_superframe) ||
int scene_change_detected =
cpi->rc.high_source_sad ||
(cpi->use_svc && cpi->svc.high_source_sad_superframe);
int force_64_split = scene_change_detected ||
(cpi->oxcf.content == VP9E_CONTENT_SCREEN &&
cpi->compute_source_sad_onepass &&
cpi->sf.use_source_sad && !x->zero_temp_sad_source);
@@ -1523,8 +1492,7 @@ static int choose_partitioning(VP9_COMP *cpi, const TileInfo *const tile,
vp9_build_inter_predictors_sb(xd, mi_row, mi_col, BLOCK_64X64);
if (cpi->use_skin_detection)
x->sb_is_skin =
skin_sb_split(cpi, x, low_res, mi_row, mi_col, force_split);
x->sb_is_skin = skin_sb_split(cpi, low_res, mi_row, mi_col, force_split);
d = xd->plane[0].dst.buf;
dp = xd->plane[0].dst.stride;
@@ -1538,7 +1506,7 @@ static int choose_partitioning(VP9_COMP *cpi, const TileInfo *const tile,
mi_row + block_height / 2 < cm->mi_rows) {
set_block_size(cpi, x, xd, mi_row, mi_col, BLOCK_64X64);
x->variance_low[0] = 1;
chroma_check(cpi, x, bsize, y_sad, is_key_frame);
chroma_check(cpi, x, bsize, y_sad, is_key_frame, scene_change_detected);
if (cpi->sf.svc_use_lowres_part &&
cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 2)
update_partition_svc(cpi, BLOCK_64X64, mi_row, mi_col);
@@ -1555,7 +1523,7 @@ static int choose_partitioning(VP9_COMP *cpi, const TileInfo *const tile,
// TODO(jianj) : tune the threshold.
if (cpi->sf.copy_partition_flag && y_sad_last < cpi->vbp_threshold_copy &&
copy_partitioning(cpi, x, xd, mi_row, mi_col, segment_id, sb_offset)) {
chroma_check(cpi, x, bsize, y_sad, is_key_frame);
chroma_check(cpi, x, bsize, y_sad, is_key_frame, scene_change_detected);
if (cpi->sf.svc_use_lowres_part &&
cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 2)
update_partition_svc(cpi, BLOCK_64X64, mi_row, mi_col);
@@ -1784,7 +1752,7 @@ static int choose_partitioning(VP9_COMP *cpi, const TileInfo *const tile,
mi_col, mi_row);
}
chroma_check(cpi, x, bsize, y_sad, is_key_frame);
chroma_check(cpi, x, bsize, y_sad, is_key_frame, scene_change_detected);
if (vt2) vpx_free(vt2);
return 0;
}
@@ -1831,7 +1799,8 @@ static void update_state(VP9_COMP *cpi, ThreadData *td, PICK_MODE_CONTEXT *ctx,
}
// Else for cyclic refresh mode update the segment map, set the segment id
// and then update the quantizer.
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) {
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
cpi->cyclic_refresh->content_mode) {
vp9_cyclic_refresh_update_segment(cpi, xd->mi[0], mi_row, mi_col, bsize,
ctx->rate, ctx->dist, x->skip, p);
}
@@ -1936,13 +1905,17 @@ void vp9_setup_src_planes(MACROBLOCK *x, const YV12_BUFFER_CONFIG *src,
}
static void set_mode_info_seg_skip(MACROBLOCK *x, TX_MODE tx_mode,
INTERP_FILTER interp_filter,
RD_COST *rd_cost, BLOCK_SIZE bsize) {
MACROBLOCKD *const xd = &x->e_mbd;
MODE_INFO *const mi = xd->mi[0];
INTERP_FILTER filter_ref;
filter_ref = get_pred_context_switchable_interp(xd);
if (filter_ref == SWITCHABLE_FILTERS) filter_ref = EIGHTTAP;
if (interp_filter == BILINEAR)
filter_ref = BILINEAR;
else if (filter_ref == SWITCHABLE_FILTERS)
filter_ref = EIGHTTAP;
mi->sb_type = bsize;
mi->mode = ZEROMV;
@@ -2526,9 +2499,11 @@ static void update_state_rt(VP9_COMP *cpi, ThreadData *td,
*(xd->mi[0]) = ctx->mic;
*(x->mbmi_ext) = ctx->mbmi_ext;
if (seg->enabled && (cpi->oxcf.aq_mode != NO_AQ || cpi->roi.enabled)) {
if (seg->enabled && (cpi->oxcf.aq_mode != NO_AQ || cpi->roi.enabled ||
cpi->active_map.enabled)) {
// Setting segmentation map for cyclic_refresh.
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) {
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
cpi->cyclic_refresh->content_mode) {
vp9_cyclic_refresh_update_segment(cpi, mi, mi_row, mi_col, bsize,
ctx->rate, ctx->dist, x->skip, p);
} else {
@@ -3108,54 +3083,6 @@ static INLINE void load_pred_mv(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx) {
memcpy(x->pred_mv, ctx->pred_mv, sizeof(x->pred_mv));
}
#if CONFIG_FP_MB_STATS
const int num_16x16_blocks_wide_lookup[BLOCK_SIZES] = { 1, 1, 1, 1, 1, 1, 1,
1, 2, 2, 2, 4, 4 };
const int num_16x16_blocks_high_lookup[BLOCK_SIZES] = { 1, 1, 1, 1, 1, 1, 1,
2, 1, 2, 4, 2, 4 };
const int qindex_skip_threshold_lookup[BLOCK_SIZES] = { 0, 10, 10, 30, 40,
40, 60, 80, 80, 90,
100, 100, 120 };
const int qindex_split_threshold_lookup[BLOCK_SIZES] = { 0, 3, 3, 7, 15,
15, 30, 40, 40, 60,
80, 80, 120 };
const int complexity_16x16_blocks_threshold[BLOCK_SIZES] = { 1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
4, 4, 6 };
typedef enum {
MV_ZERO = 0,
MV_LEFT = 1,
MV_UP = 2,
MV_RIGHT = 3,
MV_DOWN = 4,
MV_INVALID
} MOTION_DIRECTION;
static INLINE MOTION_DIRECTION get_motion_direction_fp(uint8_t fp_byte) {
if (fp_byte & FPMB_MOTION_ZERO_MASK) {
return MV_ZERO;
} else if (fp_byte & FPMB_MOTION_LEFT_MASK) {
return MV_LEFT;
} else if (fp_byte & FPMB_MOTION_RIGHT_MASK) {
return MV_RIGHT;
} else if (fp_byte & FPMB_MOTION_UP_MASK) {
return MV_UP;
} else {
return MV_DOWN;
}
}
static INLINE int get_motion_inconsistency(MOTION_DIRECTION this_mv,
MOTION_DIRECTION that_mv) {
if (this_mv == that_mv) {
return 0;
} else {
return abs(this_mv - that_mv) == 2 ? 2 : 1;
}
}
#endif
// Calculate prediction based on the given input features and neural net config.
// Assume there are no more than NN_MAX_NODES_PER_LAYER nodes in each hidden
// layer.
@@ -3755,9 +3682,6 @@ static int wiener_var_segment(VP9_COMP *cpi, BLOCK_SIZE bsize, int mi_row,
static int get_rdmult_delta(VP9_COMP *cpi, BLOCK_SIZE bsize, int mi_row,
int mi_col, int orig_rdmult) {
const int gf_group_index = cpi->twopass.gf_group.index;
TplDepFrame *tpl_frame = &cpi->tpl_stats[gf_group_index];
TplDepStats *tpl_stats = tpl_frame->tpl_stats_ptr;
int tpl_stride = tpl_frame->stride;
int64_t intra_cost = 0;
int64_t mc_dep_cost = 0;
int mi_wide = num_8x8_blocks_wide_lookup[bsize];
@@ -3768,11 +3692,18 @@ static int get_rdmult_delta(VP9_COMP *cpi, BLOCK_SIZE bsize, int mi_row,
int count = 0;
double r0, rk, beta;
if (tpl_frame->is_valid == 0) return orig_rdmult;
if (cpi->twopass.gf_group.layer_depth[gf_group_index] > 1) return orig_rdmult;
TplDepFrame *tpl_frame;
TplDepStats *tpl_stats;
int tpl_stride;
if (gf_group_index >= MAX_ARF_GOP_SIZE) return orig_rdmult;
tpl_frame = &cpi->tpl_stats[gf_group_index];
if (tpl_frame->is_valid == 0) return orig_rdmult;
tpl_stats = tpl_frame->tpl_stats_ptr;
tpl_stride = tpl_frame->stride;
if (cpi->twopass.gf_group.layer_depth[gf_group_index] > 1) return orig_rdmult;
for (row = mi_row; row < mi_row + mi_high; ++row) {
for (col = mi_col; col < mi_col + mi_wide; ++col) {
@@ -3803,6 +3734,216 @@ static int get_rdmult_delta(VP9_COMP *cpi, BLOCK_SIZE bsize, int mi_row,
}
#endif // !CONFIG_REALTIME_ONLY
#if CONFIG_RATE_CTRL
static void assign_partition_info(
const int row_start_4x4, const int col_start_4x4, const int block_width_4x4,
const int block_height_4x4, const int num_unit_rows,
const int num_unit_cols, PARTITION_INFO *partition_info) {
int i, j;
for (i = 0; i < block_height_4x4; ++i) {
for (j = 0; j < block_width_4x4; ++j) {
const int row_4x4 = row_start_4x4 + i;
const int col_4x4 = col_start_4x4 + j;
const int unit_index = row_4x4 * num_unit_cols + col_4x4;
if (row_4x4 >= num_unit_rows || col_4x4 >= num_unit_cols) continue;
partition_info[unit_index].row = row_4x4 << 2;
partition_info[unit_index].column = col_4x4 << 2;
partition_info[unit_index].row_start = row_start_4x4 << 2;
partition_info[unit_index].column_start = col_start_4x4 << 2;
partition_info[unit_index].width = block_width_4x4 << 2;
partition_info[unit_index].height = block_height_4x4 << 2;
}
}
}
static void assign_motion_vector_info(const int block_width_4x4,
const int block_height_4x4,
const int row_start_4x4,
const int col_start_4x4,
const int num_unit_rows,
const int num_unit_cols, MV *source_mv[2],
MV_REFERENCE_FRAME source_ref_frame[2],
MOTION_VECTOR_INFO *motion_vector_info) {
int i, j;
for (i = 0; i < block_height_4x4; ++i) {
for (j = 0; j < block_width_4x4; ++j) {
const int row_4x4 = row_start_4x4 + i;
const int col_4x4 = col_start_4x4 + j;
const int unit_index = row_4x4 * num_unit_cols + col_4x4;
if (row_4x4 >= num_unit_rows || col_4x4 >= num_unit_cols) continue;
if (source_ref_frame[1] == NONE) {
assert(source_mv[1]->row == 0 && source_mv[1]->col == 0);
}
motion_vector_info[unit_index].ref_frame[0] = source_ref_frame[0];
motion_vector_info[unit_index].ref_frame[1] = source_ref_frame[1];
motion_vector_info[unit_index].mv[0].as_mv.row = source_mv[0]->row;
motion_vector_info[unit_index].mv[0].as_mv.col = source_mv[0]->col;
motion_vector_info[unit_index].mv[1].as_mv.row = source_mv[1]->row;
motion_vector_info[unit_index].mv[1].as_mv.col = source_mv[1]->col;
}
}
}
static void store_superblock_info(
const PC_TREE *const pc_tree, MODE_INFO **mi_grid_visible,
const int mi_stride, const int square_size_4x4, const int num_unit_rows,
const int num_unit_cols, const int row_start_4x4, const int col_start_4x4,
PARTITION_INFO *partition_info, MOTION_VECTOR_INFO *motion_vector_info) {
const int subblock_square_size_4x4 = square_size_4x4 >> 1;
if (row_start_4x4 >= num_unit_rows || col_start_4x4 >= num_unit_cols) return;
assert(pc_tree->partitioning != PARTITION_INVALID);
// End node, no split.
if (pc_tree->partitioning == PARTITION_NONE ||
pc_tree->partitioning == PARTITION_HORZ ||
pc_tree->partitioning == PARTITION_VERT || square_size_4x4 == 1) {
const int mi_row = row_start_4x4 >> 1;
const int mi_col = col_start_4x4 >> 1;
const int mi_idx = mi_stride * mi_row + mi_col;
MODE_INFO **mi = mi_grid_visible + mi_idx;
MV *source_mv[2];
MV_REFERENCE_FRAME source_ref_frame[2];
// partition info
const int block_width_4x4 = (pc_tree->partitioning == PARTITION_VERT)
? square_size_4x4 >> 1
: square_size_4x4;
const int block_height_4x4 = (pc_tree->partitioning == PARTITION_HORZ)
? square_size_4x4 >> 1
: square_size_4x4;
assign_partition_info(row_start_4x4, col_start_4x4, block_width_4x4,
block_height_4x4, num_unit_rows, num_unit_cols,
partition_info);
if (pc_tree->partitioning == PARTITION_VERT) {
assign_partition_info(row_start_4x4, col_start_4x4 + block_width_4x4,
block_width_4x4, block_height_4x4, num_unit_rows,
num_unit_cols, partition_info);
} else if (pc_tree->partitioning == PARTITION_HORZ) {
assign_partition_info(row_start_4x4 + block_height_4x4, col_start_4x4,
block_width_4x4, block_height_4x4, num_unit_rows,
num_unit_cols, partition_info);
}
// motion vector info
if (pc_tree->partitioning == PARTITION_HORZ) {
int is_valid_second_rectangle = 0;
assert(square_size_4x4 > 1);
// First rectangle.
source_ref_frame[0] = mi[0]->ref_frame[0];
source_ref_frame[1] = mi[0]->ref_frame[1];
source_mv[0] = &mi[0]->mv[0].as_mv;
source_mv[1] = &mi[0]->mv[1].as_mv;
assign_motion_vector_info(block_width_4x4, block_height_4x4,
row_start_4x4, col_start_4x4, num_unit_rows,
num_unit_cols, source_mv, source_ref_frame,
motion_vector_info);
// Second rectangle.
if (square_size_4x4 == 2) {
is_valid_second_rectangle = 1;
source_ref_frame[0] = mi[0]->ref_frame[0];
source_ref_frame[1] = mi[0]->ref_frame[1];
source_mv[0] = &mi[0]->bmi[2].as_mv[0].as_mv;
source_mv[1] = &mi[0]->bmi[2].as_mv[1].as_mv;
} else {
const int mi_row_2 = mi_row + (block_height_4x4 >> 1);
const int mi_col_2 = mi_col;
if (mi_row_2 * 2 < num_unit_rows && mi_col_2 * 2 < num_unit_cols) {
const int mi_idx_2 = mi_stride * mi_row_2 + mi_col_2;
is_valid_second_rectangle = 1;
mi = mi_grid_visible + mi_idx_2;
source_ref_frame[0] = mi[0]->ref_frame[0];
source_ref_frame[1] = mi[0]->ref_frame[1];
source_mv[0] = &mi[0]->mv[0].as_mv;
source_mv[1] = &mi[0]->mv[1].as_mv;
}
}
if (is_valid_second_rectangle) {
assign_motion_vector_info(
block_width_4x4, block_height_4x4, row_start_4x4 + block_height_4x4,
col_start_4x4, num_unit_rows, num_unit_cols, source_mv,
source_ref_frame, motion_vector_info);
}
} else if (pc_tree->partitioning == PARTITION_VERT) {
int is_valid_second_rectangle = 0;
assert(square_size_4x4 > 1);
// First rectangle.
source_ref_frame[0] = mi[0]->ref_frame[0];
source_ref_frame[1] = mi[0]->ref_frame[1];
source_mv[0] = &mi[0]->mv[0].as_mv;
source_mv[1] = &mi[0]->mv[1].as_mv;
assign_motion_vector_info(block_width_4x4, block_height_4x4,
row_start_4x4, col_start_4x4, num_unit_rows,
num_unit_cols, source_mv, source_ref_frame,
motion_vector_info);
// Second rectangle.
if (square_size_4x4 == 2) {
is_valid_second_rectangle = 1;
source_ref_frame[0] = mi[0]->ref_frame[0];
source_ref_frame[1] = mi[0]->ref_frame[1];
source_mv[0] = &mi[0]->bmi[1].as_mv[0].as_mv;
source_mv[1] = &mi[0]->bmi[1].as_mv[1].as_mv;
} else {
const int mi_row_2 = mi_row;
const int mi_col_2 = mi_col + (block_width_4x4 >> 1);
if (mi_row_2 * 2 < num_unit_rows && mi_col_2 * 2 < num_unit_cols) {
const int mi_idx_2 = mi_stride * mi_row_2 + mi_col_2;
is_valid_second_rectangle = 1;
mi = mi_grid_visible + mi_idx_2;
source_ref_frame[0] = mi[0]->ref_frame[0];
source_ref_frame[1] = mi[0]->ref_frame[1];
source_mv[0] = &mi[0]->mv[0].as_mv;
source_mv[1] = &mi[0]->mv[1].as_mv;
}
}
if (is_valid_second_rectangle) {
assign_motion_vector_info(
block_width_4x4, block_height_4x4, row_start_4x4,
col_start_4x4 + block_width_4x4, num_unit_rows, num_unit_cols,
source_mv, source_ref_frame, motion_vector_info);
}
} else {
assert(pc_tree->partitioning == PARTITION_NONE || square_size_4x4 == 1);
source_ref_frame[0] = mi[0]->ref_frame[0];
source_ref_frame[1] = mi[0]->ref_frame[1];
if (square_size_4x4 == 1) {
const int sub8x8_row = row_start_4x4 % 2;
const int sub8x8_col = col_start_4x4 % 2;
const int sub8x8_idx = sub8x8_row * 2 + sub8x8_col;
source_mv[0] = &mi[0]->bmi[sub8x8_idx].as_mv[0].as_mv;
source_mv[1] = &mi[0]->bmi[sub8x8_idx].as_mv[1].as_mv;
} else {
source_mv[0] = &mi[0]->mv[0].as_mv;
source_mv[1] = &mi[0]->mv[1].as_mv;
}
assign_motion_vector_info(block_width_4x4, block_height_4x4,
row_start_4x4, col_start_4x4, num_unit_rows,
num_unit_cols, source_mv, source_ref_frame,
motion_vector_info);
}
return;
}
// recursively traverse partition tree when partition is split.
assert(pc_tree->partitioning == PARTITION_SPLIT);
store_superblock_info(pc_tree->split[0], mi_grid_visible, mi_stride,
subblock_square_size_4x4, num_unit_rows, num_unit_cols,
row_start_4x4, col_start_4x4, partition_info,
motion_vector_info);
store_superblock_info(pc_tree->split[1], mi_grid_visible, mi_stride,
subblock_square_size_4x4, num_unit_rows, num_unit_cols,
row_start_4x4, col_start_4x4 + subblock_square_size_4x4,
partition_info, motion_vector_info);
store_superblock_info(pc_tree->split[2], mi_grid_visible, mi_stride,
subblock_square_size_4x4, num_unit_rows, num_unit_cols,
row_start_4x4 + subblock_square_size_4x4, col_start_4x4,
partition_info, motion_vector_info);
store_superblock_info(pc_tree->split[3], mi_grid_visible, mi_stride,
subblock_square_size_4x4, num_unit_rows, num_unit_cols,
row_start_4x4 + subblock_square_size_4x4,
col_start_4x4 + subblock_square_size_4x4,
partition_info, motion_vector_info);
}
#endif // CONFIG_RATE_CTRL
#if !CONFIG_REALTIME_ONLY
// TODO(jingning,jimbankoski,rbultje): properly skip partition types that are
// unlikely to be selected depending on previous rate-distortion optimization
@@ -3839,11 +3980,6 @@ static int rd_pick_partition(VP9_COMP *cpi, ThreadData *td,
BLOCK_SIZE min_size = x->min_partition_size;
BLOCK_SIZE max_size = x->max_partition_size;
#if CONFIG_FP_MB_STATS
unsigned int src_diff_var = UINT_MAX;
int none_complexity = 0;
#endif
int partition_none_allowed = !force_horz_split && !force_vert_split;
int partition_horz_allowed =
!force_vert_split && yss <= xss && bsize >= BLOCK_8X8;
@@ -3930,65 +4066,6 @@ static int rd_pick_partition(VP9_COMP *cpi, ThreadData *td,
save_context(x, mi_row, mi_col, a, l, sa, sl, bsize);
#if CONFIG_FP_MB_STATS
if (cpi->use_fp_mb_stats) {
set_offsets(cpi, tile_info, x, mi_row, mi_col, bsize);
src_diff_var = get_sby_perpixel_diff_variance(cpi, &x->plane[0].src, mi_row,
mi_col, bsize);
}
#endif
#if CONFIG_FP_MB_STATS
// Decide whether we shall split directly and skip searching NONE by using
// the first pass block statistics
if (cpi->use_fp_mb_stats && bsize >= BLOCK_32X32 && do_split &&
partition_none_allowed && src_diff_var > 4 &&
cm->base_qindex < qindex_split_threshold_lookup[bsize]) {
int mb_row = mi_row >> 1;
int mb_col = mi_col >> 1;
int mb_row_end =
VPXMIN(mb_row + num_16x16_blocks_high_lookup[bsize], cm->mb_rows);
int mb_col_end =
VPXMIN(mb_col + num_16x16_blocks_wide_lookup[bsize], cm->mb_cols);
int r, c;
// compute a complexity measure, basically measure inconsistency of motion
// vectors obtained from the first pass in the current block
for (r = mb_row; r < mb_row_end; r++) {
for (c = mb_col; c < mb_col_end; c++) {
const int mb_index = r * cm->mb_cols + c;
MOTION_DIRECTION this_mv;
MOTION_DIRECTION right_mv;
MOTION_DIRECTION bottom_mv;
this_mv =
get_motion_direction_fp(cpi->twopass.this_frame_mb_stats[mb_index]);
// to its right
if (c != mb_col_end - 1) {
right_mv = get_motion_direction_fp(
cpi->twopass.this_frame_mb_stats[mb_index + 1]);
none_complexity += get_motion_inconsistency(this_mv, right_mv);
}
// to its bottom
if (r != mb_row_end - 1) {
bottom_mv = get_motion_direction_fp(
cpi->twopass.this_frame_mb_stats[mb_index + cm->mb_cols]);
none_complexity += get_motion_inconsistency(this_mv, bottom_mv);
}
// do not count its left and top neighbors to avoid double counting
}
}
if (none_complexity > complexity_16x16_blocks_threshold[bsize]) {
partition_none_allowed = 0;
}
}
#endif
pc_tree->partitioning = PARTITION_NONE;
if (cpi->sf.rd_ml_partition.var_pruning && !frame_is_intra_only(cm)) {
@@ -4066,53 +4143,6 @@ static int rd_pick_partition(VP9_COMP *cpi, ThreadData *td,
}
}
}
#if CONFIG_FP_MB_STATS
// Check if every 16x16 first pass block statistics has zero
// motion and the corresponding first pass residue is small enough.
// If that is the case, check the difference variance between the
// current frame and the last frame. If the variance is small enough,
// stop further splitting in RD optimization
if (cpi->use_fp_mb_stats && do_split != 0 &&
cm->base_qindex > qindex_skip_threshold_lookup[bsize]) {
int mb_row = mi_row >> 1;
int mb_col = mi_col >> 1;
int mb_row_end =
VPXMIN(mb_row + num_16x16_blocks_high_lookup[bsize], cm->mb_rows);
int mb_col_end =
VPXMIN(mb_col + num_16x16_blocks_wide_lookup[bsize], cm->mb_cols);
int r, c;
int skip = 1;
for (r = mb_row; r < mb_row_end; r++) {
for (c = mb_col; c < mb_col_end; c++) {
const int mb_index = r * cm->mb_cols + c;
if (!(cpi->twopass.this_frame_mb_stats[mb_index] &
FPMB_MOTION_ZERO_MASK) ||
!(cpi->twopass.this_frame_mb_stats[mb_index] &
FPMB_ERROR_SMALL_MASK)) {
skip = 0;
break;
}
}
if (skip == 0) {
break;
}
}
if (skip) {
if (src_diff_var == UINT_MAX) {
set_offsets(cpi, tile_info, x, mi_row, mi_col, bsize);
src_diff_var = get_sby_perpixel_diff_variance(
cpi, &x->plane[0].src, mi_row, mi_col, bsize);
}
if (src_diff_var < 8) {
do_split = 0;
do_rect = 0;
}
}
}
#endif
}
}
restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize);
@@ -4248,13 +4278,21 @@ static int rd_pick_partition(VP9_COMP *cpi, ThreadData *td,
if (cpi->sf.prune_ref_frame_for_rect_partitions) {
uint8_t used_frames;
used_frames = ref_frames_used[0] | ref_frames_used[1];
if (used_frames) pc_tree->horizontal[0].skip_ref_frame_mask = ~used_frames;
if (used_frames) {
pc_tree->horizontal[0].skip_ref_frame_mask = ~used_frames & 0xff;
}
used_frames = ref_frames_used[2] | ref_frames_used[3];
if (used_frames) pc_tree->horizontal[1].skip_ref_frame_mask = ~used_frames;
if (used_frames) {
pc_tree->horizontal[1].skip_ref_frame_mask = ~used_frames & 0xff;
}
used_frames = ref_frames_used[0] | ref_frames_used[2];
if (used_frames) pc_tree->vertical[0].skip_ref_frame_mask = ~used_frames;
if (used_frames) {
pc_tree->vertical[0].skip_ref_frame_mask = ~used_frames & 0xff;
}
used_frames = ref_frames_used[1] | ref_frames_used[3];
if (used_frames) pc_tree->vertical[1].skip_ref_frame_mask = ~used_frames;
if (used_frames) {
pc_tree->vertical[1].skip_ref_frame_mask = ~used_frames & 0xff;
}
}
{
@@ -4369,6 +4407,21 @@ static int rd_pick_partition(VP9_COMP *cpi, ThreadData *td,
int output_enabled = (bsize == BLOCK_64X64);
encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled, bsize,
pc_tree);
#if CONFIG_RATE_CTRL
if (oxcf->use_simple_encode_api) {
// Store partition, motion vector of the superblock.
if (output_enabled) {
const int num_unit_rows =
get_num_unit_4x4(cpi->frame_info.frame_height);
const int num_unit_cols = get_num_unit_4x4(cpi->frame_info.frame_width);
store_superblock_info(pc_tree, cm->mi_grid_visible, cm->mi_stride,
num_4x4_blocks_wide_lookup[BLOCK_64X64],
num_unit_rows, num_unit_cols, mi_row << 1,
mi_col << 1, cpi->partition_info,
cpi->motion_vector_info);
}
}
#endif // CONFIG_RATE_CTRL
}
if (bsize == BLOCK_64X64) {
@@ -4455,13 +4508,6 @@ static void encode_rd_sb_row(VP9_COMP *cpi, ThreadData *td,
set_fixed_partitioning(cpi, tile_info, mi, mi_row, mi_col, bsize);
rd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, BLOCK_64X64,
&dummy_rate, &dummy_dist, 1, td->pc_root);
} else if (cpi->partition_search_skippable_frame) {
BLOCK_SIZE bsize;
set_offsets(cpi, tile_info, x, mi_row, mi_col, BLOCK_64X64);
bsize = get_rd_var_based_fixed_partition(cpi, x, mi_row, mi_col);
set_fixed_partitioning(cpi, tile_info, mi, mi_row, mi_col, bsize);
rd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, BLOCK_64X64,
&dummy_rate, &dummy_dist, 1, td->pc_root);
} else if (sf->partition_search_type == VAR_BASED_PARTITION &&
cm->frame_type != KEY_FRAME) {
choose_partitioning(cpi, tile_info, x, mi_row, mi_col);
@@ -4641,7 +4687,7 @@ static void nonrd_pick_sb_modes(VP9_COMP *cpi, TileDataEnc *tile_data,
hybrid_search_svc_baseiskey(cpi, x, rd_cost, bsize, ctx, tile_data, mi_row,
mi_col);
else if (segfeature_active(&cm->seg, mi->segment_id, SEG_LVL_SKIP))
set_mode_info_seg_skip(x, cm->tx_mode, rd_cost, bsize);
set_mode_info_seg_skip(x, cm->tx_mode, cm->interp_filter, rd_cost, bsize);
else if (bsize >= BLOCK_8X8) {
if (cpi->rc.hybrid_intra_scene_change)
hybrid_search_scene_change(cpi, x, rd_cost, bsize, ctx, tile_data, mi_row,
@@ -4845,8 +4891,8 @@ static void nonrd_pick_partition(VP9_COMP *cpi, ThreadData *td,
(void)*tp_orig;
// Avoid checking for rectangular partitions for speed >= 6.
if (cpi->oxcf.speed >= 6) do_rect = 0;
// Avoid checking for rectangular partitions for speed >= 5.
if (cpi->oxcf.speed >= 5) do_rect = 0;
assert(num_8x8_blocks_wide_lookup[bsize] ==
num_8x8_blocks_high_lookup[bsize]);
@@ -5472,16 +5518,6 @@ static void encode_nonrd_sb_row(VP9_COMP *cpi, ThreadData *td,
x->arf_frame_usage = 0;
x->lastgolden_frame_usage = 0;
if (seg->enabled) {
const uint8_t *const map =
seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
int segment_id = get_segment_id(cm, map, BLOCK_64X64, mi_row, mi_col);
seg_skip = segfeature_active(seg, segment_id, SEG_LVL_SKIP);
if (seg_skip) {
partition_search_type = FIXED_PARTITION;
}
}
if (cpi->compute_source_sad_onepass && cpi->sf.use_source_sad) {
int shift = cpi->Source->y_stride * (mi_row << 3) + (mi_col << 3);
int sb_offset2 = ((cm->mi_cols + 7) >> 3) * (mi_row >> 3) + (mi_col >> 3);
@@ -5493,6 +5529,38 @@ static void encode_nonrd_sb_row(VP9_COMP *cpi, ThreadData *td,
partition_search_type = REFERENCE_PARTITION;
}
if (seg->enabled) {
const uint8_t *const map =
seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
int segment_id = get_segment_id(cm, map, BLOCK_64X64, mi_row, mi_col);
seg_skip = segfeature_active(seg, segment_id, SEG_LVL_SKIP);
if (cpi->roi.enabled && cpi->roi.skip[BACKGROUND_SEG_SKIP_ID] &&
cpi->rc.frames_since_key > FRAMES_NO_SKIPPING_AFTER_KEY &&
x->content_state_sb > kLowSadLowSumdiff) {
// For ROI with skip, force segment = 0 (no skip) over whole
// superblock to avoid artifacts if temporal change in source_sad is
// not 0.
int xi, yi;
const int bw = num_8x8_blocks_wide_lookup[BLOCK_64X64];
const int bh = num_8x8_blocks_high_lookup[BLOCK_64X64];
const int xmis = VPXMIN(cm->mi_cols - mi_col, bw);
const int ymis = VPXMIN(cm->mi_rows - mi_row, bh);
const int block_index = mi_row * cm->mi_cols + mi_col;
set_mode_info_offsets(cm, x, xd, mi_row, mi_col);
for (yi = 0; yi < ymis; yi++)
for (xi = 0; xi < xmis; xi++) {
int map_offset = block_index + yi * cm->mi_cols + xi;
cpi->segmentation_map[map_offset] = 0;
}
set_segment_index(cpi, x, mi_row, mi_col, BLOCK_64X64, 0);
seg_skip = 0;
}
if (seg_skip) {
partition_search_type = FIXED_PARTITION;
}
}
// Set the partition type of the 64X64 block
switch (partition_search_type) {
case VAR_BASED_PARTITION:
@@ -5736,9 +5804,14 @@ void vp9_init_tile_data(VP9_COMP *cpi) {
for (i = 0; i < BLOCK_SIZES; ++i) {
for (j = 0; j < MAX_MODES; ++j) {
tile_data->thresh_freq_fact[i][j] = RD_THRESH_INIT_FACT;
#if CONFIG_RATE_CTRL
if (cpi->oxcf.use_simple_encode_api) {
tile_data->thresh_freq_fact_prev[i][j] = RD_THRESH_INIT_FACT;
}
#endif // CONFIG_RATE_CTRL
#if CONFIG_CONSISTENT_RECODE
tile_data->thresh_freq_fact_prev[i][j] = RD_THRESH_INIT_FACT;
#endif
#endif // CONFIG_CONSISTENT_RECODE
tile_data->mode_map[i][j] = j;
}
}
@@ -5783,9 +5856,12 @@ void vp9_encode_sb_row(VP9_COMP *cpi, ThreadData *td, int tile_row,
get_start_tok(cpi, tile_row, tile_col, mi_row, &tok);
cpi->tplist[tile_row][tile_col][tile_sb_row].start = tok;
#if CONFIG_REALTIME_ONLY
assert(cpi->sf.use_nonrd_pick_mode);
encode_nonrd_sb_row(cpi, td, this_tile, mi_row, &tok);
#else
if (cpi->sf.use_nonrd_pick_mode)
encode_nonrd_sb_row(cpi, td, this_tile, mi_row, &tok);
#if !CONFIG_REALTIME_ONLY
else
encode_rd_sb_row(cpi, td, this_tile, mi_row, &tok);
#endif
@@ -5827,20 +5903,6 @@ static void encode_tiles(VP9_COMP *cpi) {
vp9_encode_tile(cpi, &cpi->td, tile_row, tile_col);
}
#if CONFIG_FP_MB_STATS
static int input_fpmb_stats(FIRSTPASS_MB_STATS *firstpass_mb_stats,
VP9_COMMON *cm, uint8_t **this_frame_mb_stats) {
uint8_t *mb_stats_in = firstpass_mb_stats->mb_stats_start +
cm->current_video_frame * cm->MBs * sizeof(uint8_t);
if (mb_stats_in > firstpass_mb_stats->mb_stats_end) return EOF;
*this_frame_mb_stats = mb_stats_in;
return 1;
}
#endif
static int compare_kmeans_data(const void *a, const void *b) {
if (((const KMEANS_DATA *)a)->value > ((const KMEANS_DATA *)b)->value) {
return 1;
@@ -6047,13 +6109,6 @@ static void encode_frame_internal(VP9_COMP *cpi) {
struct vpx_usec_timer emr_timer;
vpx_usec_timer_start(&emr_timer);
#if CONFIG_FP_MB_STATS
if (cpi->use_fp_mb_stats) {
input_fpmb_stats(&cpi->twopass.firstpass_mb_stats, cm,
&cpi->twopass.this_frame_mb_stats);
}
#endif
if (!cpi->row_mt) {
cpi->row_mt_sync_read_ptr = vp9_row_mt_sync_read_dummy;
cpi->row_mt_sync_write_ptr = vp9_row_mt_sync_write_dummy;
@@ -6123,7 +6178,7 @@ static int compute_frame_aq_offset(struct VP9_COMP *cpi) {
return sum_delta / (cm->mi_rows * cm->mi_cols);
}
#if CONFIG_CONSISTENT_RECODE
#if CONFIG_CONSISTENT_RECODE || CONFIG_RATE_CTRL
static void restore_encode_params(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
const int tile_cols = 1 << cm->log2_tile_cols;
@@ -6156,11 +6211,16 @@ static void restore_encode_params(VP9_COMP *cpi) {
cm->interp_filter = cpi->sf.default_interp_filter;
}
#endif
#endif // CONFIG_CONSISTENT_RECODE || CONFIG_RATE_CTRL
void vp9_encode_frame(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
#if CONFIG_RATE_CTRL
if (cpi->oxcf.use_simple_encode_api) {
restore_encode_params(cpi);
}
#endif // CONFIG_RATE_CTRL
#if CONFIG_CONSISTENT_RECODE
restore_encode_params(cpi);
#endif
@@ -6458,7 +6518,8 @@ static void encode_superblock(VP9_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
++td->counts->tx.tx_totals[mi->tx_size];
++td->counts->tx.tx_totals[get_uv_tx_size(mi, &xd->plane[1])];
if (cm->seg.enabled && cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
if (cm->seg.enabled && cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
cpi->cyclic_refresh->content_mode)
vp9_cyclic_refresh_update_sb_postencode(cpi, mi, mi_row, mi_col, bsize);
if (cpi->oxcf.pass == 0 && cpi->svc.temporal_layer_id == 0 &&
(!cpi->use_svc ||
+85 -102
View File
@@ -366,28 +366,28 @@ void vp9_xform_quant_fp(MACROBLOCK *x, int plane, int block, int row, int col,
switch (tx_size) {
case TX_32X32:
highbd_fdct32x32(x->use_lp32x32fdct, src_diff, coeff, diff_stride);
vp9_highbd_quantize_fp_32x32(coeff, 1024, x->skip_block, p->round_fp,
p->quant_fp, qcoeff, dqcoeff, pd->dequant,
eob, scan_order->scan, scan_order->iscan);
vp9_highbd_quantize_fp_32x32(coeff, 1024, p->round_fp, p->quant_fp,
qcoeff, dqcoeff, pd->dequant, eob,
scan_order->scan, scan_order->iscan);
break;
case TX_16X16:
vpx_highbd_fdct16x16(src_diff, coeff, diff_stride);
vp9_highbd_quantize_fp(coeff, 256, x->skip_block, p->round_fp,
p->quant_fp, qcoeff, dqcoeff, pd->dequant, eob,
scan_order->scan, scan_order->iscan);
vp9_highbd_quantize_fp(coeff, 256, p->round_fp, p->quant_fp, qcoeff,
dqcoeff, pd->dequant, eob, scan_order->scan,
scan_order->iscan);
break;
case TX_8X8:
vpx_highbd_fdct8x8(src_diff, coeff, diff_stride);
vp9_highbd_quantize_fp(coeff, 64, x->skip_block, p->round_fp,
p->quant_fp, qcoeff, dqcoeff, pd->dequant, eob,
scan_order->scan, scan_order->iscan);
vp9_highbd_quantize_fp(coeff, 64, p->round_fp, p->quant_fp, qcoeff,
dqcoeff, pd->dequant, eob, scan_order->scan,
scan_order->iscan);
break;
default:
assert(tx_size == TX_4X4);
x->fwd_txfm4x4(src_diff, coeff, diff_stride);
vp9_highbd_quantize_fp(coeff, 16, x->skip_block, p->round_fp,
p->quant_fp, qcoeff, dqcoeff, pd->dequant, eob,
scan_order->scan, scan_order->iscan);
vp9_highbd_quantize_fp(coeff, 16, p->round_fp, p->quant_fp, qcoeff,
dqcoeff, pd->dequant, eob, scan_order->scan,
scan_order->iscan);
break;
}
return;
@@ -397,29 +397,26 @@ void vp9_xform_quant_fp(MACROBLOCK *x, int plane, int block, int row, int col,
switch (tx_size) {
case TX_32X32:
fdct32x32(x->use_lp32x32fdct, src_diff, coeff, diff_stride);
vp9_quantize_fp_32x32(coeff, 1024, x->skip_block, p->round_fp,
p->quant_fp, qcoeff, dqcoeff, pd->dequant, eob,
scan_order->scan, scan_order->iscan);
vp9_quantize_fp_32x32(coeff, 1024, p->round_fp, p->quant_fp, qcoeff,
dqcoeff, pd->dequant, eob, scan_order->scan,
scan_order->iscan);
break;
case TX_16X16:
vpx_fdct16x16(src_diff, coeff, diff_stride);
vp9_quantize_fp(coeff, 256, x->skip_block, p->round_fp, p->quant_fp,
qcoeff, dqcoeff, pd->dequant, eob, scan_order->scan,
scan_order->iscan);
vp9_quantize_fp(coeff, 256, p->round_fp, p->quant_fp, qcoeff, dqcoeff,
pd->dequant, eob, scan_order->scan, scan_order->iscan);
break;
case TX_8X8:
vpx_fdct8x8(src_diff, coeff, diff_stride);
vp9_quantize_fp(coeff, 64, x->skip_block, p->round_fp, p->quant_fp,
qcoeff, dqcoeff, pd->dequant, eob, scan_order->scan,
scan_order->iscan);
vp9_quantize_fp(coeff, 64, p->round_fp, p->quant_fp, qcoeff, dqcoeff,
pd->dequant, eob, scan_order->scan, scan_order->iscan);
break;
default:
assert(tx_size == TX_4X4);
x->fwd_txfm4x4(src_diff, coeff, diff_stride);
vp9_quantize_fp(coeff, 16, x->skip_block, p->round_fp, p->quant_fp,
qcoeff, dqcoeff, pd->dequant, eob, scan_order->scan,
scan_order->iscan);
vp9_quantize_fp(coeff, 16, p->round_fp, p->quant_fp, qcoeff, dqcoeff,
pd->dequant, eob, scan_order->scan, scan_order->iscan);
break;
}
}
@@ -444,28 +441,24 @@ void vp9_xform_quant_dc(MACROBLOCK *x, int plane, int block, int row, int col,
switch (tx_size) {
case TX_32X32:
vpx_highbd_fdct32x32_1(src_diff, coeff, diff_stride);
vpx_highbd_quantize_dc_32x32(coeff, x->skip_block, p->round,
p->quant_fp[0], qcoeff, dqcoeff,
pd->dequant[0], eob);
vpx_highbd_quantize_dc_32x32(coeff, p->round, p->quant_fp[0], qcoeff,
dqcoeff, pd->dequant[0], eob);
break;
case TX_16X16:
vpx_highbd_fdct16x16_1(src_diff, coeff, diff_stride);
vpx_highbd_quantize_dc(coeff, 256, x->skip_block, p->round,
p->quant_fp[0], qcoeff, dqcoeff, pd->dequant[0],
eob);
vpx_highbd_quantize_dc(coeff, 256, p->round, p->quant_fp[0], qcoeff,
dqcoeff, pd->dequant[0], eob);
break;
case TX_8X8:
vpx_highbd_fdct8x8_1(src_diff, coeff, diff_stride);
vpx_highbd_quantize_dc(coeff, 64, x->skip_block, p->round,
p->quant_fp[0], qcoeff, dqcoeff, pd->dequant[0],
eob);
vpx_highbd_quantize_dc(coeff, 64, p->round, p->quant_fp[0], qcoeff,
dqcoeff, pd->dequant[0], eob);
break;
default:
assert(tx_size == TX_4X4);
x->fwd_txfm4x4(src_diff, coeff, diff_stride);
vpx_highbd_quantize_dc(coeff, 16, x->skip_block, p->round,
p->quant_fp[0], qcoeff, dqcoeff, pd->dequant[0],
eob);
vpx_highbd_quantize_dc(coeff, 16, p->round, p->quant_fp[0], qcoeff,
dqcoeff, pd->dequant[0], eob);
break;
}
return;
@@ -475,24 +468,24 @@ void vp9_xform_quant_dc(MACROBLOCK *x, int plane, int block, int row, int col,
switch (tx_size) {
case TX_32X32:
vpx_fdct32x32_1(src_diff, coeff, diff_stride);
vpx_quantize_dc_32x32(coeff, x->skip_block, p->round, p->quant_fp[0],
qcoeff, dqcoeff, pd->dequant[0], eob);
vpx_quantize_dc_32x32(coeff, p->round, p->quant_fp[0], qcoeff, dqcoeff,
pd->dequant[0], eob);
break;
case TX_16X16:
vpx_fdct16x16_1(src_diff, coeff, diff_stride);
vpx_quantize_dc(coeff, 256, x->skip_block, p->round, p->quant_fp[0],
qcoeff, dqcoeff, pd->dequant[0], eob);
vpx_quantize_dc(coeff, 256, p->round, p->quant_fp[0], qcoeff, dqcoeff,
pd->dequant[0], eob);
break;
case TX_8X8:
vpx_fdct8x8_1(src_diff, coeff, diff_stride);
vpx_quantize_dc(coeff, 64, x->skip_block, p->round, p->quant_fp[0],
qcoeff, dqcoeff, pd->dequant[0], eob);
vpx_quantize_dc(coeff, 64, p->round, p->quant_fp[0], qcoeff, dqcoeff,
pd->dequant[0], eob);
break;
default:
assert(tx_size == TX_4X4);
x->fwd_txfm4x4(src_diff, coeff, diff_stride);
vpx_quantize_dc(coeff, 16, x->skip_block, p->round, p->quant_fp[0],
qcoeff, dqcoeff, pd->dequant[0], eob);
vpx_quantize_dc(coeff, 16, p->round, p->quant_fp[0], qcoeff, dqcoeff,
pd->dequant[0], eob);
break;
}
}
@@ -518,32 +511,28 @@ void vp9_xform_quant(MACROBLOCK *x, int plane, int block, int row, int col,
switch (tx_size) {
case TX_32X32:
highbd_fdct32x32(x->use_lp32x32fdct, src_diff, coeff, diff_stride);
vpx_highbd_quantize_b_32x32(coeff, 1024, x->skip_block, p->zbin,
p->round, p->quant, p->quant_shift, qcoeff,
dqcoeff, pd->dequant, eob, scan_order->scan,
scan_order->iscan);
vpx_highbd_quantize_b_32x32(
coeff, 1024, p->zbin, p->round, p->quant, p->quant_shift, qcoeff,
dqcoeff, pd->dequant, eob, scan_order->scan, scan_order->iscan);
break;
case TX_16X16:
vpx_highbd_fdct16x16(src_diff, coeff, diff_stride);
vpx_highbd_quantize_b(coeff, 256, x->skip_block, p->zbin, p->round,
p->quant, p->quant_shift, qcoeff, dqcoeff,
pd->dequant, eob, scan_order->scan,
scan_order->iscan);
vpx_highbd_quantize_b(coeff, 256, p->zbin, p->round, p->quant,
p->quant_shift, qcoeff, dqcoeff, pd->dequant, eob,
scan_order->scan, scan_order->iscan);
break;
case TX_8X8:
vpx_highbd_fdct8x8(src_diff, coeff, diff_stride);
vpx_highbd_quantize_b(coeff, 64, x->skip_block, p->zbin, p->round,
p->quant, p->quant_shift, qcoeff, dqcoeff,
pd->dequant, eob, scan_order->scan,
scan_order->iscan);
vpx_highbd_quantize_b(coeff, 64, p->zbin, p->round, p->quant,
p->quant_shift, qcoeff, dqcoeff, pd->dequant, eob,
scan_order->scan, scan_order->iscan);
break;
default:
assert(tx_size == TX_4X4);
x->fwd_txfm4x4(src_diff, coeff, diff_stride);
vpx_highbd_quantize_b(coeff, 16, x->skip_block, p->zbin, p->round,
p->quant, p->quant_shift, qcoeff, dqcoeff,
pd->dequant, eob, scan_order->scan,
scan_order->iscan);
vpx_highbd_quantize_b(coeff, 16, p->zbin, p->round, p->quant,
p->quant_shift, qcoeff, dqcoeff, pd->dequant, eob,
scan_order->scan, scan_order->iscan);
break;
}
return;
@@ -553,29 +542,28 @@ void vp9_xform_quant(MACROBLOCK *x, int plane, int block, int row, int col,
switch (tx_size) {
case TX_32X32:
fdct32x32(x->use_lp32x32fdct, src_diff, coeff, diff_stride);
vpx_quantize_b_32x32(coeff, 1024, x->skip_block, p->zbin, p->round,
p->quant, p->quant_shift, qcoeff, dqcoeff,
pd->dequant, eob, scan_order->scan,
scan_order->iscan);
vpx_quantize_b_32x32(coeff, 1024, p->zbin, p->round, p->quant,
p->quant_shift, qcoeff, dqcoeff, pd->dequant, eob,
scan_order->scan, scan_order->iscan);
break;
case TX_16X16:
vpx_fdct16x16(src_diff, coeff, diff_stride);
vpx_quantize_b(coeff, 256, x->skip_block, p->zbin, p->round, p->quant,
p->quant_shift, qcoeff, dqcoeff, pd->dequant, eob,
scan_order->scan, scan_order->iscan);
vpx_quantize_b(coeff, 256, p->zbin, p->round, p->quant, p->quant_shift,
qcoeff, dqcoeff, pd->dequant, eob, scan_order->scan,
scan_order->iscan);
break;
case TX_8X8:
vpx_fdct8x8(src_diff, coeff, diff_stride);
vpx_quantize_b(coeff, 64, x->skip_block, p->zbin, p->round, p->quant,
p->quant_shift, qcoeff, dqcoeff, pd->dequant, eob,
scan_order->scan, scan_order->iscan);
vpx_quantize_b(coeff, 64, p->zbin, p->round, p->quant, p->quant_shift,
qcoeff, dqcoeff, pd->dequant, eob, scan_order->scan,
scan_order->iscan);
break;
default:
assert(tx_size == TX_4X4);
x->fwd_txfm4x4(src_diff, coeff, diff_stride);
vpx_quantize_b(coeff, 16, x->skip_block, p->zbin, p->round, p->quant,
p->quant_shift, qcoeff, dqcoeff, pd->dequant, eob,
scan_order->scan, scan_order->iscan);
vpx_quantize_b(coeff, 16, p->zbin, p->round, p->quant, p->quant_shift,
qcoeff, dqcoeff, pd->dequant, eob, scan_order->scan,
scan_order->iscan);
break;
}
}
@@ -869,10 +857,9 @@ void vp9_encode_block_intra(int plane, int block, int row, int col,
vpx_highbd_subtract_block(32, 32, src_diff, diff_stride, src,
src_stride, dst, dst_stride, xd->bd);
highbd_fdct32x32(x->use_lp32x32fdct, src_diff, coeff, diff_stride);
vpx_highbd_quantize_b_32x32(coeff, 1024, x->skip_block, p->zbin,
p->round, p->quant, p->quant_shift,
qcoeff, dqcoeff, pd->dequant, eob,
scan_order->scan, scan_order->iscan);
vpx_highbd_quantize_b_32x32(
coeff, 1024, p->zbin, p->round, p->quant, p->quant_shift, qcoeff,
dqcoeff, pd->dequant, eob, scan_order->scan, scan_order->iscan);
}
if (args->enable_coeff_opt && !x->skip_recode) {
*a = *l = vp9_optimize_b(x, plane, block, tx_size, entropy_ctx) > 0;
@@ -889,10 +876,9 @@ void vp9_encode_block_intra(int plane, int block, int row, int col,
vpx_highbd_fdct16x16(src_diff, coeff, diff_stride);
else
vp9_highbd_fht16x16(src_diff, coeff, diff_stride, tx_type);
vpx_highbd_quantize_b(coeff, 256, x->skip_block, p->zbin, p->round,
p->quant, p->quant_shift, qcoeff, dqcoeff,
pd->dequant, eob, scan_order->scan,
scan_order->iscan);
vpx_highbd_quantize_b(coeff, 256, p->zbin, p->round, p->quant,
p->quant_shift, qcoeff, dqcoeff, pd->dequant,
eob, scan_order->scan, scan_order->iscan);
}
if (args->enable_coeff_opt && !x->skip_recode) {
*a = *l = vp9_optimize_b(x, plane, block, tx_size, entropy_ctx) > 0;
@@ -910,10 +896,9 @@ void vp9_encode_block_intra(int plane, int block, int row, int col,
vpx_highbd_fdct8x8(src_diff, coeff, diff_stride);
else
vp9_highbd_fht8x8(src_diff, coeff, diff_stride, tx_type);
vpx_highbd_quantize_b(coeff, 64, x->skip_block, p->zbin, p->round,
p->quant, p->quant_shift, qcoeff, dqcoeff,
pd->dequant, eob, scan_order->scan,
scan_order->iscan);
vpx_highbd_quantize_b(coeff, 64, p->zbin, p->round, p->quant,
p->quant_shift, qcoeff, dqcoeff, pd->dequant,
eob, scan_order->scan, scan_order->iscan);
}
if (args->enable_coeff_opt && !x->skip_recode) {
*a = *l = vp9_optimize_b(x, plane, block, tx_size, entropy_ctx) > 0;
@@ -932,10 +917,9 @@ void vp9_encode_block_intra(int plane, int block, int row, int col,
vp9_highbd_fht4x4(src_diff, coeff, diff_stride, tx_type);
else
x->fwd_txfm4x4(src_diff, coeff, diff_stride);
vpx_highbd_quantize_b(coeff, 16, x->skip_block, p->zbin, p->round,
p->quant, p->quant_shift, qcoeff, dqcoeff,
pd->dequant, eob, scan_order->scan,
scan_order->iscan);
vpx_highbd_quantize_b(coeff, 16, p->zbin, p->round, p->quant,
p->quant_shift, qcoeff, dqcoeff, pd->dequant,
eob, scan_order->scan, scan_order->iscan);
}
if (args->enable_coeff_opt && !x->skip_recode) {
*a = *l = vp9_optimize_b(x, plane, block, tx_size, entropy_ctx) > 0;
@@ -964,10 +948,9 @@ void vp9_encode_block_intra(int plane, int block, int row, int col,
vpx_subtract_block(32, 32, src_diff, diff_stride, src, src_stride, dst,
dst_stride);
fdct32x32(x->use_lp32x32fdct, src_diff, coeff, diff_stride);
vpx_quantize_b_32x32(coeff, 1024, x->skip_block, p->zbin, p->round,
p->quant, p->quant_shift, qcoeff, dqcoeff,
pd->dequant, eob, scan_order->scan,
scan_order->iscan);
vpx_quantize_b_32x32(coeff, 1024, p->zbin, p->round, p->quant,
p->quant_shift, qcoeff, dqcoeff, pd->dequant, eob,
scan_order->scan, scan_order->iscan);
}
if (args->enable_coeff_opt && !x->skip_recode) {
*a = *l = vp9_optimize_b(x, plane, block, tx_size, entropy_ctx) > 0;
@@ -980,9 +963,9 @@ void vp9_encode_block_intra(int plane, int block, int row, int col,
vpx_subtract_block(16, 16, src_diff, diff_stride, src, src_stride, dst,
dst_stride);
vp9_fht16x16(src_diff, coeff, diff_stride, tx_type);
vpx_quantize_b(coeff, 256, x->skip_block, p->zbin, p->round, p->quant,
p->quant_shift, qcoeff, dqcoeff, pd->dequant, eob,
scan_order->scan, scan_order->iscan);
vpx_quantize_b(coeff, 256, p->zbin, p->round, p->quant, p->quant_shift,
qcoeff, dqcoeff, pd->dequant, eob, scan_order->scan,
scan_order->iscan);
}
if (args->enable_coeff_opt && !x->skip_recode) {
*a = *l = vp9_optimize_b(x, plane, block, tx_size, entropy_ctx) > 0;
@@ -995,9 +978,9 @@ void vp9_encode_block_intra(int plane, int block, int row, int col,
vpx_subtract_block(8, 8, src_diff, diff_stride, src, src_stride, dst,
dst_stride);
vp9_fht8x8(src_diff, coeff, diff_stride, tx_type);
vpx_quantize_b(coeff, 64, x->skip_block, p->zbin, p->round, p->quant,
p->quant_shift, qcoeff, dqcoeff, pd->dequant, eob,
scan_order->scan, scan_order->iscan);
vpx_quantize_b(coeff, 64, p->zbin, p->round, p->quant, p->quant_shift,
qcoeff, dqcoeff, pd->dequant, eob, scan_order->scan,
scan_order->iscan);
}
if (args->enable_coeff_opt && !x->skip_recode) {
*a = *l = vp9_optimize_b(x, plane, block, tx_size, entropy_ctx) > 0;
@@ -1014,9 +997,9 @@ void vp9_encode_block_intra(int plane, int block, int row, int col,
vp9_fht4x4(src_diff, coeff, diff_stride, tx_type);
else
x->fwd_txfm4x4(src_diff, coeff, diff_stride);
vpx_quantize_b(coeff, 16, x->skip_block, p->zbin, p->round, p->quant,
p->quant_shift, qcoeff, dqcoeff, pd->dequant, eob,
scan_order->scan, scan_order->iscan);
vpx_quantize_b(coeff, 16, p->zbin, p->round, p->quant, p->quant_shift,
qcoeff, dqcoeff, pd->dequant, eob, scan_order->scan,
scan_order->iscan);
}
if (args->enable_coeff_opt && !x->skip_recode) {
*a = *l = vp9_optimize_b(x, plane, block, tx_size, entropy_ctx) > 0;
File diff suppressed because it is too large. Load diff
+350 -83
View File
@@ -15,13 +15,16 @@
#include "./vpx_config.h"
#include "vpx/internal/vpx_codec_internal.h"
#include "vpx/vpx_ext_ratectrl.h"
#include "vpx/vp8cx.h"
#if CONFIG_INTERNAL_STATS
#include "vpx_dsp/ssim.h"
#endif
#include "vpx_dsp/variance.h"
#include "vpx_dsp/psnr.h"
#include "vpx_ports/system_state.h"
#include "vpx_util/vpx_thread.h"
#include "vpx_util/vpx_timestamp.h"
#include "vp9/common/vp9_alloccommon.h"
#include "vp9/common/vp9_ppflags.h"
@@ -36,6 +39,7 @@
#include "vp9/encoder/vp9_context_tree.h"
#include "vp9/encoder/vp9_encodemb.h"
#include "vp9/encoder/vp9_ethread.h"
#include "vp9/encoder/vp9_ext_ratectrl.h"
#include "vp9/encoder/vp9_firstpass.h"
#include "vp9/encoder/vp9_job_queue.h"
#include "vp9/encoder/vp9_lookahead.h"
@@ -145,6 +149,12 @@ typedef enum {
kVeryHighSad = 6,
} CONTENT_STATE_SB;
typedef enum {
LOOPFILTER_ALL = 0,
LOOPFILTER_REFERENCE = 1, // Disable loopfilter on non reference frames.
NO_LOOPFILTER = 2, // Disable loopfilter on all frames.
} LOOPFILTER_CONTROL;
typedef struct VP9EncoderConfig {
BITSTREAM_PROFILE profile;
vpx_bit_depth_t bit_depth; // Codec bit-depth.
@@ -152,7 +162,10 @@ typedef struct VP9EncoderConfig {
int height; // height of data passed to the compressor
unsigned int input_bit_depth; // Input bit depth.
double init_framerate; // set to passed in framerate
int64_t target_bandwidth; // bandwidth to be used in bits per second
vpx_rational_t g_timebase; // equivalent to g_timebase in vpx_codec_enc_cfg_t
vpx_rational64_t g_timebase_in_ts; // g_timebase * TICKS_PER_SEC
int64_t target_bandwidth; // bandwidth to be used in bits per second
int noise_sensitivity; // pre processing blur: recommendation 0
int sharpness; // sharpening output: recommendation 0:
@@ -259,11 +272,6 @@ typedef struct VP9EncoderConfig {
unsigned int target_level;
vpx_fixed_buf_t two_pass_stats_in;
struct vpx_codec_pkt_list *output_pkt_list;
#if CONFIG_FP_MB_STATS
vpx_fixed_buf_t firstpass_mb_stats_in;
#endif
vp8e_tuning tuning;
vp9e_tune_content content;
@@ -278,6 +286,8 @@ typedef struct VP9EncoderConfig {
int row_mt;
unsigned int motion_vector_unit_test;
int delta_q_uv;
int use_simple_encode_api; // Use SimpleEncode APIs or not
} VP9EncoderConfig;
static INLINE int is_lossless_requested(const VP9EncoderConfig *cfg) {
@@ -293,16 +303,9 @@ typedef struct TplDepStats {
int ref_frame_index;
int_mv mv;
#if CONFIG_NON_GREEDY_MV
int ready[3];
int64_t sse_arr[3];
double feature_score;
#endif
} TplDepStats;
#if CONFIG_NON_GREEDY_MV
#define SQUARE_BLOCK_SIZES 4
#define ZERO_MV_MODE 0
#define NEW_MV_MODE 1
@@ -322,63 +325,20 @@ typedef struct TplDepFrame {
int base_qindex;
#if CONFIG_NON_GREEDY_MV
int lambda;
int_mv *pyramid_mv_arr[3][SQUARE_BLOCK_SIZES];
int *mv_mode_arr[3];
double *rd_diff_arr[3];
#endif
} TplDepFrame;
#if CONFIG_NON_GREEDY_MV
static INLINE int get_square_block_idx(BLOCK_SIZE bsize) {
if (bsize == BLOCK_4X4) {
return 0;
}
if (bsize == BLOCK_8X8) {
return 1;
}
if (bsize == BLOCK_16X16) {
return 2;
}
if (bsize == BLOCK_32X32) {
return 3;
}
assert(0 && "ERROR: non-square block size");
return -1;
}
static INLINE BLOCK_SIZE square_block_idx_to_bsize(int square_block_idx) {
if (square_block_idx == 0) {
return BLOCK_4X4;
}
if (square_block_idx == 1) {
return BLOCK_8X8;
}
if (square_block_idx == 2) {
return BLOCK_16X16;
}
if (square_block_idx == 3) {
return BLOCK_32X32;
}
assert(0 && "ERROR: invalid square_block_idx");
return BLOCK_INVALID;
}
static INLINE int_mv *get_pyramid_mv(const TplDepFrame *tpl_frame, int rf_idx,
BLOCK_SIZE bsize, int mi_row, int mi_col) {
return &tpl_frame->pyramid_mv_arr[rf_idx][get_square_block_idx(bsize)]
[mi_row * tpl_frame->stride + mi_col];
}
#endif
#define TPL_DEP_COST_SCALE_LOG2 4
// TODO(jingning) All spatially adaptive variables should go to TileDataEnc.
typedef struct TileDataEnc {
TileInfo tile_info;
int thresh_freq_fact[BLOCK_SIZES][MAX_MODES];
#if CONFIG_CONSISTENT_RECODE
#if CONFIG_CONSISTENT_RECODE || CONFIG_RATE_CTRL
int thresh_freq_fact_prev[BLOCK_SIZES][MAX_MODES];
#endif
#endif // CONFIG_CONSISTENT_RECODE || CONFIG_RATE_CTRL
int8_t mode_map[BLOCK_SIZES][MAX_MODES];
FIRSTPASS_DATA fp_data;
VP9RowMTSync row_mt_sync;
@@ -533,7 +493,6 @@ typedef enum {
typedef struct {
int8_t level_index;
uint8_t rc_config_updated;
uint8_t fail_flag;
int max_frame_size; // in bits
double max_cpb_size; // in bits
@@ -555,15 +514,6 @@ typedef struct EncFrameBuf {
// Maximum operating frame buffer size needed for a GOP using ARF reference.
#define MAX_ARF_GOP_SIZE (2 * MAX_LAG_BUFFERS)
#if CONFIG_NON_GREEDY_MV
typedef struct FEATURE_SCORE_LOC {
int visited;
double feature_score;
int mi_row;
int mi_col;
} FEATURE_SCORE_LOC;
#endif
#define MAX_KMEANS_GROUPS 8
typedef struct KMEANS_DATA {
@@ -572,7 +522,145 @@ typedef struct KMEANS_DATA {
int group_idx;
} KMEANS_DATA;
#if CONFIG_RATE_CTRL
typedef struct PARTITION_INFO {
int row; // row pixel offset of current 4x4 block
int column; // column pixel offset of current 4x4 block
int row_start; // row pixel offset of the start of the prediction block
int column_start; // column pixel offset of the start of the prediction block
int width; // prediction block width
int height; // prediction block height
} PARTITION_INFO;
typedef struct MOTION_VECTOR_INFO {
MV_REFERENCE_FRAME ref_frame[2];
int_mv mv[2];
} MOTION_VECTOR_INFO;
typedef struct GOP_COMMAND {
int use; // use this command to set gop or not. If not, use vp9's decision.
int show_frame_count;
int use_alt_ref;
} GOP_COMMAND;
static INLINE void gop_command_on(GOP_COMMAND *gop_command,
int show_frame_count, int use_alt_ref) {
gop_command->use = 1;
gop_command->show_frame_count = show_frame_count;
gop_command->use_alt_ref = use_alt_ref;
}
static INLINE void gop_command_off(GOP_COMMAND *gop_command) {
gop_command->use = 0;
gop_command->show_frame_count = 0;
gop_command->use_alt_ref = 0;
}
static INLINE int gop_command_coding_frame_count(
const GOP_COMMAND *gop_command) {
if (gop_command->use == 0) {
assert(0);
return -1;
}
return gop_command->show_frame_count + gop_command->use_alt_ref;
}
// TODO(angiebird): See if we can merge this one with FrameType in
// simple_encode.h
typedef enum ENCODE_FRAME_TYPE {
ENCODE_FRAME_TYPE_KEY,
ENCODE_FRAME_TYPE_INTER,
ENCODE_FRAME_TYPE_ALTREF,
ENCODE_FRAME_TYPE_OVERLAY,
ENCODE_FRAME_TYPE_GOLDEN,
ENCODE_FRAME_TYPES,
} ENCODE_FRAME_TYPE;
// TODO(angiebird): Merge this function with get_frame_type_from_update_type()
static INLINE ENCODE_FRAME_TYPE
get_encode_frame_type(FRAME_UPDATE_TYPE update_type) {
switch (update_type) {
case KF_UPDATE: return ENCODE_FRAME_TYPE_KEY;
case ARF_UPDATE: return ENCODE_FRAME_TYPE_ALTREF;
case GF_UPDATE: return ENCODE_FRAME_TYPE_GOLDEN;
case OVERLAY_UPDATE: return ENCODE_FRAME_TYPE_OVERLAY;
case LF_UPDATE: return ENCODE_FRAME_TYPE_INTER;
default:
fprintf(stderr, "Unsupported update_type %d\n", update_type);
abort();
return ENCODE_FRAME_TYPE_INTER;
}
}
typedef struct RATE_QSTEP_MODEL {
// The rq model predicts the bit usage as follows.
// rate = bias - ratio * log2(q_step)
int ready;
double bias;
double ratio;
} RATE_QSTEP_MODEL;
typedef struct ENCODE_COMMAND {
int use_external_quantize_index;
int external_quantize_index;
int use_external_target_frame_bits;
int target_frame_bits;
double target_frame_bits_error_percent;
GOP_COMMAND gop_command;
} ENCODE_COMMAND;
static INLINE void encode_command_set_gop_command(
ENCODE_COMMAND *encode_command, GOP_COMMAND gop_command) {
encode_command->gop_command = gop_command;
}
static INLINE void encode_command_set_external_quantize_index(
ENCODE_COMMAND *encode_command, int quantize_index) {
encode_command->use_external_quantize_index = 1;
encode_command->external_quantize_index = quantize_index;
}
static INLINE void encode_command_reset_external_quantize_index(
ENCODE_COMMAND *encode_command) {
encode_command->use_external_quantize_index = 0;
encode_command->external_quantize_index = -1;
}
static INLINE void encode_command_set_target_frame_bits(
ENCODE_COMMAND *encode_command, int target_frame_bits,
double target_frame_bits_error_percent) {
encode_command->use_external_target_frame_bits = 1;
encode_command->target_frame_bits = target_frame_bits;
encode_command->target_frame_bits_error_percent =
target_frame_bits_error_percent;
}
static INLINE void encode_command_reset_target_frame_bits(
ENCODE_COMMAND *encode_command) {
encode_command->use_external_target_frame_bits = 0;
encode_command->target_frame_bits = -1;
encode_command->target_frame_bits_error_percent = 0;
}
static INLINE void encode_command_init(ENCODE_COMMAND *encode_command) {
vp9_zero(*encode_command);
encode_command_reset_external_quantize_index(encode_command);
encode_command_reset_target_frame_bits(encode_command);
gop_command_off(&encode_command->gop_command);
}
// Returns number of units in size of 4, if not multiple not a multiple of 4,
// round it up. For example, size is 7, return 2.
static INLINE int get_num_unit_4x4(int size) { return (size + 3) >> 2; }
// Returns number of units in size of 16, if not multiple not a multiple of 16,
// round it up. For example, size is 17, return 2.
static INLINE int get_num_unit_16x16(int size) { return (size + 15) >> 4; }
#endif // CONFIG_RATE_CTRL
typedef struct VP9_COMP {
FRAME_INFO frame_info;
QUANTS quants;
ThreadData td;
MB_MODE_INFO_EXT *mbmi_ext_base;
@@ -611,20 +699,14 @@ typedef struct VP9_COMP {
int kmeans_count_ls[MAX_KMEANS_GROUPS];
int kmeans_ctr_num;
#if CONFIG_NON_GREEDY_MV
MotionFieldInfo motion_field_info;
int tpl_ready;
int feature_score_loc_alloc;
FEATURE_SCORE_LOC *feature_score_loc_arr;
FEATURE_SCORE_LOC **feature_score_loc_sort;
FEATURE_SCORE_LOC **feature_score_loc_heap;
int_mv *select_mv_arr;
#endif
TileDataEnc *tile_data;
int allocated_tiles; // Keep track of memory allocated for tiles.
// For a still frame, this flag is set to 1 to skip partition search.
int partition_search_skippable_frame;
int scaled_ref_idx[REFS_PER_FRAME];
int lst_fb_idx;
int gld_fb_idx;
@@ -658,6 +740,7 @@ typedef struct VP9_COMP {
// Ambient reconstruction err target for force key frames
int64_t ambient_err;
RD_CONTROL rd_ctrl;
RD_OPT rd;
CODING_CONTEXT coding_context;
@@ -716,10 +799,6 @@ typedef struct VP9_COMP {
uint64_t time_pick_lpf;
uint64_t time_encode_sb_row;
#if CONFIG_FP_MB_STATS
int use_fp_mb_stats;
#endif
TWO_PASS twopass;
// Force recalculation of segment_ids for each mode info
@@ -871,6 +950,8 @@ typedef struct VP9_COMP {
int compute_source_sad_onepass;
int compute_frame_low_motion_onepass;
LevelConstraint level_constraint;
uint8_t *count_arf_frame_usage;
@@ -878,11 +959,162 @@ typedef struct VP9_COMP {
int multi_layer_arf;
vpx_roi_map_t roi;
LOOPFILTER_CONTROL loopfilter_ctrl;
#if CONFIG_RATE_CTRL
ENCODE_COMMAND encode_command;
PARTITION_INFO *partition_info;
MOTION_VECTOR_INFO *motion_vector_info;
MOTION_VECTOR_INFO *fp_motion_vector_info;
TplDepStats *tpl_stats_info;
RATE_QSTEP_MODEL rq_model[ENCODE_FRAME_TYPES];
#endif
EXT_RATECTRL ext_ratectrl;
} VP9_COMP;
#if CONFIG_RATE_CTRL
// Allocates memory for the partition information.
// The unit size is each 4x4 block.
// Only called once in vp9_create_compressor().
static INLINE void partition_info_init(struct VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
const int unit_width = get_num_unit_4x4(cpi->frame_info.frame_width);
const int unit_height = get_num_unit_4x4(cpi->frame_info.frame_height);
CHECK_MEM_ERROR(cm, cpi->partition_info,
(PARTITION_INFO *)vpx_calloc(unit_width * unit_height,
sizeof(PARTITION_INFO)));
memset(cpi->partition_info, 0,
unit_width * unit_height * sizeof(PARTITION_INFO));
}
// Frees memory of the partition information.
// Only called once in dealloc_compressor_data().
static INLINE void free_partition_info(struct VP9_COMP *cpi) {
vpx_free(cpi->partition_info);
cpi->partition_info = NULL;
}
static INLINE void reset_mv_info(MOTION_VECTOR_INFO *mv_info) {
mv_info->ref_frame[0] = NONE;
mv_info->ref_frame[1] = NONE;
mv_info->mv[0].as_int = INVALID_MV;
mv_info->mv[1].as_int = INVALID_MV;
}
// Allocates memory for the motion vector information.
// The unit size is each 4x4 block.
// Only called once in vp9_create_compressor().
static INLINE void motion_vector_info_init(struct VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
const int unit_width = get_num_unit_4x4(cpi->frame_info.frame_width);
const int unit_height = get_num_unit_4x4(cpi->frame_info.frame_height);
CHECK_MEM_ERROR(cm, cpi->motion_vector_info,
(MOTION_VECTOR_INFO *)vpx_calloc(unit_width * unit_height,
sizeof(MOTION_VECTOR_INFO)));
memset(cpi->motion_vector_info, 0,
unit_width * unit_height * sizeof(MOTION_VECTOR_INFO));
}
// Frees memory of the motion vector information.
// Only called once in dealloc_compressor_data().
static INLINE void free_motion_vector_info(struct VP9_COMP *cpi) {
vpx_free(cpi->motion_vector_info);
cpi->motion_vector_info = NULL;
}
// Allocates memory for the tpl stats information.
// Only called once in vp9_create_compressor().
static INLINE void tpl_stats_info_init(struct VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
CHECK_MEM_ERROR(
cm, cpi->tpl_stats_info,
(TplDepStats *)vpx_calloc(MAX_LAG_BUFFERS, sizeof(TplDepStats)));
memset(cpi->tpl_stats_info, 0, MAX_LAG_BUFFERS * sizeof(TplDepStats));
}
// Frees memory of the tpl stats information.
// Only called once in dealloc_compressor_data().
static INLINE void free_tpl_stats_info(struct VP9_COMP *cpi) {
vpx_free(cpi->tpl_stats_info);
cpi->tpl_stats_info = NULL;
}
// Allocates memory for the first pass motion vector information.
// The unit size is each 16x16 block.
// Only called once in vp9_create_compressor().
static INLINE void fp_motion_vector_info_init(struct VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
const int unit_width = get_num_unit_16x16(cpi->frame_info.frame_width);
const int unit_height = get_num_unit_16x16(cpi->frame_info.frame_height);
CHECK_MEM_ERROR(cm, cpi->fp_motion_vector_info,
(MOTION_VECTOR_INFO *)vpx_calloc(unit_width * unit_height,
sizeof(MOTION_VECTOR_INFO)));
}
static INLINE void fp_motion_vector_info_reset(
int frame_width, int frame_height,
MOTION_VECTOR_INFO *fp_motion_vector_info) {
const int unit_width = get_num_unit_16x16(frame_width);
const int unit_height = get_num_unit_16x16(frame_height);
int i;
for (i = 0; i < unit_width * unit_height; ++i) {
reset_mv_info(fp_motion_vector_info + i);
}
}
// Frees memory of the first pass motion vector information.
// Only called once in dealloc_compressor_data().
static INLINE void free_fp_motion_vector_info(struct VP9_COMP *cpi) {
vpx_free(cpi->fp_motion_vector_info);
cpi->fp_motion_vector_info = NULL;
}
// This is the c-version counter part of ImageBuffer
typedef struct IMAGE_BUFFER {
int allocated;
int plane_width[3];
int plane_height[3];
uint8_t *plane_buffer[3];
} IMAGE_BUFFER;
#define RATE_CTRL_MAX_RECODE_NUM 7
typedef struct RATE_QINDEX_HISTORY {
int recode_count;
int q_index_history[RATE_CTRL_MAX_RECODE_NUM];
int rate_history[RATE_CTRL_MAX_RECODE_NUM];
int q_index_high;
int q_index_low;
} RATE_QINDEX_HISTORY;
#endif // CONFIG_RATE_CTRL
typedef struct ENCODE_FRAME_RESULT {
int show_idx;
FRAME_UPDATE_TYPE update_type;
#if CONFIG_RATE_CTRL
int frame_coding_index;
int ref_frame_coding_indexes[MAX_INTER_REF_FRAMES];
int ref_frame_valid_list[MAX_INTER_REF_FRAMES];
double psnr;
uint64_t sse;
FRAME_COUNTS frame_counts;
const PARTITION_INFO *partition_info;
const MOTION_VECTOR_INFO *motion_vector_info;
const TplDepStats *tpl_stats_info;
IMAGE_BUFFER coded_frame;
RATE_QINDEX_HISTORY rq_history;
#endif // CONFIG_RATE_CTRL
int quantize_index;
} ENCODE_FRAME_RESULT;
void vp9_init_encode_frame_result(ENCODE_FRAME_RESULT *encode_frame_result);
void vp9_initialize_enc(void);
struct VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf,
void vp9_update_compressor_with_img_fmt(VP9_COMP *cpi, vpx_img_fmt_t img_fmt);
struct VP9_COMP *vp9_create_compressor(const VP9EncoderConfig *oxcf,
BufferPool *const pool);
void vp9_remove_compressor(VP9_COMP *cpi);
@@ -896,7 +1128,8 @@ int vp9_receive_raw_frame(VP9_COMP *cpi, vpx_enc_frame_flags_t frame_flags,
int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
size_t *size, uint8_t *dest, int64_t *time_stamp,
int64_t *time_end, int flush);
int64_t *time_end, int flush,
ENCODE_FRAME_RESULT *encode_frame_result);
int vp9_get_preview_raw_frame(VP9_COMP *cpi, YV12_BUFFER_CONFIG *dest,
vp9_ppflags_t *flags);
@@ -927,6 +1160,14 @@ int vp9_set_size_literal(VP9_COMP *cpi, unsigned int width,
void vp9_set_svc(VP9_COMP *cpi, int use_svc);
// Check for resetting the rc flags (rc_1_frame, rc_2_frame) if the
// configuration change has a large change in avg_frame_bandwidth.
// For SVC check for resetting based on spatial layer average bandwidth.
// Also reset buffer level to optimal level.
void vp9_check_reset_rc_flag(VP9_COMP *cpi);
void vp9_set_rc_buffer_sizes(VP9_COMP *cpi);
static INLINE int stack_pop(int *stack, int stack_size) {
int idx;
const int r = stack[0];
@@ -948,13 +1189,20 @@ static INLINE void stack_init(int *stack, int length) {
for (idx = 0; idx < length; ++idx) stack[idx] = -1;
}
int vp9_get_quantizer(struct VP9_COMP *cpi);
int vp9_get_quantizer(const VP9_COMP *cpi);
static INLINE int frame_is_kf_gf_arf(const VP9_COMP *cpi) {
return frame_is_intra_only(&cpi->common) || cpi->refresh_alt_ref_frame ||
(cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref);
}
static INLINE int ref_frame_to_flag(int8_t ref_frame) {
static const int kVp9RefFlagList[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
VP9_ALT_FLAG };
assert(ref_frame >= LAST_FRAME && ref_frame <= ALTREF_FRAME);
return kVp9RefFlagList[ref_frame];
}
static INLINE int get_ref_frame_map_idx(const VP9_COMP *cpi,
MV_REFERENCE_FRAME ref_frame) {
if (ref_frame == LAST_FRAME) {
@@ -973,10 +1221,22 @@ static INLINE int get_ref_frame_buf_idx(const VP9_COMP *const cpi,
return (map_idx != INVALID_IDX) ? cm->ref_frame_map[map_idx] : INVALID_IDX;
}
static INLINE RefCntBuffer *get_ref_cnt_buffer(VP9_COMMON *cm, int fb_idx) {
static INLINE RefCntBuffer *get_ref_cnt_buffer(const VP9_COMMON *cm,
int fb_idx) {
return fb_idx != INVALID_IDX ? &cm->buffer_pool->frame_bufs[fb_idx] : NULL;
}
static INLINE void get_ref_frame_bufs(
const VP9_COMP *cpi, RefCntBuffer *ref_frame_bufs[MAX_INTER_REF_FRAMES]) {
const VP9_COMMON *const cm = &cpi->common;
MV_REFERENCE_FRAME ref_frame;
for (ref_frame = LAST_FRAME; ref_frame < MAX_REF_FRAMES; ++ref_frame) {
int ref_frame_buf_idx = get_ref_frame_buf_idx(cpi, ref_frame);
int inter_ref_idx = mv_ref_frame_to_inter_ref_idx(ref_frame);
ref_frame_bufs[inter_ref_idx] = get_ref_cnt_buffer(cm, ref_frame_buf_idx);
}
}
static INLINE YV12_BUFFER_CONFIG *get_ref_frame_buffer(
const VP9_COMP *const cpi, MV_REFERENCE_FRAME ref_frame) {
const VP9_COMMON *const cm = &cpi->common;
@@ -1027,6 +1287,11 @@ void vp9_scale_references(VP9_COMP *cpi);
void vp9_update_reference_frames(VP9_COMP *cpi);
void vp9_get_ref_frame_info(FRAME_UPDATE_TYPE update_type, int ref_frame_flags,
RefCntBuffer *ref_frame_bufs[MAX_INTER_REF_FRAMES],
int *ref_frame_coding_indexes,
int *ref_frame_valid_list);
void vp9_set_high_precision_mv(VP9_COMP *cpi, int allow_high_precision_mv);
YV12_BUFFER_CONFIG *vp9_svc_twostage_scale(
@@ -1121,6 +1386,8 @@ void vp9_new_framerate(VP9_COMP *cpi, double framerate);
void vp9_set_row_mt(VP9_COMP *cpi);
int vp9_get_psnr(const VP9_COMP *cpi, PSNR_STATS *psnr);
#define LAYER_IDS_TO_IDX(sl, tl, num_tl) ((sl) * (num_tl) + (tl))
#ifdef __cplusplus
+73 -51
View File
@@ -8,6 +8,8 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vp9/common/vp9_thread_common.h"
#include "vp9/encoder/vp9_bitstream.h"
#include "vp9/encoder/vp9_encodeframe.h"
#include "vp9/encoder/vp9_encoder.h"
#include "vp9/encoder/vp9_ethread.h"
@@ -79,60 +81,59 @@ static void create_enc_workers(VP9_COMP *cpi, int num_workers) {
VP9_COMMON *const cm = &cpi->common;
const VPxWorkerInterface *const winterface = vpx_get_worker_interface();
int i;
// While using SVC, we need to allocate threads according to the highest
// resolution. When row based multithreading is enabled, it is OK to
// allocate more threads than the number of max tile columns.
if (cpi->use_svc && !cpi->row_mt) {
int max_tile_cols = get_max_tile_cols(cpi);
num_workers = VPXMIN(cpi->oxcf.max_threads, max_tile_cols);
}
assert(num_workers > 0);
if (num_workers == cpi->num_workers) return;
vp9_loop_filter_dealloc(&cpi->lf_row_sync);
vp9_bitstream_encode_tiles_buffer_dealloc(cpi);
vp9_encode_free_mt_data(cpi);
// Only run once to create threads and allocate thread data.
if (cpi->num_workers == 0) {
int allocated_workers = num_workers;
CHECK_MEM_ERROR(cm, cpi->workers,
vpx_malloc(num_workers * sizeof(*cpi->workers)));
// While using SVC, we need to allocate threads according to the highest
// resolution. When row based multithreading is enabled, it is OK to
// allocate more threads than the number of max tile columns.
if (cpi->use_svc && !cpi->row_mt) {
int max_tile_cols = get_max_tile_cols(cpi);
allocated_workers = VPXMIN(cpi->oxcf.max_threads, max_tile_cols);
}
CHECK_MEM_ERROR(cm, cpi->workers,
vpx_malloc(allocated_workers * sizeof(*cpi->workers)));
CHECK_MEM_ERROR(cm, cpi->tile_thr_data,
vpx_calloc(allocated_workers, sizeof(*cpi->tile_thr_data)));
for (i = 0; i < allocated_workers; i++) {
VPxWorker *const worker = &cpi->workers[i];
EncWorkerData *thread_data = &cpi->tile_thr_data[i];
++cpi->num_workers;
winterface->init(worker);
if (i < allocated_workers - 1) {
thread_data->cpi = cpi;
// Allocate thread data.
CHECK_MEM_ERROR(cm, thread_data->td,
vpx_memalign(32, sizeof(*thread_data->td)));
vp9_zero(*thread_data->td);
// Set up pc_tree.
thread_data->td->leaf_tree = NULL;
thread_data->td->pc_tree = NULL;
vp9_setup_pc_tree(cm, thread_data->td);
// Allocate frame counters in thread data.
CHECK_MEM_ERROR(cm, thread_data->td->counts,
vpx_calloc(1, sizeof(*thread_data->td->counts)));
// Create threads
if (!winterface->reset(worker))
vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
"Tile encoder thread creation failed");
} else {
// Main thread acts as a worker and uses the thread data in cpi.
thread_data->cpi = cpi;
thread_data->td = &cpi->td;
}
winterface->sync(worker);
CHECK_MEM_ERROR(cm, cpi->tile_thr_data,
vpx_calloc(num_workers, sizeof(*cpi->tile_thr_data)));
for (i = 0; i < num_workers; i++) {
VPxWorker *const worker = &cpi->workers[i];
EncWorkerData *thread_data = &cpi->tile_thr_data[i];
++cpi->num_workers;
winterface->init(worker);
if (i < num_workers - 1) {
thread_data->cpi = cpi;
// Allocate thread data.
CHECK_MEM_ERROR(cm, thread_data->td,
vpx_memalign(32, sizeof(*thread_data->td)));
vp9_zero(*thread_data->td);
// Set up pc_tree.
thread_data->td->leaf_tree = NULL;
thread_data->td->pc_tree = NULL;
vp9_setup_pc_tree(cm, thread_data->td);
// Allocate frame counters in thread data.
CHECK_MEM_ERROR(cm, thread_data->td->counts,
vpx_calloc(1, sizeof(*thread_data->td->counts)));
// Create threads
if (!winterface->reset(worker))
vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
"Tile encoder thread creation failed");
} else {
// Main thread acts as a worker and uses the thread data in cpi.
thread_data->cpi = cpi;
thread_data->td = &cpi->td;
}
winterface->sync(worker);
}
}
@@ -169,6 +170,27 @@ static void launch_enc_workers(VP9_COMP *cpi, VPxWorkerHook hook, void *data2,
}
}
void vp9_encode_free_mt_data(struct VP9_COMP *cpi) {
int t;
for (t = 0; t < cpi->num_workers; ++t) {
VPxWorker *const worker = &cpi->workers[t];
EncWorkerData *const thread_data = &cpi->tile_thr_data[t];
// Deallocate allocated threads.
vpx_get_worker_interface()->end(worker);
// Deallocate allocated thread data.
if (t < cpi->num_workers - 1) {
vpx_free(thread_data->td->counts);
vp9_free_pc_tree(thread_data->td);
vpx_free(thread_data->td);
}
}
vpx_free(cpi->tile_thr_data);
vpx_free(cpi->workers);
cpi->num_workers = 0;
}
void vp9_encode_tiles_mt(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
const int tile_cols = 1 << cm->log2_tile_cols;
+5
View File
@@ -42,6 +42,11 @@ typedef struct VP9RowMTSyncData {
int rows;
} VP9RowMTSync;
// Frees EncWorkerData related allocations made by vp9_encode_*_mt().
// row_mt specific data is freed with vp9_row_mt_mem_dealloc() and is not
// called by this function.
void vp9_encode_free_mt_data(struct VP9_COMP *cpi);
void vp9_encode_tiles_mt(struct VP9_COMP *cpi);
void vp9_encode_tiles_row_mt(struct VP9_COMP *cpi);
+200
View File
@@ -0,0 +1,200 @@
/*
* Copyright (c) 2020 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vp9/encoder/vp9_ext_ratectrl.h"
#include "vp9/encoder/vp9_encoder.h"
#include "vp9/common/vp9_common.h"
#include "vpx_dsp/psnr.h"
vpx_codec_err_t vp9_extrc_init(EXT_RATECTRL *ext_ratectrl) {
if (ext_ratectrl == NULL) {
return VPX_CODEC_INVALID_PARAM;
}
vp9_zero(*ext_ratectrl);
return VPX_CODEC_OK;
}
vpx_codec_err_t vp9_extrc_create(vpx_rc_funcs_t funcs,
vpx_rc_config_t ratectrl_config,
EXT_RATECTRL *ext_ratectrl) {
vpx_rc_status_t rc_status;
vpx_rc_firstpass_stats_t *rc_firstpass_stats;
if (ext_ratectrl == NULL) {
return VPX_CODEC_INVALID_PARAM;
}
vp9_extrc_delete(ext_ratectrl);
ext_ratectrl->funcs = funcs;
ext_ratectrl->ratectrl_config = ratectrl_config;
rc_status = ext_ratectrl->funcs.create_model(ext_ratectrl->funcs.priv,
&ext_ratectrl->ratectrl_config,
&ext_ratectrl->model);
if (rc_status == VPX_RC_ERROR) {
return VPX_CODEC_ERROR;
}
rc_firstpass_stats = &ext_ratectrl->rc_firstpass_stats;
rc_firstpass_stats->num_frames = ratectrl_config.show_frame_count;
rc_firstpass_stats->frame_stats =
vpx_malloc(sizeof(*rc_firstpass_stats->frame_stats) *
rc_firstpass_stats->num_frames);
if (rc_firstpass_stats->frame_stats == NULL) {
return VPX_CODEC_MEM_ERROR;
}
ext_ratectrl->ready = 1;
return VPX_CODEC_OK;
}
vpx_codec_err_t vp9_extrc_delete(EXT_RATECTRL *ext_ratectrl) {
if (ext_ratectrl == NULL) {
return VPX_CODEC_INVALID_PARAM;
}
if (ext_ratectrl->ready) {
vpx_rc_status_t rc_status =
ext_ratectrl->funcs.delete_model(ext_ratectrl->model);
if (rc_status == VPX_RC_ERROR) {
return VPX_CODEC_ERROR;
}
vpx_free(ext_ratectrl->rc_firstpass_stats.frame_stats);
}
return vp9_extrc_init(ext_ratectrl);
}
static void gen_rc_firstpass_stats(const FIRSTPASS_STATS *stats,
vpx_rc_frame_stats_t *rc_frame_stats) {
rc_frame_stats->frame = stats->frame;
rc_frame_stats->weight = stats->weight;
rc_frame_stats->intra_error = stats->intra_error;
rc_frame_stats->coded_error = stats->coded_error;
rc_frame_stats->sr_coded_error = stats->sr_coded_error;
rc_frame_stats->frame_noise_energy = stats->frame_noise_energy;
rc_frame_stats->pcnt_inter = stats->pcnt_inter;
rc_frame_stats->pcnt_motion = stats->pcnt_motion;
rc_frame_stats->pcnt_second_ref = stats->pcnt_second_ref;
rc_frame_stats->pcnt_neutral = stats->pcnt_neutral;
rc_frame_stats->pcnt_intra_low = stats->pcnt_intra_low;
rc_frame_stats->pcnt_intra_high = stats->pcnt_intra_high;
rc_frame_stats->intra_skip_pct = stats->intra_skip_pct;
rc_frame_stats->intra_smooth_pct = stats->intra_smooth_pct;
rc_frame_stats->inactive_zone_rows = stats->inactive_zone_rows;
rc_frame_stats->inactive_zone_cols = stats->inactive_zone_cols;
rc_frame_stats->MVr = stats->MVr;
rc_frame_stats->mvr_abs = stats->mvr_abs;
rc_frame_stats->MVc = stats->MVc;
rc_frame_stats->mvc_abs = stats->mvc_abs;
rc_frame_stats->MVrv = stats->MVrv;
rc_frame_stats->MVcv = stats->MVcv;
rc_frame_stats->mv_in_out_count = stats->mv_in_out_count;
rc_frame_stats->duration = stats->duration;
rc_frame_stats->count = stats->count;
}
vpx_codec_err_t vp9_extrc_send_firstpass_stats(
EXT_RATECTRL *ext_ratectrl, const FIRST_PASS_INFO *first_pass_info) {
if (ext_ratectrl == NULL) {
return VPX_CODEC_INVALID_PARAM;
}
if (ext_ratectrl->ready) {
vpx_rc_status_t rc_status;
vpx_rc_firstpass_stats_t *rc_firstpass_stats =
&ext_ratectrl->rc_firstpass_stats;
int i;
assert(rc_firstpass_stats->num_frames == first_pass_info->num_frames);
for (i = 0; i < rc_firstpass_stats->num_frames; ++i) {
gen_rc_firstpass_stats(&first_pass_info->stats[i],
&rc_firstpass_stats->frame_stats[i]);
}
rc_status = ext_ratectrl->funcs.send_firstpass_stats(ext_ratectrl->model,
rc_firstpass_stats);
if (rc_status == VPX_RC_ERROR) {
return VPX_CODEC_ERROR;
}
}
return VPX_CODEC_OK;
}
static int extrc_get_frame_type(FRAME_UPDATE_TYPE update_type) {
// TODO(angiebird): Add unit test to make sure this function behaves like
// get_frame_type_from_update_type()
// TODO(angiebird): Merge this function with get_frame_type_from_update_type()
switch (update_type) {
case KF_UPDATE: return 0; // kFrameTypeKey;
case ARF_UPDATE: return 2; // kFrameTypeAltRef;
case GF_UPDATE: return 4; // kFrameTypeGolden;
case OVERLAY_UPDATE: return 3; // kFrameTypeOverlay;
case LF_UPDATE: return 1; // kFrameTypeInter;
default:
fprintf(stderr, "Unsupported update_type %d\n", update_type);
abort();
return 1;
}
}
vpx_codec_err_t vp9_extrc_get_encodeframe_decision(
EXT_RATECTRL *ext_ratectrl, int show_index, int coding_index, int gop_index,
FRAME_UPDATE_TYPE update_type,
RefCntBuffer *ref_frame_bufs[MAX_INTER_REF_FRAMES], int ref_frame_flags,
vpx_rc_encodeframe_decision_t *encode_frame_decision) {
if (ext_ratectrl == NULL) {
return VPX_CODEC_INVALID_PARAM;
}
if (ext_ratectrl->ready) {
vpx_rc_status_t rc_status;
vpx_rc_encodeframe_info_t encode_frame_info;
encode_frame_info.show_index = show_index;
encode_frame_info.coding_index = coding_index;
encode_frame_info.gop_index = gop_index;
encode_frame_info.frame_type = extrc_get_frame_type(update_type);
vp9_get_ref_frame_info(update_type, ref_frame_flags, ref_frame_bufs,
encode_frame_info.ref_frame_coding_indexes,
encode_frame_info.ref_frame_valid_list);
rc_status = ext_ratectrl->funcs.get_encodeframe_decision(
ext_ratectrl->model, &encode_frame_info, encode_frame_decision);
if (rc_status == VPX_RC_ERROR) {
return VPX_CODEC_ERROR;
}
}
return VPX_CODEC_OK;
}
vpx_codec_err_t vp9_extrc_update_encodeframe_result(
EXT_RATECTRL *ext_ratectrl, int64_t bit_count,
const YV12_BUFFER_CONFIG *source_frame,
const YV12_BUFFER_CONFIG *coded_frame, uint32_t bit_depth,
uint32_t input_bit_depth, const int actual_encoding_qindex) {
if (ext_ratectrl == NULL) {
return VPX_CODEC_INVALID_PARAM;
}
if (ext_ratectrl->ready) {
PSNR_STATS psnr;
vpx_rc_status_t rc_status;
vpx_rc_encodeframe_result_t encode_frame_result;
encode_frame_result.bit_count = bit_count;
encode_frame_result.pixel_count =
source_frame->y_crop_width * source_frame->y_crop_height +
2 * source_frame->uv_crop_width * source_frame->uv_crop_height;
encode_frame_result.actual_encoding_qindex = actual_encoding_qindex;
#if CONFIG_VP9_HIGHBITDEPTH
vpx_calc_highbd_psnr(source_frame, coded_frame, &psnr, bit_depth,
input_bit_depth);
#else
(void)bit_depth;
(void)input_bit_depth;
vpx_calc_psnr(source_frame, coded_frame, &psnr);
#endif
encode_frame_result.sse = psnr.sse[0];
rc_status = ext_ratectrl->funcs.update_encodeframe_result(
ext_ratectrl->model, &encode_frame_result);
if (rc_status == VPX_RC_ERROR) {
return VPX_CODEC_ERROR;
}
}
return VPX_CODEC_OK;
}
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2020 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP9_ENCODER_VP9_EXT_RATECTRL_H_
#define VPX_VP9_ENCODER_VP9_EXT_RATECTRL_H_
#include "vpx/vpx_ext_ratectrl.h"
#include "vp9/encoder/vp9_firstpass.h"
typedef struct EXT_RATECTRL {
int ready;
vpx_rc_model_t model;
vpx_rc_funcs_t funcs;
vpx_rc_config_t ratectrl_config;
vpx_rc_firstpass_stats_t rc_firstpass_stats;
} EXT_RATECTRL;
vpx_codec_err_t vp9_extrc_init(EXT_RATECTRL *ext_ratectrl);
vpx_codec_err_t vp9_extrc_create(vpx_rc_funcs_t funcs,
vpx_rc_config_t ratectrl_config,
EXT_RATECTRL *ext_ratectrl);
vpx_codec_err_t vp9_extrc_delete(EXT_RATECTRL *ext_ratectrl);
vpx_codec_err_t vp9_extrc_send_firstpass_stats(
EXT_RATECTRL *ext_ratectrl, const FIRST_PASS_INFO *first_pass_info);
vpx_codec_err_t vp9_extrc_get_encodeframe_decision(
EXT_RATECTRL *ext_ratectrl, int show_index, int coding_index, int gop_index,
FRAME_UPDATE_TYPE update_type,
RefCntBuffer *ref_frame_bufs[MAX_INTER_REF_FRAMES], int ref_frame_flags,
vpx_rc_encodeframe_decision_t *encode_frame_decision);
vpx_codec_err_t vp9_extrc_update_encodeframe_result(
EXT_RATECTRL *ext_ratectrl, int64_t bit_count,
const YV12_BUFFER_CONFIG *source_frame,
const YV12_BUFFER_CONFIG *coded_frame, uint32_t bit_depth,
uint32_t input_bit_depth, const int actual_encoding_qindex);
#endif // VPX_VP9_ENCODER_VP9_EXT_RATECTRL_H_
+22 -10
View File
@@ -18,18 +18,26 @@
static void copy_and_extend_plane(const uint8_t *src, int src_pitch,
uint8_t *dst, int dst_pitch, int w, int h,
int extend_top, int extend_left,
int extend_bottom, int extend_right) {
int i, linesize;
int extend_bottom, int extend_right,
int interleave_step) {
int i, j, linesize;
const int step = interleave_step < 1 ? 1 : interleave_step;
// copy the left and right most columns out
const uint8_t *src_ptr1 = src;
const uint8_t *src_ptr2 = src + w - 1;
const uint8_t *src_ptr2 = src + (w - 1) * step;
uint8_t *dst_ptr1 = dst - extend_left;
uint8_t *dst_ptr2 = dst + w;
for (i = 0; i < h; i++) {
memset(dst_ptr1, src_ptr1[0], extend_left);
memcpy(dst_ptr1 + extend_left, src_ptr1, w);
if (step == 1) {
memcpy(dst_ptr1 + extend_left, src_ptr1, w);
} else {
for (j = 0; j < w; j++) {
dst_ptr1[extend_left + j] = src_ptr1[step * j];
}
}
memset(dst_ptr2, src_ptr2[0], extend_right);
src_ptr1 += src_pitch;
src_ptr2 += src_pitch;
@@ -122,6 +130,8 @@ void vp9_copy_and_extend_frame(const YV12_BUFFER_CONFIG *src,
const int el_uv = el_y >> uv_width_subsampling;
const int eb_uv = eb_y >> uv_height_subsampling;
const int er_uv = er_y >> uv_width_subsampling;
// detect nv12 colorspace
const int chroma_step = src->v_buffer - src->u_buffer == 1 ? 2 : 1;
#if CONFIG_VP9_HIGHBITDEPTH
if (src->flags & YV12_FLAG_HIGHBITDEPTH) {
@@ -142,15 +152,15 @@ void vp9_copy_and_extend_frame(const YV12_BUFFER_CONFIG *src,
copy_and_extend_plane(src->y_buffer, src->y_stride, dst->y_buffer,
dst->y_stride, src->y_crop_width, src->y_crop_height,
et_y, el_y, eb_y, er_y);
et_y, el_y, eb_y, er_y, 1);
copy_and_extend_plane(src->u_buffer, src->uv_stride, dst->u_buffer,
dst->uv_stride, src->uv_crop_width, src->uv_crop_height,
et_uv, el_uv, eb_uv, er_uv);
et_uv, el_uv, eb_uv, er_uv, chroma_step);
copy_and_extend_plane(src->v_buffer, src->uv_stride, dst->v_buffer,
dst->uv_stride, src->uv_crop_width, src->uv_crop_height,
et_uv, el_uv, eb_uv, er_uv);
et_uv, el_uv, eb_uv, er_uv, chroma_step);
}
void vp9_copy_and_extend_frame_with_rect(const YV12_BUFFER_CONFIG *src,
@@ -176,16 +186,18 @@ void vp9_copy_and_extend_frame_with_rect(const YV12_BUFFER_CONFIG *src,
const int dst_uv_offset = ((srcy * dst->uv_stride) >> 1) + (srcx >> 1);
const int srch_uv = ROUND_POWER_OF_TWO(srch, 1);
const int srcw_uv = ROUND_POWER_OF_TWO(srcw, 1);
// detect nv12 colorspace
const int chroma_step = src->v_buffer - src->u_buffer == 1 ? 2 : 1;
copy_and_extend_plane(src->y_buffer + src_y_offset, src->y_stride,
dst->y_buffer + dst_y_offset, dst->y_stride, srcw, srch,
et_y, el_y, eb_y, er_y);
et_y, el_y, eb_y, er_y, 1);
copy_and_extend_plane(src->u_buffer + src_uv_offset, src->uv_stride,
dst->u_buffer + dst_uv_offset, dst->uv_stride, srcw_uv,
srch_uv, et_uv, el_uv, eb_uv, er_uv);
srch_uv, et_uv, el_uv, eb_uv, er_uv, chroma_step);
copy_and_extend_plane(src->v_buffer + src_uv_offset, src->uv_stride,
dst->v_buffer + dst_uv_offset, dst->uv_stride, srcw_uv,
srch_uv, et_uv, el_uv, eb_uv, er_uv);
srch_uv, et_uv, el_uv, eb_uv, er_uv, chroma_step);
}
File diff suppressed because it is too large. Load diff
+102 -27
View File
@@ -13,6 +13,7 @@
#include <assert.h>
#include "vp9/common/vp9_onyxc_int.h"
#include "vp9/encoder/vp9_lookahead.h"
#include "vp9/encoder/vp9_ratectrl.h"
@@ -20,27 +21,6 @@
extern "C" {
#endif
#if CONFIG_FP_MB_STATS
#define FPMB_DCINTRA_MASK 0x01
#define FPMB_MOTION_ZERO_MASK 0x02
#define FPMB_MOTION_LEFT_MASK 0x04
#define FPMB_MOTION_RIGHT_MASK 0x08
#define FPMB_MOTION_UP_MASK 0x10
#define FPMB_MOTION_DOWN_MASK 0x20
#define FPMB_ERROR_SMALL_MASK 0x40
#define FPMB_ERROR_LARGE_MASK 0x80
#define FPMB_ERROR_SMALL_TH 2000
#define FPMB_ERROR_LARGE_TH 48000
typedef struct {
uint8_t *mb_stats_start;
uint8_t *mb_stats_end;
} FIRSTPASS_MB_STATS;
#endif
#define INVALID_ROW (-1)
#define MAX_ARF_LAYERS 6
@@ -146,6 +126,30 @@ typedef struct {
int group_noise_energy;
} GF_GROUP;
typedef struct {
const FIRSTPASS_STATS *stats;
int num_frames;
} FIRST_PASS_INFO;
static INLINE void fps_init_first_pass_info(FIRST_PASS_INFO *first_pass_info,
const FIRSTPASS_STATS *stats,
int num_frames) {
first_pass_info->stats = stats;
first_pass_info->num_frames = num_frames;
}
static INLINE int fps_get_num_frames(const FIRST_PASS_INFO *first_pass_info) {
return first_pass_info->num_frames;
}
static INLINE const FIRSTPASS_STATS *fps_get_frame_stats(
const FIRST_PASS_INFO *first_pass_info, int show_idx) {
if (show_idx < 0 || show_idx >= first_pass_info->num_frames) {
return NULL;
}
return &first_pass_info->stats[show_idx];
}
typedef struct {
unsigned int section_intra_rating;
unsigned int key_frame_section_intra_rating;
@@ -154,6 +158,7 @@ typedef struct {
const FIRSTPASS_STATS *stats_in;
const FIRSTPASS_STATS *stats_in_start;
const FIRSTPASS_STATS *stats_in_end;
FIRST_PASS_INFO first_pass_info;
FIRSTPASS_STATS total_left_stats;
int first_pass_done;
int64_t bits_left;
@@ -162,12 +167,6 @@ typedef struct {
double mb_av_energy;
double mb_smooth_pct;
#if CONFIG_FP_MB_STATS
uint8_t *frame_mb_stats_buf;
uint8_t *this_frame_mb_stats;
FIRSTPASS_MB_STATS firstpass_mb_stats;
#endif
FP_MB_FLOAT_STATS *fp_mb_float_stats;
// An indication of the content type of the current frame
@@ -192,8 +191,27 @@ typedef struct {
int extend_maxq;
int extend_minq_fast;
int arnr_strength_adjustment;
int last_qindex_of_arf_layer[MAX_ARF_LAYERS];
GF_GROUP gf_group;
// Vizeir project experimental two pass rate control parameters.
// When |use_vizier_rc_params| is 1, the following parameters will
// be overwritten by pass in values. Otherwise, they are initialized
// by default values.
int use_vizier_rc_params;
double active_wq_factor;
double err_per_mb;
double sr_default_decay_limit;
double sr_diff_factor;
double kf_err_per_mb;
double kf_frame_min_boost;
double kf_frame_max_boost_first; // Max for first kf in a chunk.
double kf_frame_max_boost_subs; // Max for subsequent mid chunk kfs.
double kf_max_total_boost;
double gf_max_total_boost;
double gf_frame_max_boost;
double zm_factor;
} TWO_PASS;
struct VP9_COMP;
@@ -212,6 +230,7 @@ void vp9_first_pass_encode_tile_mb_row(struct VP9_COMP *cpi,
void vp9_init_second_pass(struct VP9_COMP *cpi);
void vp9_rc_get_second_pass_params(struct VP9_COMP *cpi);
void vp9_init_vizier_params(TWO_PASS *const twopass, int screen_area);
// Post encode update of the rate control parameters for 2-pass
void vp9_twopass_postencode_update(struct VP9_COMP *cpi);
@@ -219,6 +238,62 @@ void vp9_twopass_postencode_update(struct VP9_COMP *cpi);
void calculate_coded_size(struct VP9_COMP *cpi, int *scaled_frame_width,
int *scaled_frame_height);
struct VP9EncoderConfig;
int vp9_get_frames_to_next_key(const struct VP9EncoderConfig *oxcf,
const TWO_PASS *const twopass, int kf_show_idx,
int min_gf_interval);
#if CONFIG_RATE_CTRL
/* Call this function to get info about the next group of pictures.
* This function should be called after vp9_create_compressor() when encoding
* starts or after vp9_get_compressed_data() when the encoding process of
* the last group of pictures is just finished.
*/
void vp9_get_next_group_of_picture(const struct VP9_COMP *cpi,
int *first_is_key_frame, int *use_alt_ref,
int *coding_frame_count, int *first_show_idx,
int *last_gop_use_alt_ref);
/*!\brief Call this function before coding a new group of pictures to get
* information about it.
* \param[in] oxcf Encoder config
* \param[in] twopass Twopass info
* \param[in] frame_info Frame info
* \param[in] rc Rate control state
* \param[in] show_idx Show index of the first frame in the group
* \param[in] multi_layer_arf Is multi-layer alternate reference used
* \param[in] allow_alt_ref Is alternate reference allowed
* \param[in] first_is_key_frame Is the first frame in the group a key frame
* \param[in] last_gop_use_alt_ref Does the last group use alternate reference
*
* \param[out] use_alt_ref Does this group use alternate reference
*
* \return Returns coding frame count
*/
int vp9_get_gop_coding_frame_count(const struct VP9EncoderConfig *oxcf,
const TWO_PASS *const twopass,
const FRAME_INFO *frame_info,
const RATE_CONTROL *rc, int show_idx,
int multi_layer_arf, int allow_alt_ref,
int first_is_key_frame,
int last_gop_use_alt_ref, int *use_alt_ref);
int vp9_get_coding_frame_num(const struct VP9EncoderConfig *oxcf,
const TWO_PASS *const twopass,
const FRAME_INFO *frame_info, int multi_layer_arf,
int allow_alt_ref);
/*!\brief Compute a key frame binary map indicates whether key frames appear
* in the corresponding positions. The passed in key_frame_map must point to an
* integer array with length equal to twopass->first_pass_info.num_frames,
* which is the number of show frames in the video.
*/
void vp9_get_key_frame_map(const struct VP9EncoderConfig *oxcf,
const TWO_PASS *const twopass, int *key_frame_map);
#endif // CONFIG_RATE_CTRL
FIRSTPASS_STATS vp9_get_frame_stats(const TWO_PASS *twopass);
FIRSTPASS_STATS vp9_get_total_stats(const TWO_PASS *twopass);
#ifdef __cplusplus
} // extern "C"
#endif
+16 -5
View File
@@ -64,6 +64,7 @@ struct lookahead_ctx *vp9_lookahead_init(unsigned int width,
unsigned int i;
ctx->max_sz = depth;
ctx->buf = calloc(depth, sizeof(*ctx->buf));
ctx->next_show_idx = 0;
if (!ctx->buf) goto bail;
for (i = 0; i < depth; i++)
if (vpx_alloc_frame_buffer(
@@ -81,12 +82,16 @@ bail:
}
#define USE_PARTIAL_COPY 0
int vp9_lookahead_full(const struct lookahead_ctx *ctx) {
return ctx->sz + 1 + MAX_PRE_FRAMES > ctx->max_sz;
}
int vp9_lookahead_next_show_idx(const struct lookahead_ctx *ctx) {
return ctx->next_show_idx;
}
int vp9_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
int64_t ts_start, int64_t ts_end,
#if CONFIG_VP9_HIGHBITDEPTH
int use_highbitdepth,
#endif
int64_t ts_start, int64_t ts_end, int use_highbitdepth,
vpx_enc_frame_flags_t flags) {
struct lookahead_entry *buf;
#if USE_PARTIAL_COPY
@@ -101,8 +106,12 @@ int vp9_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
int subsampling_x = src->subsampling_x;
int subsampling_y = src->subsampling_y;
int larger_dimensions, new_dimensions;
#if !CONFIG_VP9_HIGHBITDEPTH
(void)use_highbitdepth;
assert(use_highbitdepth == 0);
#endif
if (ctx->sz + 1 + MAX_PRE_FRAMES > ctx->max_sz) return 1;
if (vp9_lookahead_full(ctx)) return 1;
ctx->sz++;
buf = pop(ctx, &ctx->write_idx);
@@ -184,6 +193,8 @@ int vp9_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
buf->ts_start = ts_start;
buf->ts_end = ts_end;
buf->flags = flags;
buf->show_idx = ctx->next_show_idx;
++ctx->next_show_idx;
return 0;
}
+25 -12
View File
@@ -25,6 +25,7 @@ struct lookahead_entry {
YV12_BUFFER_CONFIG img;
int64_t ts_start;
int64_t ts_end;
int show_idx; /*The show_idx of this frame*/
vpx_enc_frame_flags_t flags;
};
@@ -32,10 +33,12 @@ struct lookahead_entry {
#define MAX_PRE_FRAMES 1
struct lookahead_ctx {
int max_sz; /* Absolute size of the queue */
int sz; /* Number of buffers currently in the queue */
int read_idx; /* Read index */
int write_idx; /* Write index */
int max_sz; /* Absolute size of the queue */
int sz; /* Number of buffers currently in the queue */
int read_idx; /* Read index */
int write_idx; /* Write index */
int next_show_idx; /* The show_idx that will be assigned to the next frame
being pushed in the queue*/
struct lookahead_entry *buf; /* Buffer list */
};
@@ -57,26 +60,36 @@ struct lookahead_ctx *vp9_lookahead_init(unsigned int width,
*/
void vp9_lookahead_destroy(struct lookahead_ctx *ctx);
/**\brief Check if lookahead is full
*
* \param[in] ctx Pointer to the lookahead context
*
* Return 1 if lookahead is full, otherwise return 0.
*/
int vp9_lookahead_full(const struct lookahead_ctx *ctx);
/**\brief Return the next_show_idx
*
* \param[in] ctx Pointer to the lookahead context
*
* Return the show_idx that will be assigned to the next
* frame pushed by vp9_lookahead_push()
*/
int vp9_lookahead_next_show_idx(const struct lookahead_ctx *ctx);
/**\brief Enqueue a source buffer
*
* This function will copy the source image into a new framebuffer with
* the expected stride/border.
*
* If active_map is non-NULL and there is only one frame in the queue, then copy
* only active macroblocks.
*
* \param[in] ctx Pointer to the lookahead context
* \param[in] src Pointer to the image to enqueue
* \param[in] ts_start Timestamp for the start of this frame
* \param[in] ts_end Timestamp for the end of this frame
* \param[in] flags Flags set on this frame
* \param[in] active_map Map that specifies which macroblock is active
*/
int vp9_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
int64_t ts_start, int64_t ts_end,
#if CONFIG_VP9_HIGHBITDEPTH
int use_highbitdepth,
#endif
int64_t ts_start, int64_t ts_end, int use_highbitdepth,
vpx_enc_frame_flags_t flags);
/**\brief Get the next source buffer to encode
+1 -7
View File
@@ -219,7 +219,7 @@ static void update_mbgraph_frame_stats(VP9_COMP *cpi,
VP9_COMMON *const cm = &cpi->common;
int mb_col, mb_row, offset = 0;
int mb_y_offset = 0, arf_y_offset = 0, gld_y_offset = 0;
int mb_y_offset = 0;
MV gld_top_mv = { 0, 0 };
MODE_INFO mi_local;
MODE_INFO mi_above, mi_left;
@@ -243,8 +243,6 @@ static void update_mbgraph_frame_stats(VP9_COMP *cpi,
for (mb_row = 0; mb_row < cm->mb_rows; mb_row++) {
MV gld_left_mv = gld_top_mv;
int mb_y_in_offset = mb_y_offset;
int arf_y_in_offset = arf_y_offset;
int gld_y_in_offset = gld_y_offset;
// Set up limit values for motion vectors to prevent them extending outside
// the UMV borders.
@@ -266,8 +264,6 @@ static void update_mbgraph_frame_stats(VP9_COMP *cpi,
xd->left_mi = &mi_left;
mb_y_in_offset += 16;
gld_y_in_offset += 16;
arf_y_in_offset += 16;
x->mv_limits.col_min -= 16;
x->mv_limits.col_max -= 16;
}
@@ -276,8 +272,6 @@ static void update_mbgraph_frame_stats(VP9_COMP *cpi,
xd->above_mi = &mi_above;
mb_y_offset += buf->y_stride * 16;
gld_y_offset += golden_ref->y_stride * 16;
if (alt_ref) arf_y_offset += alt_ref->y_stride * 16;
x->mv_limits.row_min -= 16;
x->mv_limits.row_max -= 16;
offset += cm->mb_cols;
+306 -454
View File
@@ -159,59 +159,63 @@ static INLINE const uint8_t *pre(const uint8_t *buf, int stride, int r, int c) {
#if CONFIG_VP9_HIGHBITDEPTH
/* checks if (r, c) has better score than previous best */
#define CHECK_BETTER(v, r, c) \
if (c >= minc && c <= maxc && r >= minr && r <= maxr) { \
int64_t tmpmse; \
const MV mv = { r, c }; \
const MV ref_mv = { rr, rc }; \
if (second_pred == NULL) { \
thismse = vfp->svf(pre(y, y_stride, r, c), y_stride, sp(c), sp(r), z, \
src_stride, &sse); \
} else { \
thismse = vfp->svaf(pre(y, y_stride, r, c), y_stride, sp(c), sp(r), z, \
src_stride, &sse, second_pred); \
} \
tmpmse = thismse; \
tmpmse += mv_err_cost(&mv, &ref_mv, mvjcost, mvcost, error_per_bit); \
if (tmpmse >= INT_MAX) { \
v = INT_MAX; \
} else if ((v = (uint32_t)tmpmse) < besterr) { \
besterr = v; \
br = r; \
bc = c; \
*distortion = thismse; \
*sse1 = sse; \
} \
} else { \
v = INT_MAX; \
}
#define CHECK_BETTER(v, r, c) \
do { \
if (c >= minc && c <= maxc && r >= minr && r <= maxr) { \
int64_t tmpmse; \
const MV mv = { r, c }; \
const MV ref_mv = { rr, rc }; \
if (second_pred == NULL) { \
thismse = vfp->svf(pre(y, y_stride, r, c), y_stride, sp(c), sp(r), z, \
src_stride, &sse); \
} else { \
thismse = vfp->svaf(pre(y, y_stride, r, c), y_stride, sp(c), sp(r), z, \
src_stride, &sse, second_pred); \
} \
tmpmse = thismse; \
tmpmse += mv_err_cost(&mv, &ref_mv, mvjcost, mvcost, error_per_bit); \
if (tmpmse >= INT_MAX) { \
v = INT_MAX; \
} else if ((v = (uint32_t)tmpmse) < besterr) { \
besterr = v; \
br = r; \
bc = c; \
*distortion = thismse; \
*sse1 = sse; \
} \
} else { \
v = INT_MAX; \
} \
} while (0)
#else
/* checks if (r, c) has better score than previous best */
#define CHECK_BETTER(v, r, c) \
if (c >= minc && c <= maxc && r >= minr && r <= maxr) { \
const MV mv = { r, c }; \
const MV ref_mv = { rr, rc }; \
if (second_pred == NULL) \
thismse = vfp->svf(pre(y, y_stride, r, c), y_stride, sp(c), sp(r), z, \
src_stride, &sse); \
else \
thismse = vfp->svaf(pre(y, y_stride, r, c), y_stride, sp(c), sp(r), z, \
src_stride, &sse, second_pred); \
if ((v = mv_err_cost(&mv, &ref_mv, mvjcost, mvcost, error_per_bit) + \
thismse) < besterr) { \
besterr = v; \
br = r; \
bc = c; \
*distortion = thismse; \
*sse1 = sse; \
} \
} else { \
v = INT_MAX; \
}
#define CHECK_BETTER(v, r, c) \
do { \
if (c >= minc && c <= maxc && r >= minr && r <= maxr) { \
const MV mv = { r, c }; \
const MV ref_mv = { rr, rc }; \
if (second_pred == NULL) \
thismse = vfp->svf(pre(y, y_stride, r, c), y_stride, sp(c), sp(r), z, \
src_stride, &sse); \
else \
thismse = vfp->svaf(pre(y, y_stride, r, c), y_stride, sp(c), sp(r), z, \
src_stride, &sse, second_pred); \
if ((v = mv_err_cost(&mv, &ref_mv, mvjcost, mvcost, error_per_bit) + \
thismse) < besterr) { \
besterr = v; \
br = r; \
bc = c; \
*distortion = thismse; \
*sse1 = sse; \
} \
} else { \
v = INT_MAX; \
} \
} while (0)
#endif
#define FIRST_LEVEL_CHECKS \
{ \
do { \
unsigned int left, right, up, down, diag; \
CHECK_BETTER(left, tr, tc - hstep); \
CHECK_BETTER(right, tr, tc + hstep); \
@@ -224,10 +228,10 @@ static INLINE const uint8_t *pre(const uint8_t *buf, int stride, int r, int c) {
case 2: CHECK_BETTER(diag, tr + hstep, tc - hstep); break; \
case 3: CHECK_BETTER(diag, tr + hstep, tc + hstep); break; \
} \
}
} while (0)
#define SECOND_LEVEL_CHECKS \
{ \
do { \
int kr, kc; \
unsigned int second; \
if (tr != br && tc != bc) { \
@@ -256,7 +260,7 @@ static INLINE const uint8_t *pre(const uint8_t *buf, int stride, int r, int c) {
case 3: CHECK_BETTER(second, tr + kr, tc - hstep); break; \
} \
} \
}
} while (0)
#define SETUP_SUBPEL_SEARCH \
const uint8_t *const z = x->plane[0].src.buf; \
@@ -290,7 +294,7 @@ static INLINE const uint8_t *pre(const uint8_t *buf, int stride, int r, int c) {
maxr = subpel_mv_limits.row_max; \
\
bestmv->row *= 8; \
bestmv->col *= 8;
bestmv->col *= 8
static unsigned int setup_center_error(
const MACROBLOCKD *xd, const MV *bestmv, const MV *ref_mv,
@@ -678,48 +682,52 @@ static int accurate_sub_pel_search(
// TODO(yunqing): this part can be further refactored.
#if CONFIG_VP9_HIGHBITDEPTH
/* checks if (r, c) has better score than previous best */
#define CHECK_BETTER1(v, r, c) \
if (c >= minc && c <= maxc && r >= minr && r <= maxr) { \
int64_t tmpmse; \
const MV mv = { r, c }; \
const MV ref_mv = { rr, rc }; \
thismse = \
accurate_sub_pel_search(xd, &mv, x->me_sf, kernel, vfp, z, src_stride, \
y, y_stride, second_pred, w, h, &sse); \
tmpmse = thismse; \
tmpmse += mv_err_cost(&mv, &ref_mv, mvjcost, mvcost, error_per_bit); \
if (tmpmse >= INT_MAX) { \
v = INT_MAX; \
} else if ((v = (uint32_t)tmpmse) < besterr) { \
besterr = v; \
br = r; \
bc = c; \
*distortion = thismse; \
*sse1 = sse; \
} \
} else { \
v = INT_MAX; \
}
#define CHECK_BETTER1(v, r, c) \
do { \
if (c >= minc && c <= maxc && r >= minr && r <= maxr) { \
int64_t tmpmse; \
const MV mv = { r, c }; \
const MV ref_mv = { rr, rc }; \
thismse = accurate_sub_pel_search(xd, &mv, x->me_sf, kernel, vfp, z, \
src_stride, y, y_stride, second_pred, \
w, h, &sse); \
tmpmse = thismse; \
tmpmse += mv_err_cost(&mv, &ref_mv, mvjcost, mvcost, error_per_bit); \
if (tmpmse >= INT_MAX) { \
v = INT_MAX; \
} else if ((v = (uint32_t)tmpmse) < besterr) { \
besterr = v; \
br = r; \
bc = c; \
*distortion = thismse; \
*sse1 = sse; \
} \
} else { \
v = INT_MAX; \
} \
} while (0)
#else
/* checks if (r, c) has better score than previous best */
#define CHECK_BETTER1(v, r, c) \
if (c >= minc && c <= maxc && r >= minr && r <= maxr) { \
const MV mv = { r, c }; \
const MV ref_mv = { rr, rc }; \
thismse = \
accurate_sub_pel_search(xd, &mv, x->me_sf, kernel, vfp, z, src_stride, \
y, y_stride, second_pred, w, h, &sse); \
if ((v = mv_err_cost(&mv, &ref_mv, mvjcost, mvcost, error_per_bit) + \
thismse) < besterr) { \
besterr = v; \
br = r; \
bc = c; \
*distortion = thismse; \
*sse1 = sse; \
} \
} else { \
v = INT_MAX; \
}
#define CHECK_BETTER1(v, r, c) \
do { \
if (c >= minc && c <= maxc && r >= minr && r <= maxr) { \
const MV mv = { r, c }; \
const MV ref_mv = { rr, rc }; \
thismse = accurate_sub_pel_search(xd, &mv, x->me_sf, kernel, vfp, z, \
src_stride, y, y_stride, second_pred, \
w, h, &sse); \
if ((v = mv_err_cost(&mv, &ref_mv, mvjcost, mvcost, error_per_bit) + \
thismse) < besterr) { \
besterr = v; \
br = r; \
bc = c; \
*distortion = thismse; \
*sse1 = sse; \
} \
} else { \
v = INT_MAX; \
} \
} while (0)
#endif
@@ -1731,196 +1739,102 @@ static int exhaustive_mesh_search(const MACROBLOCK *x, MV *ref_mv, MV *best_mv,
#define MAX_RANGE 256
#define MIN_INTERVAL 1
#if CONFIG_NON_GREEDY_MV
#define LOG2_TABLE_SIZE 1024
static const int log2_table[LOG2_TABLE_SIZE] = {
0, // This is a dummy value
0, 1048576, 1661954, 2097152, 2434718, 2710530, 2943725,
3145728, 3323907, 3483294, 3627477, 3759106, 3880192, 3992301,
4096672, 4194304, 4286015, 4372483, 4454275, 4531870, 4605679,
4676053, 4743299, 4807682, 4869436, 4928768, 4985861, 5040877,
5093962, 5145248, 5194851, 5242880, 5289431, 5334591, 5378443,
5421059, 5462508, 5502851, 5542146, 5580446, 5617800, 5654255,
5689851, 5724629, 5758625, 5791875, 5824409, 5856258, 5887450,
5918012, 5947969, 5977344, 6006160, 6034437, 6062195, 6089453,
6116228, 6142538, 6168398, 6193824, 6218829, 6243427, 6267632,
6291456, 6314910, 6338007, 6360756, 6383167, 6405252, 6427019,
6448477, 6469635, 6490501, 6511084, 6531390, 6551427, 6571202,
6590722, 6609993, 6629022, 6647815, 6666376, 6684713, 6702831,
6720734, 6738427, 6755916, 6773205, 6790299, 6807201, 6823917,
6840451, 6856805, 6872985, 6888993, 6904834, 6920510, 6936026,
6951384, 6966588, 6981641, 6996545, 7011304, 7025920, 7040397,
7054736, 7068940, 7083013, 7096956, 7110771, 7124461, 7138029,
7151476, 7164804, 7178017, 7191114, 7204100, 7216974, 7229740,
7242400, 7254954, 7267405, 7279754, 7292003, 7304154, 7316208,
7328167, 7340032, 7351805, 7363486, 7375079, 7386583, 7398000,
7409332, 7420579, 7431743, 7442826, 7453828, 7464751, 7475595,
7486362, 7497053, 7507669, 7518211, 7528680, 7539077, 7549404,
7559660, 7569847, 7579966, 7590017, 7600003, 7609923, 7619778,
7629569, 7639298, 7648964, 7658569, 7668114, 7677598, 7687023,
7696391, 7705700, 7714952, 7724149, 7733289, 7742375, 7751407,
7760385, 7769310, 7778182, 7787003, 7795773, 7804492, 7813161,
7821781, 7830352, 7838875, 7847350, 7855777, 7864158, 7872493,
7880782, 7889027, 7897226, 7905381, 7913492, 7921561, 7929586,
7937569, 7945510, 7953410, 7961268, 7969086, 7976864, 7984602,
7992301, 7999960, 8007581, 8015164, 8022709, 8030217, 8037687,
8045121, 8052519, 8059880, 8067206, 8074496, 8081752, 8088973,
8096159, 8103312, 8110431, 8117516, 8124569, 8131589, 8138576,
8145532, 8152455, 8159347, 8166208, 8173037, 8179836, 8186605,
8193343, 8200052, 8206731, 8213380, 8220001, 8226593, 8233156,
8239690, 8246197, 8252676, 8259127, 8265550, 8271947, 8278316,
8284659, 8290976, 8297266, 8303530, 8309768, 8315981, 8322168,
8328330, 8334467, 8340579, 8346667, 8352730, 8358769, 8364784,
8370775, 8376743, 8382687, 8388608, 8394506, 8400381, 8406233,
8412062, 8417870, 8423655, 8429418, 8435159, 8440878, 8446576,
8452252, 8457908, 8463542, 8469155, 8474748, 8480319, 8485871,
8491402, 8496913, 8502404, 8507875, 8513327, 8518759, 8524171,
8529564, 8534938, 8540293, 8545629, 8550947, 8556245, 8561525,
8566787, 8572031, 8577256, 8582464, 8587653, 8592825, 8597980,
8603116, 8608236, 8613338, 8618423, 8623491, 8628542, 8633576,
8638593, 8643594, 8648579, 8653547, 8658499, 8663434, 8668354,
8673258, 8678145, 8683017, 8687874, 8692715, 8697540, 8702350,
8707145, 8711925, 8716690, 8721439, 8726174, 8730894, 8735599,
8740290, 8744967, 8749628, 8754276, 8758909, 8763528, 8768134,
8772725, 8777302, 8781865, 8786415, 8790951, 8795474, 8799983,
8804478, 8808961, 8813430, 8817886, 8822328, 8826758, 8831175,
8835579, 8839970, 8844349, 8848715, 8853068, 8857409, 8861737,
8866053, 8870357, 8874649, 8878928, 8883195, 8887451, 8891694,
8895926, 8900145, 8904353, 8908550, 8912734, 8916908, 8921069,
8925220, 8929358, 8933486, 8937603, 8941708, 8945802, 8949885,
8953957, 8958018, 8962068, 8966108, 8970137, 8974155, 8978162,
8982159, 8986145, 8990121, 8994086, 8998041, 9001986, 9005920,
9009844, 9013758, 9017662, 9021556, 9025440, 9029314, 9033178,
9037032, 9040877, 9044711, 9048536, 9052352, 9056157, 9059953,
9063740, 9067517, 9071285, 9075044, 9078793, 9082533, 9086263,
9089985, 9093697, 9097400, 9101095, 9104780, 9108456, 9112123,
9115782, 9119431, 9123072, 9126704, 9130328, 9133943, 9137549,
9141146, 9144735, 9148316, 9151888, 9155452, 9159007, 9162554,
9166092, 9169623, 9173145, 9176659, 9180165, 9183663, 9187152,
9190634, 9194108, 9197573, 9201031, 9204481, 9207923, 9211357,
9214784, 9218202, 9221613, 9225017, 9228412, 9231800, 9235181,
9238554, 9241919, 9245277, 9248628, 9251971, 9255307, 9258635,
9261956, 9265270, 9268577, 9271876, 9275169, 9278454, 9281732,
9285002, 9288266, 9291523, 9294773, 9298016, 9301252, 9304481,
9307703, 9310918, 9314126, 9317328, 9320523, 9323711, 9326892,
9330067, 9333235, 9336397, 9339552, 9342700, 9345842, 9348977,
9352106, 9355228, 9358344, 9361454, 9364557, 9367654, 9370744,
9373828, 9376906, 9379978, 9383043, 9386102, 9389155, 9392202,
9395243, 9398278, 9401306, 9404329, 9407345, 9410356, 9413360,
9416359, 9419351, 9422338, 9425319, 9428294, 9431263, 9434226,
9437184, 9440136, 9443082, 9446022, 9448957, 9451886, 9454809,
9457726, 9460638, 9463545, 9466446, 9469341, 9472231, 9475115,
9477994, 9480867, 9483735, 9486597, 9489454, 9492306, 9495152,
9497993, 9500828, 9503659, 9506484, 9509303, 9512118, 9514927,
9517731, 9520530, 9523324, 9526112, 9528895, 9531674, 9534447,
9537215, 9539978, 9542736, 9545489, 9548237, 9550980, 9553718,
9556451, 9559179, 9561903, 9564621, 9567335, 9570043, 9572747,
9575446, 9578140, 9580830, 9583514, 9586194, 9588869, 9591540,
9594205, 9596866, 9599523, 9602174, 9604821, 9607464, 9610101,
9612735, 9615363, 9617987, 9620607, 9623222, 9625832, 9628438,
9631040, 9633637, 9636229, 9638818, 9641401, 9643981, 9646556,
9649126, 9651692, 9654254, 9656812, 9659365, 9661914, 9664459,
9666999, 9669535, 9672067, 9674594, 9677118, 9679637, 9682152,
9684663, 9687169, 9689672, 9692170, 9694665, 9697155, 9699641,
9702123, 9704601, 9707075, 9709545, 9712010, 9714472, 9716930,
9719384, 9721834, 9724279, 9726721, 9729159, 9731593, 9734024,
9736450, 9738872, 9741291, 9743705, 9746116, 9748523, 9750926,
9753326, 9755721, 9758113, 9760501, 9762885, 9765266, 9767642,
9770015, 9772385, 9774750, 9777112, 9779470, 9781825, 9784175,
9786523, 9788866, 9791206, 9793543, 9795875, 9798204, 9800530,
9802852, 9805170, 9807485, 9809797, 9812104, 9814409, 9816710,
9819007, 9821301, 9823591, 9825878, 9828161, 9830441, 9832718,
9834991, 9837261, 9839527, 9841790, 9844050, 9846306, 9848559,
9850808, 9853054, 9855297, 9857537, 9859773, 9862006, 9864235,
9866462, 9868685, 9870904, 9873121, 9875334, 9877544, 9879751,
9881955, 9884155, 9886352, 9888546, 9890737, 9892925, 9895109,
9897291, 9899469, 9901644, 9903816, 9905985, 9908150, 9910313,
9912473, 9914629, 9916783, 9918933, 9921080, 9923225, 9925366,
9927504, 9929639, 9931771, 9933900, 9936027, 9938150, 9940270,
9942387, 9944502, 9946613, 9948721, 9950827, 9952929, 9955029,
9957126, 9959219, 9961310, 9963398, 9965484, 9967566, 9969645,
9971722, 9973796, 9975866, 9977934, 9980000, 9982062, 9984122,
9986179, 9988233, 9990284, 9992332, 9994378, 9996421, 9998461,
10000498, 10002533, 10004565, 10006594, 10008621, 10010644, 10012665,
10014684, 10016700, 10018713, 10020723, 10022731, 10024736, 10026738,
10028738, 10030735, 10032729, 10034721, 10036710, 10038697, 10040681,
10042662, 10044641, 10046617, 10048591, 10050562, 10052530, 10054496,
10056459, 10058420, 10060379, 10062334, 10064287, 10066238, 10068186,
10070132, 10072075, 10074016, 10075954, 10077890, 10079823, 10081754,
10083682, 10085608, 10087532, 10089453, 10091371, 10093287, 10095201,
10097112, 10099021, 10100928, 10102832, 10104733, 10106633, 10108529,
10110424, 10112316, 10114206, 10116093, 10117978, 10119861, 10121742,
10123620, 10125495, 10127369, 10129240, 10131109, 10132975, 10134839,
10136701, 10138561, 10140418, 10142273, 10144126, 10145976, 10147825,
10149671, 10151514, 10153356, 10155195, 10157032, 10158867, 10160699,
10162530, 10164358, 10166184, 10168007, 10169829, 10171648, 10173465,
10175280, 10177093, 10178904, 10180712, 10182519, 10184323, 10186125,
10187925, 10189722, 10191518, 10193311, 10195103, 10196892, 10198679,
10200464, 10202247, 10204028, 10205806, 10207583, 10209357, 10211130,
10212900, 10214668, 10216435, 10218199, 10219961, 10221721, 10223479,
10225235, 10226989, 10228741, 10230491, 10232239, 10233985, 10235728,
10237470, 10239210, 10240948, 10242684, 10244417, 10246149, 10247879,
10249607, 10251333, 10253057, 10254779, 10256499, 10258217, 10259933,
10261647, 10263360, 10265070, 10266778, 10268485, 10270189, 10271892,
10273593, 10275292, 10276988, 10278683, 10280376, 10282068, 10283757,
10285444, 10287130, 10288814, 10290495, 10292175, 10293853, 10295530,
10297204, 10298876, 10300547, 10302216, 10303883, 10305548, 10307211,
10308873, 10310532, 10312190, 10313846, 10315501, 10317153, 10318804,
10320452, 10322099, 10323745, 10325388, 10327030, 10328670, 10330308,
10331944, 10333578, 10335211, 10336842, 10338472, 10340099, 10341725,
10343349, 10344971, 10346592, 10348210, 10349828, 10351443, 10353057,
10354668, 10356279, 10357887, 10359494, 10361099, 10362702, 10364304,
10365904, 10367502, 10369099, 10370694, 10372287, 10373879, 10375468,
10377057, 10378643, 10380228, 10381811, 10383393, 10384973, 10386551,
10388128, 10389703, 10391276, 10392848, 10394418, 10395986, 10397553,
10399118, 10400682, 10402244, 10403804, 10405363, 10406920, 10408476,
10410030, 10411582, 10413133, 10414682, 10416230, 10417776, 10419320,
10420863, 10422404, 10423944, 10425482, 10427019, 10428554, 10430087,
10431619, 10433149, 10434678, 10436206, 10437731, 10439256, 10440778,
10442299, 10443819, 10445337, 10446854, 10448369, 10449882, 10451394,
10452905, 10454414, 10455921, 10457427, 10458932, 10460435, 10461936,
10463436, 10464935, 10466432, 10467927, 10469422, 10470914, 10472405,
10473895, 10475383, 10476870, 10478355, 10479839, 10481322, 10482802,
10484282,
};
#define LOG2_PRECISION 20
static int64_t log2_approximation(int64_t v) {
assert(v > 0);
if (v < LOG2_TABLE_SIZE) {
return log2_table[v];
} else {
// use linear approximation when v >= 2^10
const int slope =
1477; // slope = 1 / (log(2) * 1024) * (1 << LOG2_PRECISION)
assert(LOG2_TABLE_SIZE == 1 << 10);
return slope * (v - LOG2_TABLE_SIZE) + (10 << LOG2_PRECISION);
}
}
int64_t vp9_nb_mvs_inconsistency(const MV *mv, const int_mv *nb_mvs,
int mv_num) {
int i;
int update = 0;
int64_t best_cost = 0;
vpx_clear_system_state();
for (i = 0; i < mv_num; ++i) {
if (nb_mvs[i].as_int != INVALID_MV) {
MV nb_mv = nb_mvs[i].as_mv;
const int64_t row_diff = abs(mv->row - nb_mv.row);
const int64_t col_diff = abs(mv->col - nb_mv.col);
const int64_t cost =
log2_approximation(1 + row_diff * row_diff + col_diff * col_diff);
if (update == 0) {
best_cost = cost;
update = 1;
} else {
best_cost = cost < best_cost ? cost : best_cost;
static int64_t exhaustive_mesh_search_multi_step(
MV *best_mv, const MV *center_mv, int range, int step,
const struct buf_2d *src, const struct buf_2d *pre, int lambda,
const int_mv *nb_full_mvs, int full_mv_num, const MvLimits *mv_limits,
const vp9_variance_fn_ptr_t *fn_ptr) {
int64_t best_sad;
int r, c;
int start_col, end_col, start_row, end_row;
*best_mv = *center_mv;
best_sad =
((int64_t)fn_ptr->sdf(src->buf, src->stride,
get_buf_from_mv(pre, center_mv), pre->stride)
<< LOG2_PRECISION) +
lambda * vp9_nb_mvs_inconsistency(best_mv, nb_full_mvs, full_mv_num);
start_row = VPXMAX(center_mv->row - range, mv_limits->row_min);
start_col = VPXMAX(center_mv->col - range, mv_limits->col_min);
end_row = VPXMIN(center_mv->row + range, mv_limits->row_max);
end_col = VPXMIN(center_mv->col + range, mv_limits->col_max);
for (r = start_row; r <= end_row; r += step) {
for (c = start_col; c <= end_col; c += step) {
const MV mv = { r, c };
int64_t sad = (int64_t)fn_ptr->sdf(src->buf, src->stride,
get_buf_from_mv(pre, &mv), pre->stride)
<< LOG2_PRECISION;
if (sad < best_sad) {
sad += lambda * vp9_nb_mvs_inconsistency(&mv, nb_full_mvs, full_mv_num);
if (sad < best_sad) {
best_sad = sad;
*best_mv = mv;
}
}
}
}
return best_cost;
return best_sad;
}
static int64_t exhaustive_mesh_search_single_step(
MV *best_mv, const MV *center_mv, int range, const struct buf_2d *src,
const struct buf_2d *pre, int lambda, const int_mv *nb_full_mvs,
int full_mv_num, const MvLimits *mv_limits,
const vp9_variance_fn_ptr_t *fn_ptr) {
int64_t best_sad;
int r, c, i;
int start_col, end_col, start_row, end_row;
*best_mv = *center_mv;
best_sad =
((int64_t)fn_ptr->sdf(src->buf, src->stride,
get_buf_from_mv(pre, center_mv), pre->stride)
<< LOG2_PRECISION) +
lambda * vp9_nb_mvs_inconsistency(best_mv, nb_full_mvs, full_mv_num);
start_row = VPXMAX(center_mv->row - range, mv_limits->row_min);
start_col = VPXMAX(center_mv->col - range, mv_limits->col_min);
end_row = VPXMIN(center_mv->row + range, mv_limits->row_max);
end_col = VPXMIN(center_mv->col + range, mv_limits->col_max);
for (r = start_row; r <= end_row; r += 1) {
c = start_col;
while (c + 3 <= end_col) {
unsigned int sads[4];
const uint8_t *addrs[4];
for (i = 0; i < 4; ++i) {
const MV mv = { r, c + i };
addrs[i] = get_buf_from_mv(pre, &mv);
}
fn_ptr->sdx4df(src->buf, src->stride, addrs, pre->stride, sads);
for (i = 0; i < 4; ++i) {
int64_t sad = (int64_t)sads[i] << LOG2_PRECISION;
if (sad < best_sad) {
const MV mv = { r, c + i };
sad +=
lambda * vp9_nb_mvs_inconsistency(&mv, nb_full_mvs, full_mv_num);
if (sad < best_sad) {
best_sad = sad;
*best_mv = mv;
}
}
}
c += 4;
}
while (c <= end_col) {
const MV mv = { r, c };
int64_t sad = (int64_t)fn_ptr->sdf(src->buf, src->stride,
get_buf_from_mv(pre, &mv), pre->stride)
<< LOG2_PRECISION;
if (sad < best_sad) {
sad += lambda * vp9_nb_mvs_inconsistency(&mv, nb_full_mvs, full_mv_num);
if (sad < best_sad) {
best_sad = sad;
*best_mv = mv;
}
}
c += 1;
}
}
return best_sad;
}
static int64_t exhaustive_mesh_search_new(const MACROBLOCK *x, MV *best_mv,
@@ -1930,92 +1844,18 @@ static int64_t exhaustive_mesh_search_new(const MACROBLOCK *x, MV *best_mv,
const int_mv *nb_full_mvs,
int full_mv_num) {
const MACROBLOCKD *const xd = &x->e_mbd;
const struct buf_2d *const what = &x->plane[0].src;
const struct buf_2d *const in_what = &xd->plane[0].pre[0];
MV fcenter_mv = { center_mv->row, center_mv->col };
int64_t best_sad;
int r, c, i;
int start_col, end_col, start_row, end_row;
int col_step = (step > 1) ? step : 4;
const struct buf_2d *src = &x->plane[0].src;
const struct buf_2d *pre = &xd->plane[0].pre[0];
assert(step >= 1);
clamp_mv(&fcenter_mv, x->mv_limits.col_min, x->mv_limits.col_max,
x->mv_limits.row_min, x->mv_limits.row_max);
*best_mv = fcenter_mv;
best_sad =
((int64_t)fn_ptr->sdf(what->buf, what->stride,
get_buf_from_mv(in_what, &fcenter_mv),
in_what->stride)
<< LOG2_PRECISION) +
lambda * vp9_nb_mvs_inconsistency(&fcenter_mv, nb_full_mvs, full_mv_num);
start_row = VPXMAX(-range, x->mv_limits.row_min - fcenter_mv.row);
start_col = VPXMAX(-range, x->mv_limits.col_min - fcenter_mv.col);
end_row = VPXMIN(range, x->mv_limits.row_max - fcenter_mv.row);
end_col = VPXMIN(range, x->mv_limits.col_max - fcenter_mv.col);
for (r = start_row; r <= end_row; r += step) {
for (c = start_col; c <= end_col; c += col_step) {
// Step > 1 means we are not checking every location in this pass.
if (step > 1) {
const MV mv = { fcenter_mv.row + r, fcenter_mv.col + c };
int64_t sad =
(int64_t)fn_ptr->sdf(what->buf, what->stride,
get_buf_from_mv(in_what, &mv), in_what->stride)
<< LOG2_PRECISION;
if (sad < best_sad) {
sad +=
lambda * vp9_nb_mvs_inconsistency(&mv, nb_full_mvs, full_mv_num);
if (sad < best_sad) {
best_sad = sad;
*best_mv = mv;
}
}
} else {
// 4 sads in a single call if we are checking every location
if (c + 3 <= end_col) {
unsigned int sads[4];
const uint8_t *addrs[4];
for (i = 0; i < 4; ++i) {
const MV mv = { fcenter_mv.row + r, fcenter_mv.col + c + i };
addrs[i] = get_buf_from_mv(in_what, &mv);
}
fn_ptr->sdx4df(what->buf, what->stride, addrs, in_what->stride, sads);
for (i = 0; i < 4; ++i) {
int64_t sad = (int64_t)sads[i] << LOG2_PRECISION;
if (sad < best_sad) {
const MV mv = { fcenter_mv.row + r, fcenter_mv.col + c + i };
sad += lambda *
vp9_nb_mvs_inconsistency(&mv, nb_full_mvs, full_mv_num);
if (sad < best_sad) {
best_sad = sad;
*best_mv = mv;
}
}
}
} else {
for (i = 0; i < end_col - c; ++i) {
const MV mv = { fcenter_mv.row + r, fcenter_mv.col + c + i };
int64_t sad = (int64_t)fn_ptr->sdf(what->buf, what->stride,
get_buf_from_mv(in_what, &mv),
in_what->stride)
<< LOG2_PRECISION;
if (sad < best_sad) {
sad += lambda *
vp9_nb_mvs_inconsistency(&mv, nb_full_mvs, full_mv_num);
if (sad < best_sad) {
best_sad = sad;
*best_mv = mv;
}
}
}
}
}
}
assert(is_mv_in(&x->mv_limits, center_mv));
if (step == 1) {
return exhaustive_mesh_search_single_step(
best_mv, center_mv, range, src, pre, lambda, nb_full_mvs, full_mv_num,
&x->mv_limits, fn_ptr);
}
return best_sad;
return exhaustive_mesh_search_multi_step(best_mv, center_mv, range, step, src,
pre, lambda, nb_full_mvs,
full_mv_num, &x->mv_limits, fn_ptr);
}
static int64_t full_pixel_exhaustive_new(const VP9_COMP *cpi, MACROBLOCK *x,
@@ -2031,7 +1871,6 @@ static int64_t full_pixel_exhaustive_new(const VP9_COMP *cpi, MACROBLOCK *x,
int interval = sf->mesh_patterns[0].interval;
int range = sf->mesh_patterns[0].range;
int baseline_interval_divisor;
const MV dummy_mv = { 0, 0 };
// Trap illegal values for interval and range for this function.
if ((range < MIN_RANGE) || (range > MAX_RANGE) || (interval < MIN_INTERVAL) ||
@@ -2067,19 +1906,18 @@ static int64_t full_pixel_exhaustive_new(const VP9_COMP *cpi, MACROBLOCK *x,
}
}
bestsme = vp9_get_mvpred_var(x, &temp_mv, &dummy_mv, fn_ptr, 0);
*dst_mv = temp_mv;
return bestsme;
}
static double diamond_search_sad_new(const MACROBLOCK *x,
const search_site_config *cfg,
const MV *init_full_mv, MV *best_full_mv,
int search_param, int lambda, int *num00,
const vp9_variance_fn_ptr_t *fn_ptr,
const int_mv *nb_full_mvs,
int full_mv_num) {
static int64_t diamond_search_sad_new(const MACROBLOCK *x,
const search_site_config *cfg,
const MV *init_full_mv, MV *best_full_mv,
int search_param, int lambda, int *num00,
const vp9_variance_fn_ptr_t *fn_ptr,
const int_mv *nb_full_mvs,
int full_mv_num) {
int i, j, step;
const MACROBLOCKD *const xd = &x->e_mbd;
@@ -2089,7 +1927,7 @@ static double diamond_search_sad_new(const MACROBLOCK *x,
const int in_what_stride = xd->plane[0].pre[0].stride;
const uint8_t *best_address;
double bestsad;
int64_t bestsad;
int best_site = -1;
int last_site = -1;
@@ -2116,11 +1954,11 @@ static double diamond_search_sad_new(const MACROBLOCK *x,
// Check the starting position
{
const double mv_dist =
fn_ptr->sdf(what, what_stride, in_what, in_what_stride);
const double mv_cost =
vp9_nb_mvs_inconsistency(best_full_mv, nb_full_mvs, full_mv_num) /
(double)(1 << LOG2_PRECISION);
const int64_t mv_dist =
(int64_t)fn_ptr->sdf(what, what_stride, in_what, in_what_stride)
<< LOG2_PRECISION;
const int64_t mv_cost =
vp9_nb_mvs_inconsistency(best_full_mv, nb_full_mvs, full_mv_num);
bestsad = mv_dist + lambda * mv_cost;
}
@@ -2151,14 +1989,13 @@ static double diamond_search_sad_new(const MACROBLOCK *x,
sad_array);
for (t = 0; t < 4; t++, i++) {
if (sad_array[t] < bestsad) {
const int64_t mv_dist = (int64_t)sad_array[t] << LOG2_PRECISION;
if (mv_dist < bestsad) {
const MV this_mv = { best_full_mv->row + ss_mv[i].row,
best_full_mv->col + ss_mv[i].col };
const double mv_dist = sad_array[t];
const double mv_cost =
vp9_nb_mvs_inconsistency(&this_mv, nb_full_mvs, full_mv_num) /
(double)(1 << LOG2_PRECISION);
double thissad = mv_dist + lambda * mv_cost;
const int64_t mv_cost =
vp9_nb_mvs_inconsistency(&this_mv, nb_full_mvs, full_mv_num);
const int64_t thissad = mv_dist + lambda * mv_cost;
if (thissad < bestsad) {
bestsad = thissad;
best_site = i;
@@ -2174,13 +2011,14 @@ static double diamond_search_sad_new(const MACROBLOCK *x,
if (is_mv_in(&x->mv_limits, &this_mv)) {
const uint8_t *const check_here = ss_os[i] + best_address;
const double mv_dist =
fn_ptr->sdf(what, what_stride, check_here, in_what_stride);
const int64_t mv_dist =
(int64_t)fn_ptr->sdf(what, what_stride, check_here,
in_what_stride)
<< LOG2_PRECISION;
if (mv_dist < bestsad) {
const double mv_cost =
vp9_nb_mvs_inconsistency(&this_mv, nb_full_mvs, full_mv_num) /
(double)(1 << LOG2_PRECISION);
double thissad = mv_dist + lambda * mv_cost;
const int64_t mv_cost =
vp9_nb_mvs_inconsistency(&this_mv, nb_full_mvs, full_mv_num);
const int64_t thissad = mv_dist + lambda * mv_cost;
if (thissad < bestsad) {
bestsad = thissad;
best_site = i;
@@ -2202,32 +2040,30 @@ static double diamond_search_sad_new(const MACROBLOCK *x,
return bestsad;
}
void vp9_prepare_nb_full_mvs(const TplDepFrame *tpl_frame, int mi_row,
int mi_col, int rf_idx, BLOCK_SIZE bsize,
int_mv *nb_full_mvs) {
const int mi_width = num_8x8_blocks_wide_lookup[bsize];
const int mi_height = num_8x8_blocks_high_lookup[bsize];
int vp9_prepare_nb_full_mvs(const MotionField *motion_field, int mi_row,
int mi_col, int_mv *nb_full_mvs) {
const int mi_width = num_8x8_blocks_wide_lookup[motion_field->bsize];
const int mi_height = num_8x8_blocks_high_lookup[motion_field->bsize];
const int dirs[NB_MVS_NUM][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
int nb_full_mv_num = 0;
int i;
assert(mi_row % mi_height == 0);
assert(mi_col % mi_width == 0);
for (i = 0; i < NB_MVS_NUM; ++i) {
int r = dirs[i][0] * mi_height;
int c = dirs[i][1] * mi_width;
if (mi_row + r >= 0 && mi_row + r < tpl_frame->mi_rows && mi_col + c >= 0 &&
mi_col + c < tpl_frame->mi_cols) {
const TplDepStats *tpl_ptr =
&tpl_frame
->tpl_stats_ptr[(mi_row + r) * tpl_frame->stride + mi_col + c];
int_mv *mv =
get_pyramid_mv(tpl_frame, rf_idx, bsize, mi_row + r, mi_col + c);
if (tpl_ptr->ready[rf_idx]) {
nb_full_mvs[i].as_mv = get_full_mv(&mv->as_mv);
} else {
nb_full_mvs[i].as_int = INVALID_MV;
int r = dirs[i][0];
int c = dirs[i][1];
int brow = mi_row / mi_height + r;
int bcol = mi_col / mi_width + c;
if (brow >= 0 && brow < motion_field->block_rows && bcol >= 0 &&
bcol < motion_field->block_cols) {
if (vp9_motion_field_is_mv_set(motion_field, brow, bcol)) {
int_mv mv = vp9_motion_field_get_mv(motion_field, brow, bcol);
nb_full_mvs[nb_full_mv_num].as_mv = get_full_mv(&mv.as_mv);
++nb_full_mv_num;
}
} else {
nb_full_mvs[i].as_int = INVALID_MV;
}
}
return nb_full_mv_num;
}
#endif // CONFIG_NON_GREEDY_MV
@@ -2585,26 +2421,32 @@ unsigned int vp9_int_pro_motion_estimation(const VP9_COMP *cpi, MACROBLOCK *x,
return best_sad;
}
static int get_exhaustive_threshold(int exhaustive_searches_thresh,
BLOCK_SIZE bsize) {
return exhaustive_searches_thresh >>
(8 - (b_width_log2_lookup[bsize] + b_height_log2_lookup[bsize]));
}
#if CONFIG_NON_GREEDY_MV
// Runs sequence of diamond searches in smaller steps for RD.
/* do_refine: If last step (1-away) of n-step search doesn't pick the center
point as the best match, we will do a final 1-away diamond
refining search */
double vp9_full_pixel_diamond_new(const VP9_COMP *cpi, MACROBLOCK *x,
MV *mvp_full, int step_param, int lambda,
int do_refine,
const vp9_variance_fn_ptr_t *fn_ptr,
const int_mv *nb_full_mvs, int full_mv_num,
MV *best_mv) {
int vp9_full_pixel_diamond_new(const VP9_COMP *cpi, MACROBLOCK *x,
BLOCK_SIZE bsize, MV *mvp_full, int step_param,
int lambda, int do_refine,
const int_mv *nb_full_mvs, int full_mv_num,
MV *best_mv) {
const vp9_variance_fn_ptr_t *fn_ptr = &cpi->fn_ptr[bsize];
const SPEED_FEATURES *const sf = &cpi->sf;
int n, num00 = 0;
double thissme;
double bestsme;
int thissme;
int bestsme;
const int further_steps = MAX_MVSEARCH_STEPS - 1 - step_param;
const MV center_mv = { 0, 0 };
vpx_clear_system_state();
bestsme =
diamond_search_sad_new(x, &cpi->ss_cfg, mvp_full, best_mv, step_param,
lambda, &n, fn_ptr, nb_full_mvs, full_mv_num);
diamond_search_sad_new(x, &cpi->ss_cfg, mvp_full, best_mv, step_param, lambda,
&n, fn_ptr, nb_full_mvs, full_mv_num);
bestsme = vp9_get_mvpred_var(x, best_mv, &center_mv, fn_ptr, 0);
@@ -2618,9 +2460,9 @@ double vp9_full_pixel_diamond_new(const VP9_COMP *cpi, MACROBLOCK *x,
num00--;
} else {
MV temp_mv;
thissme = diamond_search_sad_new(x, &cpi->ss_cfg, mvp_full, &temp_mv,
step_param + n, lambda, &num00, fn_ptr,
nb_full_mvs, full_mv_num);
diamond_search_sad_new(x, &cpi->ss_cfg, mvp_full, &temp_mv,
step_param + n, lambda, &num00, fn_ptr,
nb_full_mvs, full_mv_num);
thissme = vp9_get_mvpred_var(x, &temp_mv, &center_mv, fn_ptr, 0);
// check to see if refining search is needed.
if (num00 > further_steps - n) do_refine = 0;
@@ -2636,8 +2478,8 @@ double vp9_full_pixel_diamond_new(const VP9_COMP *cpi, MACROBLOCK *x,
if (do_refine) {
const int search_range = 8;
MV temp_mv = *best_mv;
thissme = vp9_refining_search_sad_new(x, &temp_mv, lambda, search_range,
fn_ptr, nb_full_mvs, full_mv_num);
vp9_refining_search_sad_new(x, &temp_mv, lambda, search_range, fn_ptr,
nb_full_mvs, full_mv_num);
thissme = vp9_get_mvpred_var(x, &temp_mv, &center_mv, fn_ptr, 0);
if (thissme < bestsme) {
bestsme = thissme;
@@ -2645,8 +2487,16 @@ double vp9_full_pixel_diamond_new(const VP9_COMP *cpi, MACROBLOCK *x,
}
}
bestsme = (double)full_pixel_exhaustive_new(cpi, x, best_mv, fn_ptr, best_mv,
lambda, nb_full_mvs, full_mv_num);
if (sf->exhaustive_searches_thresh < INT_MAX &&
!cpi->rc.is_src_frame_alt_ref) {
const int64_t exhaustive_thr =
get_exhaustive_threshold(sf->exhaustive_searches_thresh, bsize);
if (bestsme > exhaustive_thr) {
full_pixel_exhaustive_new(cpi, x, best_mv, fn_ptr, best_mv, lambda,
nb_full_mvs, full_mv_num);
bestsme = vp9_get_mvpred_var(x, best_mv, &center_mv, fn_ptr, 0);
}
}
return bestsme;
}
#endif // CONFIG_NON_GREEDY_MV
@@ -2774,24 +2624,25 @@ static int full_pixel_exhaustive(const VP9_COMP *const cpi,
}
#if CONFIG_NON_GREEDY_MV
double vp9_refining_search_sad_new(const MACROBLOCK *x, MV *best_full_mv,
int lambda, int search_range,
const vp9_variance_fn_ptr_t *fn_ptr,
const int_mv *nb_full_mvs, int full_mv_num) {
int64_t vp9_refining_search_sad_new(const MACROBLOCK *x, MV *best_full_mv,
int lambda, int search_range,
const vp9_variance_fn_ptr_t *fn_ptr,
const int_mv *nb_full_mvs,
int full_mv_num) {
const MACROBLOCKD *const xd = &x->e_mbd;
const MV neighbors[4] = { { -1, 0 }, { 0, -1 }, { 0, 1 }, { 1, 0 } };
const struct buf_2d *const what = &x->plane[0].src;
const struct buf_2d *const in_what = &xd->plane[0].pre[0];
const uint8_t *best_address = get_buf_from_mv(in_what, best_full_mv);
double best_sad;
int64_t best_sad;
int i, j;
vpx_clear_system_state();
{
const double mv_dist =
fn_ptr->sdf(what->buf, what->stride, best_address, in_what->stride);
const double mv_cost =
vp9_nb_mvs_inconsistency(best_full_mv, nb_full_mvs, full_mv_num) /
(double)(1 << LOG2_PRECISION);
const int64_t mv_dist = (int64_t)fn_ptr->sdf(what->buf, what->stride,
best_address, in_what->stride)
<< LOG2_PRECISION;
const int64_t mv_cost =
vp9_nb_mvs_inconsistency(best_full_mv, nb_full_mvs, full_mv_num);
best_sad = mv_dist + lambda * mv_cost;
}
@@ -2813,11 +2664,10 @@ double vp9_refining_search_sad_new(const MACROBLOCK *x, MV *best_full_mv,
for (j = 0; j < 4; ++j) {
const MV mv = { best_full_mv->row + neighbors[j].row,
best_full_mv->col + neighbors[j].col };
const double mv_dist = sads[j];
const double mv_cost =
vp9_nb_mvs_inconsistency(&mv, nb_full_mvs, full_mv_num) /
(double)(1 << LOG2_PRECISION);
const double thissad = mv_dist + lambda * mv_cost;
const int64_t mv_dist = (int64_t)sads[j] << LOG2_PRECISION;
const int64_t mv_cost =
vp9_nb_mvs_inconsistency(&mv, nb_full_mvs, full_mv_num);
const int64_t thissad = mv_dist + lambda * mv_cost;
if (thissad < best_sad) {
best_sad = thissad;
best_site = j;
@@ -2829,13 +2679,14 @@ double vp9_refining_search_sad_new(const MACROBLOCK *x, MV *best_full_mv,
best_full_mv->col + neighbors[j].col };
if (is_mv_in(&x->mv_limits, &mv)) {
const double mv_dist =
fn_ptr->sdf(what->buf, what->stride,
get_buf_from_mv(in_what, &mv), in_what->stride);
const double mv_cost =
vp9_nb_mvs_inconsistency(&mv, nb_full_mvs, full_mv_num) /
(double)(1 << LOG2_PRECISION);
const double thissad = mv_dist + lambda * mv_cost;
const int64_t mv_dist =
(int64_t)fn_ptr->sdf(what->buf, what->stride,
get_buf_from_mv(in_what, &mv),
in_what->stride)
<< LOG2_PRECISION;
const int64_t mv_cost =
vp9_nb_mvs_inconsistency(&mv, nb_full_mvs, full_mv_num);
const int64_t thissad = mv_dist + lambda * mv_cost;
if (thissad < best_sad) {
best_sad = thissad;
best_site = j;
@@ -3034,9 +2885,10 @@ int vp9_full_pixel_search(const VP9_COMP *const cpi, const MACROBLOCK *const x,
if (sf->exhaustive_searches_thresh < INT_MAX &&
!cpi->rc.is_src_frame_alt_ref) {
const int64_t exhaustive_thr =
sf->exhaustive_searches_thresh >>
(8 - (b_width_log2_lookup[bsize] + b_height_log2_lookup[bsize]));
if (var > exhaustive_thr) run_exhaustive_search = 1;
get_exhaustive_threshold(sf->exhaustive_searches_thresh, bsize);
if (var > exhaustive_thr) {
run_exhaustive_search = 1;
}
}
} else if (method == MESH) {
run_exhaustive_search = 1;
@@ -3095,7 +2947,7 @@ int vp9_full_pixel_search(const VP9_COMP *const cpi, const MACROBLOCK *const x,
(void)sse; \
(void)thismse; \
(void)cost_list; \
(void)use_accurate_subpel_search;
(void)use_accurate_subpel_search
// Return the maximum MV.
uint32_t vp9_return_max_sub_pixel_mv(
+14 -26
View File
@@ -12,6 +12,9 @@
#define VPX_VP9_ENCODER_VP9_MCOMP_H_
#include "vp9/encoder/vp9_block.h"
#if CONFIG_NON_GREEDY_MV
#include "vp9/encoder/vp9_non_greedy_mv.h"
#endif // CONFIG_NON_GREEDY_MV
#include "vpx_dsp/variance.h"
#ifdef __cplusplus
@@ -90,16 +93,6 @@ extern fractional_mv_step_fp vp9_skip_sub_pixel_tree;
extern fractional_mv_step_fp vp9_return_max_sub_pixel_mv;
extern fractional_mv_step_fp vp9_return_min_sub_pixel_mv;
typedef int (*vp9_full_search_fn_t)(const MACROBLOCK *x, const MV *ref_mv,
int sad_per_bit, int distance,
const vp9_variance_fn_ptr_t *fn_ptr,
const MV *center_mv, MV *best_mv);
typedef int (*vp9_refining_search_fn_t)(const MACROBLOCK *x, MV *ref_mv,
int sad_per_bit, int distance,
const vp9_variance_fn_ptr_t *fn_ptr,
const MV *center_mv);
typedef int (*vp9_diamond_search_fn_t)(
const MACROBLOCK *x, const search_site_config *cfg, MV *ref_mv, MV *best_mv,
int search_param, int sad_per_bit, int *num00,
@@ -126,22 +119,18 @@ void vp9_set_subpel_mv_search_range(MvLimits *subpel_mv_limits,
const MV *ref_mv);
#if CONFIG_NON_GREEDY_MV
#define NB_MVS_NUM 4
struct TplDepStats;
double vp9_refining_search_sad_new(const MACROBLOCK *x, MV *best_full_mv,
int lambda, int search_range,
const vp9_variance_fn_ptr_t *fn_ptr,
const int_mv *nb_full_mvs, int full_mv_num);
int64_t vp9_refining_search_sad_new(const MACROBLOCK *x, MV *best_full_mv,
int lambda, int search_range,
const vp9_variance_fn_ptr_t *fn_ptr,
const int_mv *nb_full_mvs, int full_mv_num);
double vp9_full_pixel_diamond_new(const struct VP9_COMP *cpi, MACROBLOCK *x,
MV *mvp_full, int step_param, int lambda,
int do_refine,
const vp9_variance_fn_ptr_t *fn_ptr,
const int_mv *nb_full_mvs, int full_mv_num,
MV *best_mv);
int vp9_full_pixel_diamond_new(const struct VP9_COMP *cpi, MACROBLOCK *x,
BLOCK_SIZE bsize, MV *mvp_full, int step_param,
int lambda, int do_refine,
const int_mv *nb_full_mvs, int full_mv_num,
MV *best_mv);
int64_t vp9_nb_mvs_inconsistency(const MV *mv, const int_mv *nb_mvs,
int mv_num);
static INLINE MV get_full_mv(const MV *mv) {
MV out_mv;
out_mv.row = mv->row >> 3;
@@ -149,9 +138,8 @@ static INLINE MV get_full_mv(const MV *mv) {
return out_mv;
}
struct TplDepFrame;
void vp9_prepare_nb_full_mvs(const struct TplDepFrame *tpl_frame, int mi_row,
int mi_col, int rf_idx, BLOCK_SIZE bsize,
int_mv *nb_full_mvs);
int vp9_prepare_nb_full_mvs(const struct MotionField *motion_field, int mi_row,
int mi_col, int_mv *nb_full_mvs);
static INLINE BLOCK_SIZE get_square_block_size(BLOCK_SIZE bsize) {
BLOCK_SIZE square_bsize;
+6 -5
View File
@@ -36,7 +36,7 @@ void *vp9_enc_grp_get_next_job(MultiThreadHandle *multi_thread_ctxt,
pthread_mutex_lock(mutex_handle);
#endif
next = job_queue_hdl->next;
if (NULL != next) {
if (next != NULL) {
JobQueue *job_queue = (JobQueue *)next;
job_info = &job_queue->job_info;
// Update the next job in the queue
@@ -58,9 +58,10 @@ void vp9_row_mt_alloc_rd_thresh(VP9_COMP *const cpi,
(mi_cols_aligned_to_sb(cm->mi_rows) >> MI_BLOCK_SIZE_LOG2) + 1;
int i;
this_tile->row_base_thresh_freq_fact =
CHECK_MEM_ERROR(
cm, this_tile->row_base_thresh_freq_fact,
(int *)vpx_calloc(sb_rows * BLOCK_SIZES * MAX_MODES,
sizeof(*(this_tile->row_base_thresh_freq_fact)));
sizeof(*(this_tile->row_base_thresh_freq_fact))));
for (i = 0; i < sb_rows * BLOCK_SIZES * MAX_MODES; i++)
this_tile->row_base_thresh_freq_fact[i] = RD_THRESH_INIT_FACT;
}
@@ -84,8 +85,8 @@ void vp9_row_mt_mem_alloc(VP9_COMP *cpi) {
multi_thread_ctxt->allocated_tile_rows = tile_rows;
multi_thread_ctxt->allocated_vert_unit_rows = jobs_per_tile_col;
multi_thread_ctxt->job_queue =
(JobQueue *)vpx_memalign(32, total_jobs * sizeof(JobQueue));
CHECK_MEM_ERROR(cm, multi_thread_ctxt->job_queue,
(JobQueue *)vpx_memalign(32, total_jobs * sizeof(JobQueue)));
#if CONFIG_MULTITHREAD
// Create mutex for each tile
+536
View File
@@ -0,0 +1,536 @@
/*
* Copyright (c) 2019 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vp9/common/vp9_mv.h"
#include "vp9/encoder/vp9_non_greedy_mv.h"
// TODO(angiebird): move non_greedy_mv related functions to this file
#define LOG2_TABLE_SIZE 1024
static const int log2_table[LOG2_TABLE_SIZE] = {
0, // This is a dummy value
0, 1048576, 1661954, 2097152, 2434718, 2710530, 2943725,
3145728, 3323907, 3483294, 3627477, 3759106, 3880192, 3992301,
4096672, 4194304, 4286015, 4372483, 4454275, 4531870, 4605679,
4676053, 4743299, 4807682, 4869436, 4928768, 4985861, 5040877,
5093962, 5145248, 5194851, 5242880, 5289431, 5334591, 5378443,
5421059, 5462508, 5502851, 5542146, 5580446, 5617800, 5654255,
5689851, 5724629, 5758625, 5791875, 5824409, 5856258, 5887450,
5918012, 5947969, 5977344, 6006160, 6034437, 6062195, 6089453,
6116228, 6142538, 6168398, 6193824, 6218829, 6243427, 6267632,
6291456, 6314910, 6338007, 6360756, 6383167, 6405252, 6427019,
6448477, 6469635, 6490501, 6511084, 6531390, 6551427, 6571202,
6590722, 6609993, 6629022, 6647815, 6666376, 6684713, 6702831,
6720734, 6738427, 6755916, 6773205, 6790299, 6807201, 6823917,
6840451, 6856805, 6872985, 6888993, 6904834, 6920510, 6936026,
6951384, 6966588, 6981641, 6996545, 7011304, 7025920, 7040397,
7054736, 7068940, 7083013, 7096956, 7110771, 7124461, 7138029,
7151476, 7164804, 7178017, 7191114, 7204100, 7216974, 7229740,
7242400, 7254954, 7267405, 7279754, 7292003, 7304154, 7316208,
7328167, 7340032, 7351805, 7363486, 7375079, 7386583, 7398000,
7409332, 7420579, 7431743, 7442826, 7453828, 7464751, 7475595,
7486362, 7497053, 7507669, 7518211, 7528680, 7539077, 7549404,
7559660, 7569847, 7579966, 7590017, 7600003, 7609923, 7619778,
7629569, 7639298, 7648964, 7658569, 7668114, 7677598, 7687023,
7696391, 7705700, 7714952, 7724149, 7733289, 7742375, 7751407,
7760385, 7769310, 7778182, 7787003, 7795773, 7804492, 7813161,
7821781, 7830352, 7838875, 7847350, 7855777, 7864158, 7872493,
7880782, 7889027, 7897226, 7905381, 7913492, 7921561, 7929586,
7937569, 7945510, 7953410, 7961268, 7969086, 7976864, 7984602,
7992301, 7999960, 8007581, 8015164, 8022709, 8030217, 8037687,
8045121, 8052519, 8059880, 8067206, 8074496, 8081752, 8088973,
8096159, 8103312, 8110431, 8117516, 8124569, 8131589, 8138576,
8145532, 8152455, 8159347, 8166208, 8173037, 8179836, 8186605,
8193343, 8200052, 8206731, 8213380, 8220001, 8226593, 8233156,
8239690, 8246197, 8252676, 8259127, 8265550, 8271947, 8278316,
8284659, 8290976, 8297266, 8303530, 8309768, 8315981, 8322168,
8328330, 8334467, 8340579, 8346667, 8352730, 8358769, 8364784,
8370775, 8376743, 8382687, 8388608, 8394506, 8400381, 8406233,
8412062, 8417870, 8423655, 8429418, 8435159, 8440878, 8446576,
8452252, 8457908, 8463542, 8469155, 8474748, 8480319, 8485871,
8491402, 8496913, 8502404, 8507875, 8513327, 8518759, 8524171,
8529564, 8534938, 8540293, 8545629, 8550947, 8556245, 8561525,
8566787, 8572031, 8577256, 8582464, 8587653, 8592825, 8597980,
8603116, 8608236, 8613338, 8618423, 8623491, 8628542, 8633576,
8638593, 8643594, 8648579, 8653547, 8658499, 8663434, 8668354,
8673258, 8678145, 8683017, 8687874, 8692715, 8697540, 8702350,
8707145, 8711925, 8716690, 8721439, 8726174, 8730894, 8735599,
8740290, 8744967, 8749628, 8754276, 8758909, 8763528, 8768134,
8772725, 8777302, 8781865, 8786415, 8790951, 8795474, 8799983,
8804478, 8808961, 8813430, 8817886, 8822328, 8826758, 8831175,
8835579, 8839970, 8844349, 8848715, 8853068, 8857409, 8861737,
8866053, 8870357, 8874649, 8878928, 8883195, 8887451, 8891694,
8895926, 8900145, 8904353, 8908550, 8912734, 8916908, 8921069,
8925220, 8929358, 8933486, 8937603, 8941708, 8945802, 8949885,
8953957, 8958018, 8962068, 8966108, 8970137, 8974155, 8978162,
8982159, 8986145, 8990121, 8994086, 8998041, 9001986, 9005920,
9009844, 9013758, 9017662, 9021556, 9025440, 9029314, 9033178,
9037032, 9040877, 9044711, 9048536, 9052352, 9056157, 9059953,
9063740, 9067517, 9071285, 9075044, 9078793, 9082533, 9086263,
9089985, 9093697, 9097400, 9101095, 9104780, 9108456, 9112123,
9115782, 9119431, 9123072, 9126704, 9130328, 9133943, 9137549,
9141146, 9144735, 9148316, 9151888, 9155452, 9159007, 9162554,
9166092, 9169623, 9173145, 9176659, 9180165, 9183663, 9187152,
9190634, 9194108, 9197573, 9201031, 9204481, 9207923, 9211357,
9214784, 9218202, 9221613, 9225017, 9228412, 9231800, 9235181,
9238554, 9241919, 9245277, 9248628, 9251971, 9255307, 9258635,
9261956, 9265270, 9268577, 9271876, 9275169, 9278454, 9281732,
9285002, 9288266, 9291523, 9294773, 9298016, 9301252, 9304481,
9307703, 9310918, 9314126, 9317328, 9320523, 9323711, 9326892,
9330067, 9333235, 9336397, 9339552, 9342700, 9345842, 9348977,
9352106, 9355228, 9358344, 9361454, 9364557, 9367654, 9370744,
9373828, 9376906, 9379978, 9383043, 9386102, 9389155, 9392202,
9395243, 9398278, 9401306, 9404329, 9407345, 9410356, 9413360,
9416359, 9419351, 9422338, 9425319, 9428294, 9431263, 9434226,
9437184, 9440136, 9443082, 9446022, 9448957, 9451886, 9454809,
9457726, 9460638, 9463545, 9466446, 9469341, 9472231, 9475115,
9477994, 9480867, 9483735, 9486597, 9489454, 9492306, 9495152,
9497993, 9500828, 9503659, 9506484, 9509303, 9512118, 9514927,
9517731, 9520530, 9523324, 9526112, 9528895, 9531674, 9534447,
9537215, 9539978, 9542736, 9545489, 9548237, 9550980, 9553718,
9556451, 9559179, 9561903, 9564621, 9567335, 9570043, 9572747,
9575446, 9578140, 9580830, 9583514, 9586194, 9588869, 9591540,
9594205, 9596866, 9599523, 9602174, 9604821, 9607464, 9610101,
9612735, 9615363, 9617987, 9620607, 9623222, 9625832, 9628438,
9631040, 9633637, 9636229, 9638818, 9641401, 9643981, 9646556,
9649126, 9651692, 9654254, 9656812, 9659365, 9661914, 9664459,
9666999, 9669535, 9672067, 9674594, 9677118, 9679637, 9682152,
9684663, 9687169, 9689672, 9692170, 9694665, 9697155, 9699641,
9702123, 9704601, 9707075, 9709545, 9712010, 9714472, 9716930,
9719384, 9721834, 9724279, 9726721, 9729159, 9731593, 9734024,
9736450, 9738872, 9741291, 9743705, 9746116, 9748523, 9750926,
9753326, 9755721, 9758113, 9760501, 9762885, 9765266, 9767642,
9770015, 9772385, 9774750, 9777112, 9779470, 9781825, 9784175,
9786523, 9788866, 9791206, 9793543, 9795875, 9798204, 9800530,
9802852, 9805170, 9807485, 9809797, 9812104, 9814409, 9816710,
9819007, 9821301, 9823591, 9825878, 9828161, 9830441, 9832718,
9834991, 9837261, 9839527, 9841790, 9844050, 9846306, 9848559,
9850808, 9853054, 9855297, 9857537, 9859773, 9862006, 9864235,
9866462, 9868685, 9870904, 9873121, 9875334, 9877544, 9879751,
9881955, 9884155, 9886352, 9888546, 9890737, 9892925, 9895109,
9897291, 9899469, 9901644, 9903816, 9905985, 9908150, 9910313,
9912473, 9914629, 9916783, 9918933, 9921080, 9923225, 9925366,
9927504, 9929639, 9931771, 9933900, 9936027, 9938150, 9940270,
9942387, 9944502, 9946613, 9948721, 9950827, 9952929, 9955029,
9957126, 9959219, 9961310, 9963398, 9965484, 9967566, 9969645,
9971722, 9973796, 9975866, 9977934, 9980000, 9982062, 9984122,
9986179, 9988233, 9990284, 9992332, 9994378, 9996421, 9998461,
10000498, 10002533, 10004565, 10006594, 10008621, 10010644, 10012665,
10014684, 10016700, 10018713, 10020723, 10022731, 10024736, 10026738,
10028738, 10030735, 10032729, 10034721, 10036710, 10038697, 10040681,
10042662, 10044641, 10046617, 10048591, 10050562, 10052530, 10054496,
10056459, 10058420, 10060379, 10062334, 10064287, 10066238, 10068186,
10070132, 10072075, 10074016, 10075954, 10077890, 10079823, 10081754,
10083682, 10085608, 10087532, 10089453, 10091371, 10093287, 10095201,
10097112, 10099021, 10100928, 10102832, 10104733, 10106633, 10108529,
10110424, 10112316, 10114206, 10116093, 10117978, 10119861, 10121742,
10123620, 10125495, 10127369, 10129240, 10131109, 10132975, 10134839,
10136701, 10138561, 10140418, 10142273, 10144126, 10145976, 10147825,
10149671, 10151514, 10153356, 10155195, 10157032, 10158867, 10160699,
10162530, 10164358, 10166184, 10168007, 10169829, 10171648, 10173465,
10175280, 10177093, 10178904, 10180712, 10182519, 10184323, 10186125,
10187925, 10189722, 10191518, 10193311, 10195103, 10196892, 10198679,
10200464, 10202247, 10204028, 10205806, 10207583, 10209357, 10211130,
10212900, 10214668, 10216435, 10218199, 10219961, 10221721, 10223479,
10225235, 10226989, 10228741, 10230491, 10232239, 10233985, 10235728,
10237470, 10239210, 10240948, 10242684, 10244417, 10246149, 10247879,
10249607, 10251333, 10253057, 10254779, 10256499, 10258217, 10259933,
10261647, 10263360, 10265070, 10266778, 10268485, 10270189, 10271892,
10273593, 10275292, 10276988, 10278683, 10280376, 10282068, 10283757,
10285444, 10287130, 10288814, 10290495, 10292175, 10293853, 10295530,
10297204, 10298876, 10300547, 10302216, 10303883, 10305548, 10307211,
10308873, 10310532, 10312190, 10313846, 10315501, 10317153, 10318804,
10320452, 10322099, 10323745, 10325388, 10327030, 10328670, 10330308,
10331944, 10333578, 10335211, 10336842, 10338472, 10340099, 10341725,
10343349, 10344971, 10346592, 10348210, 10349828, 10351443, 10353057,
10354668, 10356279, 10357887, 10359494, 10361099, 10362702, 10364304,
10365904, 10367502, 10369099, 10370694, 10372287, 10373879, 10375468,
10377057, 10378643, 10380228, 10381811, 10383393, 10384973, 10386551,
10388128, 10389703, 10391276, 10392848, 10394418, 10395986, 10397553,
10399118, 10400682, 10402244, 10403804, 10405363, 10406920, 10408476,
10410030, 10411582, 10413133, 10414682, 10416230, 10417776, 10419320,
10420863, 10422404, 10423944, 10425482, 10427019, 10428554, 10430087,
10431619, 10433149, 10434678, 10436206, 10437731, 10439256, 10440778,
10442299, 10443819, 10445337, 10446854, 10448369, 10449882, 10451394,
10452905, 10454414, 10455921, 10457427, 10458932, 10460435, 10461936,
10463436, 10464935, 10466432, 10467927, 10469422, 10470914, 10472405,
10473895, 10475383, 10476870, 10478355, 10479839, 10481322, 10482802,
10484282,
};
static int mi_size_to_block_size(int mi_bsize, int mi_num) {
return (mi_num % mi_bsize) ? mi_num / mi_bsize + 1 : mi_num / mi_bsize;
}
Status vp9_alloc_motion_field_info(MotionFieldInfo *motion_field_info,
int frame_num, int mi_rows, int mi_cols) {
int frame_idx, rf_idx, square_block_idx;
if (motion_field_info->allocated) {
// TODO(angiebird): Avoid re-allocate buffer if possible
vp9_free_motion_field_info(motion_field_info);
}
motion_field_info->frame_num = frame_num;
motion_field_info->motion_field_array =
vpx_calloc(frame_num, sizeof(*motion_field_info->motion_field_array));
if (!motion_field_info->motion_field_array) return STATUS_FAILED;
for (frame_idx = 0; frame_idx < frame_num; ++frame_idx) {
for (rf_idx = 0; rf_idx < MAX_INTER_REF_FRAMES; ++rf_idx) {
for (square_block_idx = 0; square_block_idx < SQUARE_BLOCK_SIZES;
++square_block_idx) {
BLOCK_SIZE bsize = square_block_idx_to_bsize(square_block_idx);
const int mi_height = num_8x8_blocks_high_lookup[bsize];
const int mi_width = num_8x8_blocks_wide_lookup[bsize];
const int block_rows = mi_size_to_block_size(mi_height, mi_rows);
const int block_cols = mi_size_to_block_size(mi_width, mi_cols);
MotionField *motion_field =
&motion_field_info
->motion_field_array[frame_idx][rf_idx][square_block_idx];
Status status =
vp9_alloc_motion_field(motion_field, bsize, block_rows, block_cols);
if (status == STATUS_FAILED) {
return STATUS_FAILED;
}
}
}
}
motion_field_info->allocated = 1;
return STATUS_OK;
}
Status vp9_alloc_motion_field(MotionField *motion_field, BLOCK_SIZE bsize,
int block_rows, int block_cols) {
Status status = STATUS_OK;
motion_field->ready = 0;
motion_field->bsize = bsize;
motion_field->block_rows = block_rows;
motion_field->block_cols = block_cols;
motion_field->block_num = block_rows * block_cols;
motion_field->mf =
vpx_calloc(motion_field->block_num, sizeof(*motion_field->mf));
if (motion_field->mf == NULL) {
status = STATUS_FAILED;
}
motion_field->set_mv =
vpx_calloc(motion_field->block_num, sizeof(*motion_field->set_mv));
if (motion_field->set_mv == NULL) {
vpx_free(motion_field->mf);
motion_field->mf = NULL;
status = STATUS_FAILED;
}
motion_field->local_structure = vpx_calloc(
motion_field->block_num, sizeof(*motion_field->local_structure));
if (motion_field->local_structure == NULL) {
vpx_free(motion_field->mf);
motion_field->mf = NULL;
vpx_free(motion_field->set_mv);
motion_field->set_mv = NULL;
status = STATUS_FAILED;
}
return status;
}
void vp9_free_motion_field(MotionField *motion_field) {
vpx_free(motion_field->mf);
vpx_free(motion_field->set_mv);
vpx_free(motion_field->local_structure);
vp9_zero(*motion_field);
}
void vp9_free_motion_field_info(MotionFieldInfo *motion_field_info) {
if (motion_field_info->allocated) {
int frame_idx, rf_idx, square_block_idx;
for (frame_idx = 0; frame_idx < motion_field_info->frame_num; ++frame_idx) {
for (rf_idx = 0; rf_idx < MAX_INTER_REF_FRAMES; ++rf_idx) {
for (square_block_idx = 0; square_block_idx < SQUARE_BLOCK_SIZES;
++square_block_idx) {
MotionField *motion_field =
&motion_field_info
->motion_field_array[frame_idx][rf_idx][square_block_idx];
vp9_free_motion_field(motion_field);
}
}
}
vpx_free(motion_field_info->motion_field_array);
motion_field_info->motion_field_array = NULL;
motion_field_info->frame_num = 0;
motion_field_info->allocated = 0;
}
}
MotionField *vp9_motion_field_info_get_motion_field(
MotionFieldInfo *motion_field_info, int frame_idx, int rf_idx,
BLOCK_SIZE bsize) {
int square_block_idx = get_square_block_idx(bsize);
assert(frame_idx < motion_field_info->frame_num);
assert(motion_field_info->allocated == 1);
return &motion_field_info
->motion_field_array[frame_idx][rf_idx][square_block_idx];
}
int vp9_motion_field_is_mv_set(const MotionField *motion_field, int brow,
int bcol) {
assert(brow >= 0 && brow < motion_field->block_rows);
assert(bcol >= 0 && bcol < motion_field->block_cols);
return motion_field->set_mv[brow * motion_field->block_cols + bcol];
}
int_mv vp9_motion_field_get_mv(const MotionField *motion_field, int brow,
int bcol) {
assert(brow >= 0 && brow < motion_field->block_rows);
assert(bcol >= 0 && bcol < motion_field->block_cols);
return motion_field->mf[brow * motion_field->block_cols + bcol];
}
int_mv vp9_motion_field_mi_get_mv(const MotionField *motion_field, int mi_row,
int mi_col) {
const int mi_height = num_8x8_blocks_high_lookup[motion_field->bsize];
const int mi_width = num_8x8_blocks_wide_lookup[motion_field->bsize];
const int brow = mi_row / mi_height;
const int bcol = mi_col / mi_width;
assert(mi_row % mi_height == 0);
assert(mi_col % mi_width == 0);
return vp9_motion_field_get_mv(motion_field, brow, bcol);
}
void vp9_motion_field_mi_set_mv(MotionField *motion_field, int mi_row,
int mi_col, int_mv mv) {
const int mi_height = num_8x8_blocks_high_lookup[motion_field->bsize];
const int mi_width = num_8x8_blocks_wide_lookup[motion_field->bsize];
const int brow = mi_row / mi_height;
const int bcol = mi_col / mi_width;
assert(mi_row % mi_height == 0);
assert(mi_col % mi_width == 0);
assert(brow >= 0 && brow < motion_field->block_rows);
assert(bcol >= 0 && bcol < motion_field->block_cols);
motion_field->mf[brow * motion_field->block_cols + bcol] = mv;
motion_field->set_mv[brow * motion_field->block_cols + bcol] = 1;
}
void vp9_motion_field_reset_mvs(MotionField *motion_field) {
memset(motion_field->set_mv, 0,
motion_field->block_num * sizeof(*motion_field->set_mv));
}
static int64_t log2_approximation(int64_t v) {
assert(v > 0);
if (v < LOG2_TABLE_SIZE) {
return log2_table[v];
} else {
// use linear approximation when v >= 2^10
const int slope =
1477; // slope = 1 / (log(2) * 1024) * (1 << LOG2_PRECISION)
assert(LOG2_TABLE_SIZE == 1 << 10);
return slope * (v - LOG2_TABLE_SIZE) + (10 << LOG2_PRECISION);
}
}
int64_t vp9_nb_mvs_inconsistency(const MV *mv, const int_mv *nb_full_mvs,
int mv_num) {
// The behavior of this function is to compute log2 of mv difference,
// i.e. min log2(1 + row_diff * row_diff + col_diff * col_diff)
// against available neighbor mvs.
// Since the log2 is monotonically increasing, we can compute
// min row_diff * row_diff + col_diff * col_diff first
// then apply log2 in the end.
int i;
int64_t min_abs_diff = INT64_MAX;
int cnt = 0;
assert(mv_num <= NB_MVS_NUM);
for (i = 0; i < mv_num; ++i) {
MV nb_mv = nb_full_mvs[i].as_mv;
const int64_t row_diff = abs(mv->row - nb_mv.row);
const int64_t col_diff = abs(mv->col - nb_mv.col);
const int64_t abs_diff = row_diff * row_diff + col_diff * col_diff;
assert(nb_full_mvs[i].as_int != INVALID_MV);
min_abs_diff = VPXMIN(abs_diff, min_abs_diff);
++cnt;
}
if (cnt) {
return log2_approximation(1 + min_abs_diff);
}
return 0;
}
static FloatMV get_smooth_motion_vector(const FloatMV scaled_search_mv,
const FloatMV *tmp_mf,
const int (*M)[MF_LOCAL_STRUCTURE_SIZE],
int rows, int cols, int row, int col,
float alpha) {
const FloatMV tmp_mv = tmp_mf[row * cols + col];
int idx_row, idx_col;
FloatMV avg_nb_mv = { 0.0f, 0.0f };
FloatMV mv = { 0.0f, 0.0f };
float filter[3][3] = { { 1.0f / 12.0f, 1.0f / 6.0f, 1.0f / 12.0f },
{ 1.0f / 6.0f, 0.0f, 1.0f / 6.0f },
{ 1.0f / 12.0f, 1.0f / 6.0f, 1.0f / 12.0f } };
for (idx_row = 0; idx_row < 3; ++idx_row) {
int nb_row = row + idx_row - 1;
for (idx_col = 0; idx_col < 3; ++idx_col) {
int nb_col = col + idx_col - 1;
if (nb_row < 0 || nb_col < 0 || nb_row >= rows || nb_col >= cols) {
avg_nb_mv.row += (tmp_mv.row) * filter[idx_row][idx_col];
avg_nb_mv.col += (tmp_mv.col) * filter[idx_row][idx_col];
} else {
const FloatMV nb_mv = tmp_mf[nb_row * cols + nb_col];
avg_nb_mv.row += (nb_mv.row) * filter[idx_row][idx_col];
avg_nb_mv.col += (nb_mv.col) * filter[idx_row][idx_col];
}
}
}
{
// M is the local variance of reference frame
float M00 = M[row * cols + col][0];
float M01 = M[row * cols + col][1];
float M10 = M[row * cols + col][2];
float M11 = M[row * cols + col][3];
float det = (M00 + alpha) * (M11 + alpha) - M01 * M10;
float inv_M00 = (M11 + alpha) / det;
float inv_M01 = -M01 / det;
float inv_M10 = -M10 / det;
float inv_M11 = (M00 + alpha) / det;
float inv_MM00 = inv_M00 * M00 + inv_M01 * M10;
float inv_MM01 = inv_M00 * M01 + inv_M01 * M11;
float inv_MM10 = inv_M10 * M00 + inv_M11 * M10;
float inv_MM11 = inv_M10 * M01 + inv_M11 * M11;
mv.row = inv_M00 * avg_nb_mv.row * alpha + inv_M01 * avg_nb_mv.col * alpha +
inv_MM00 * scaled_search_mv.row + inv_MM01 * scaled_search_mv.col;
mv.col = inv_M10 * avg_nb_mv.row * alpha + inv_M11 * avg_nb_mv.col * alpha +
inv_MM10 * scaled_search_mv.row + inv_MM11 * scaled_search_mv.col;
}
return mv;
}
void vp9_get_smooth_motion_field(const MV *search_mf,
const int (*M)[MF_LOCAL_STRUCTURE_SIZE],
int rows, int cols, BLOCK_SIZE bsize,
float alpha, int num_iters, MV *smooth_mf) {
// M is the local variation of reference frame
// build two buffers
FloatMV *input = (FloatMV *)malloc(rows * cols * sizeof(FloatMV));
FloatMV *output = (FloatMV *)malloc(rows * cols * sizeof(FloatMV));
int idx;
int row, col;
int bw = 4 << b_width_log2_lookup[bsize];
int bh = 4 << b_height_log2_lookup[bsize];
if (!(input && output)) goto fail;
// copy search results to input buffer
for (idx = 0; idx < rows * cols; ++idx) {
input[idx].row = (float)search_mf[idx].row / bh;
input[idx].col = (float)search_mf[idx].col / bw;
}
for (idx = 0; idx < num_iters; ++idx) {
FloatMV *tmp;
for (row = 0; row < rows; ++row) {
for (col = 0; col < cols; ++col) {
// note: the scaled_search_mf and smooth_mf are all scaled by macroblock
// size
const MV search_mv = search_mf[row * cols + col];
FloatMV scaled_search_mv = { (float)search_mv.row / bh,
(float)search_mv.col / bw };
output[row * cols + col] = get_smooth_motion_vector(
scaled_search_mv, input, M, rows, cols, row, col, alpha);
}
}
// swap buffers
tmp = input;
input = output;
output = tmp;
}
// copy smoothed results to output
for (idx = 0; idx < rows * cols; ++idx) {
smooth_mf[idx].row = (int)(input[idx].row * bh);
smooth_mf[idx].col = (int)(input[idx].col * bw);
}
fail:
free(input);
free(output);
}
void vp9_get_local_structure(const YV12_BUFFER_CONFIG *cur_frame,
const YV12_BUFFER_CONFIG *ref_frame,
const MV *search_mf,
const vp9_variance_fn_ptr_t *fn_ptr, int rows,
int cols, BLOCK_SIZE bsize,
int (*M)[MF_LOCAL_STRUCTURE_SIZE]) {
const int bw = 4 << b_width_log2_lookup[bsize];
const int bh = 4 << b_height_log2_lookup[bsize];
const int cur_stride = cur_frame->y_stride;
const int ref_stride = ref_frame->y_stride;
const int width = ref_frame->y_width;
const int height = ref_frame->y_height;
int row, col;
for (row = 0; row < rows; ++row) {
for (col = 0; col < cols; ++col) {
int cur_offset = row * bh * cur_stride + col * bw;
uint8_t *center = cur_frame->y_buffer + cur_offset;
int ref_h = row * bh + search_mf[row * cols + col].row;
int ref_w = col * bw + search_mf[row * cols + col].col;
int ref_offset;
uint8_t *target;
uint8_t *nb;
int search_dist;
int nb_dist;
int I_row = 0, I_col = 0;
// TODO(Dan): handle the case that when reference frame block beyond the
// boundary
ref_h = ref_h < 0 ? 0 : (ref_h >= height - bh ? height - bh - 1 : ref_h);
ref_w = ref_w < 0 ? 0 : (ref_w >= width - bw ? width - bw - 1 : ref_w);
// compute search results distortion
// TODO(Dan): maybe need to use vp9 function to find the reference block,
// to compare with the results of my python code, I first use my way to
// compute the reference block
ref_offset = ref_h * ref_stride + ref_w;
target = ref_frame->y_buffer + ref_offset;
search_dist = fn_ptr->sdf(center, cur_stride, target, ref_stride);
// compute target's neighbors' distortions
// TODO(Dan): if using padding, the boundary condition may vary
// up
if (ref_h - bh >= 0) {
nb = target - ref_stride * bh;
nb_dist = fn_ptr->sdf(center, cur_stride, nb, ref_stride);
I_row += nb_dist - search_dist;
}
// down
if (ref_h + bh < height - bh) {
nb = target + ref_stride * bh;
nb_dist = fn_ptr->sdf(center, cur_stride, nb, ref_stride);
I_row += nb_dist - search_dist;
}
if (ref_h - bh >= 0 && ref_h + bh < height - bh) {
I_row /= 2;
}
I_row /= (bw * bh);
// left
if (ref_w - bw >= 0) {
nb = target - bw;
nb_dist = fn_ptr->sdf(center, cur_stride, nb, ref_stride);
I_col += nb_dist - search_dist;
}
// down
if (ref_w + bw < width - bw) {
nb = target + bw;
nb_dist = fn_ptr->sdf(center, cur_stride, nb, ref_stride);
I_col += nb_dist - search_dist;
}
if (ref_w - bw >= 0 && ref_w + bw < width - bw) {
I_col /= 2;
}
I_col /= (bw * bh);
M[row * cols + col][0] = I_row * I_row;
M[row * cols + col][1] = I_row * I_col;
M[row * cols + col][2] = I_col * I_row;
M[row * cols + col][3] = I_col * I_col;
}
}
}
+129
View File
@@ -0,0 +1,129 @@
/*
* Copyright (c) 2019 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP9_ENCODER_VP9_NON_GREEDY_MV_H_
#define VPX_VP9_ENCODER_VP9_NON_GREEDY_MV_H_
#include "vp9/common/vp9_enums.h"
#include "vp9/common/vp9_blockd.h"
#include "vpx_scale/yv12config.h"
#include "vpx_dsp/variance.h"
#ifdef __cplusplus
extern "C" {
#endif
#define NB_MVS_NUM 4
#define LOG2_PRECISION 20
#define MF_LOCAL_STRUCTURE_SIZE 4
#define SQUARE_BLOCK_SIZES 4
typedef enum Status { STATUS_OK = 0, STATUS_FAILED = 1 } Status;
typedef struct MotionField {
int ready;
BLOCK_SIZE bsize;
int block_rows;
int block_cols;
int block_num; // block_num == block_rows * block_cols
int (*local_structure)[MF_LOCAL_STRUCTURE_SIZE];
int_mv *mf;
int *set_mv;
int mv_log_scale;
} MotionField;
typedef struct MotionFieldInfo {
int frame_num;
int allocated;
MotionField (*motion_field_array)[MAX_INTER_REF_FRAMES][SQUARE_BLOCK_SIZES];
} MotionFieldInfo;
typedef struct {
float row, col;
} FloatMV;
static INLINE int get_square_block_idx(BLOCK_SIZE bsize) {
if (bsize == BLOCK_4X4) {
return 0;
}
if (bsize == BLOCK_8X8) {
return 1;
}
if (bsize == BLOCK_16X16) {
return 2;
}
if (bsize == BLOCK_32X32) {
return 3;
}
assert(0 && "ERROR: non-square block size");
return -1;
}
static INLINE BLOCK_SIZE square_block_idx_to_bsize(int square_block_idx) {
if (square_block_idx == 0) {
return BLOCK_4X4;
}
if (square_block_idx == 1) {
return BLOCK_8X8;
}
if (square_block_idx == 2) {
return BLOCK_16X16;
}
if (square_block_idx == 3) {
return BLOCK_32X32;
}
assert(0 && "ERROR: invalid square_block_idx");
return BLOCK_INVALID;
}
Status vp9_alloc_motion_field_info(MotionFieldInfo *motion_field_info,
int frame_num, int mi_rows, int mi_cols);
Status vp9_alloc_motion_field(MotionField *motion_field, BLOCK_SIZE bsize,
int block_rows, int block_cols);
void vp9_free_motion_field(MotionField *motion_field);
void vp9_free_motion_field_info(MotionFieldInfo *motion_field_info);
int64_t vp9_nb_mvs_inconsistency(const MV *mv, const int_mv *nb_full_mvs,
int mv_num);
void vp9_get_smooth_motion_field(const MV *search_mf,
const int (*M)[MF_LOCAL_STRUCTURE_SIZE],
int rows, int cols, BLOCK_SIZE bize,
float alpha, int num_iters, MV *smooth_mf);
void vp9_get_local_structure(const YV12_BUFFER_CONFIG *cur_frame,
const YV12_BUFFER_CONFIG *ref_frame,
const MV *search_mf,
const vp9_variance_fn_ptr_t *fn_ptr, int rows,
int cols, BLOCK_SIZE bsize,
int (*M)[MF_LOCAL_STRUCTURE_SIZE]);
MotionField *vp9_motion_field_info_get_motion_field(
MotionFieldInfo *motion_field_info, int frame_idx, int rf_idx,
BLOCK_SIZE bsize);
void vp9_motion_field_mi_set_mv(MotionField *motion_field, int mi_row,
int mi_col, int_mv mv);
void vp9_motion_field_reset_mvs(MotionField *motion_field);
int_mv vp9_motion_field_get_mv(const MotionField *motion_field, int brow,
int bcol);
int_mv vp9_motion_field_mi_get_mv(const MotionField *motion_field, int mi_row,
int mi_col);
int vp9_motion_field_is_mv_set(const MotionField *motion_field, int brow,
int bcol);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP9_ENCODER_VP9_NON_GREEDY_MV_H_
+45 -35
View File
@@ -19,7 +19,7 @@
#include "vpx/vpx_codec.h"
#include "vpx_dsp/vpx_dsp_common.h"
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/mem.h"
#include "vpx_ports/compiler_attributes.h"
#include "vp9/common/vp9_blockd.h"
#include "vp9/common/vp9_common.h"
@@ -771,24 +771,27 @@ static void block_yrd(VP9_COMP *cpi, MACROBLOCK *x, RD_COST *this_rdc,
const int16_t *src_diff;
src_diff = &p->src_diff[(r * diff_stride + c) << 2];
// skip block condition should be handled before this is called.
assert(!x->skip_block);
switch (tx_size) {
case TX_16X16:
vpx_hadamard_16x16(src_diff, diff_stride, coeff);
vp9_quantize_fp(coeff, 256, x->skip_block, p->round_fp, p->quant_fp,
qcoeff, dqcoeff, pd->dequant, eob, scan_order->scan,
vp9_quantize_fp(coeff, 256, p->round_fp, p->quant_fp, qcoeff,
dqcoeff, pd->dequant, eob, scan_order->scan,
scan_order->iscan);
break;
case TX_8X8:
vpx_hadamard_8x8(src_diff, diff_stride, coeff);
vp9_quantize_fp(coeff, 64, x->skip_block, p->round_fp, p->quant_fp,
qcoeff, dqcoeff, pd->dequant, eob, scan_order->scan,
vp9_quantize_fp(coeff, 64, p->round_fp, p->quant_fp, qcoeff,
dqcoeff, pd->dequant, eob, scan_order->scan,
scan_order->iscan);
break;
default:
assert(tx_size == TX_4X4);
x->fwd_txfm4x4(src_diff, coeff, diff_stride);
vp9_quantize_fp(coeff, 16, x->skip_block, p->round_fp, p->quant_fp,
qcoeff, dqcoeff, pd->dequant, eob, scan_order->scan,
vp9_quantize_fp(coeff, 16, p->round_fp, p->quant_fp, qcoeff,
dqcoeff, pd->dequant, eob, scan_order->scan,
scan_order->iscan);
break;
}
@@ -1127,7 +1130,7 @@ static INLINE void update_thresh_freq_fact_row_mt(
}
static INLINE void update_thresh_freq_fact(
VP9_COMP *cpi, TileDataEnc *tile_data, int source_variance,
VP9_COMP *cpi, TileDataEnc *tile_data, unsigned int source_variance,
BLOCK_SIZE bsize, MV_REFERENCE_FRAME ref_frame, THR_MODES best_mode_idx,
PREDICTION_MODE mode) {
THR_MODES thr_mode_idx = mode_idx[ref_frame][mode_offset(mode)];
@@ -1247,7 +1250,7 @@ static INLINE void find_predictors(
VP9_COMP *cpi, MACROBLOCK *x, MV_REFERENCE_FRAME ref_frame,
int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES],
int const_motion[MAX_REF_FRAMES], int *ref_frame_skip_mask,
const int flag_list[4], TileDataEnc *tile_data, int mi_row, int mi_col,
TileDataEnc *tile_data, int mi_row, int mi_col,
struct buf_2d yv12_mb[4][MAX_MB_PLANE], BLOCK_SIZE bsize,
int force_skip_low_temp_var, int comp_pred_allowed) {
VP9_COMMON *const cm = &cpi->common;
@@ -1259,7 +1262,7 @@ static INLINE void find_predictors(
frame_mv[NEWMV][ref_frame].as_int = INVALID_MV;
frame_mv[ZEROMV][ref_frame].as_int = 0;
// this needs various further optimizations. to be continued..
if ((cpi->ref_frame_flags & flag_list[ref_frame]) && (yv12 != NULL)) {
if ((cpi->ref_frame_flags & ref_frame_to_flag(ref_frame)) && (yv12 != NULL)) {
int_mv *const candidates = x->mbmi_ext->ref_mvs[ref_frame];
const struct scale_factors *const sf = &cm->frame_refs[ref_frame - 1].sf;
vp9_setup_pred_block(xd, yv12_mb[ref_frame], yv12, mi_row, mi_col, sf, sf);
@@ -1501,7 +1504,8 @@ static void search_filter_ref(VP9_COMP *cpi, MACROBLOCK *x, RD_COST *this_rdc,
int best_early_term = 0;
int best_flag_preduv_computed[2] = { 0 };
INTERP_FILTER filter_start = force_smooth_filter ? EIGHTTAP_SMOOTH : EIGHTTAP;
for (filter = filter_start; filter <= EIGHTTAP_SMOOTH; ++filter) {
INTERP_FILTER filter_end = EIGHTTAP_SMOOTH;
for (filter = filter_start; filter <= filter_end; ++filter) {
int64_t cost;
mi->interp_filter = filter;
vp9_build_inter_predictors_sby(xd, mi_row, mi_col, bsize);
@@ -1531,9 +1535,11 @@ static void search_filter_ref(VP9_COMP *cpi, MACROBLOCK *x, RD_COST *this_rdc,
free_pred_buffer(*this_mode_pred);
*this_mode_pred = current_pred;
}
current_pred = &tmp[get_pred_buffer(tmp, 3)];
pd->dst.buf = current_pred->data;
pd->dst.stride = bw;
if (filter != filter_end) {
current_pred = &tmp[get_pred_buffer(tmp, 3)];
pd->dst.buf = current_pred->data;
pd->dst.stride = bw;
}
}
}
}
@@ -1554,6 +1560,9 @@ static void search_filter_ref(VP9_COMP *cpi, MACROBLOCK *x, RD_COST *this_rdc,
if (reuse_inter_pred) {
pd->dst.buf = (*this_mode_pred)->data;
pd->dst.stride = (*this_mode_pred)->stride;
} else if (best_filter < filter_end) {
mi->interp_filter = best_filter;
vp9_build_inter_predictors_sby(xd, mi_row, mi_col, bsize);
}
}
@@ -1684,8 +1693,6 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, TileDataEnc *tile_data,
int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES];
uint8_t mode_checked[MB_MODE_COUNT][MAX_REF_FRAMES];
struct buf_2d yv12_mb[4][MAX_MB_PLANE];
static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
VP9_ALT_FLAG };
RD_COST this_rdc, best_rdc;
// var_y and sse_y are saved to be used in skipping checking
unsigned int var_y = UINT_MAX;
@@ -1713,9 +1720,9 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, TileDataEnc *tile_data,
// process.
// tmp[3] points to dst buffer, and the other 3 point to allocated buffers.
PRED_BUFFER tmp[4];
DECLARE_ALIGNED(16, uint8_t, pred_buf[3 * 64 * 64]);
DECLARE_ALIGNED(16, uint8_t, pred_buf[3 * 64 * 64] VPX_UNINITIALIZED);
#if CONFIG_VP9_HIGHBITDEPTH
DECLARE_ALIGNED(16, uint16_t, pred_buf_16[3 * 64 * 64]);
DECLARE_ALIGNED(16, uint16_t, pred_buf_16[3 * 64 * 64] VPX_UNINITIALIZED);
#endif
struct buf_2d orig_dst = pd->dst;
PRED_BUFFER *this_mode_pred = NULL;
@@ -1919,14 +1926,14 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, TileDataEnc *tile_data,
// constrain the inter mode to only test zero motion.
if (cpi->use_svc && svc->force_zero_mode_spatial_ref &&
svc->spatial_layer_id > 0 && !gf_temporal_ref) {
if (cpi->ref_frame_flags & flag_list[LAST_FRAME]) {
if (cpi->ref_frame_flags & VP9_LAST_FLAG) {
struct scale_factors *const sf = &cm->frame_refs[LAST_FRAME - 1].sf;
if (vp9_is_scaled(sf)) {
svc_force_zero_mode[LAST_FRAME - 1] = 1;
inter_layer_ref = LAST_FRAME;
}
}
if (cpi->ref_frame_flags & flag_list[GOLDEN_FRAME]) {
if (cpi->ref_frame_flags & VP9_GOLD_FLAG) {
struct scale_factors *const sf = &cm->frame_refs[GOLDEN_FRAME - 1].sf;
if (vp9_is_scaled(sf)) {
svc_force_zero_mode[GOLDEN_FRAME - 1] = 1;
@@ -1951,7 +1958,7 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, TileDataEnc *tile_data,
cpi->rc.avg_frame_low_motion < 60))
usable_ref_frame = LAST_FRAME;
if (!((cpi->ref_frame_flags & flag_list[GOLDEN_FRAME]) &&
if (!((cpi->ref_frame_flags & VP9_GOLD_FLAG) &&
!svc_force_zero_mode[GOLDEN_FRAME - 1] && !force_skip_low_temp_var))
use_golden_nonzeromv = 0;
@@ -1979,12 +1986,11 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, TileDataEnc *tile_data,
// Skip find_predictor if the reference frame is not in the
// ref_frame_flags (i.e., not used as a reference for this frame).
skip_ref_find_pred[ref_frame] =
!(cpi->ref_frame_flags & flag_list[ref_frame]);
!(cpi->ref_frame_flags & ref_frame_to_flag(ref_frame));
if (!skip_ref_find_pred[ref_frame]) {
find_predictors(cpi, x, ref_frame, frame_mv, const_motion,
&ref_frame_skip_mask, flag_list, tile_data, mi_row,
mi_col, yv12_mb, bsize, force_skip_low_temp_var,
comp_modes > 0);
&ref_frame_skip_mask, tile_data, mi_row, mi_col, yv12_mb,
bsize, force_skip_low_temp_var, comp_modes > 0);
}
}
@@ -2008,7 +2014,7 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, TileDataEnc *tile_data,
// than current layer: force check of GF-ZEROMV before early exit
// due to skip flag.
if (svc->spatial_layer_id > 0 && no_scaling &&
(cpi->ref_frame_flags & flag_list[GOLDEN_FRAME]) &&
(cpi->ref_frame_flags & VP9_GOLD_FLAG) &&
cm->base_qindex > svc->lower_layer_qindex + 10)
force_test_gf_zeromv = 1;
@@ -2088,7 +2094,8 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, TileDataEnc *tile_data,
if (comp_pred) {
if (!cpi->allow_comp_inter_inter) continue;
// Skip compound inter modes if ARF is not available.
if (!(cpi->ref_frame_flags & flag_list[second_ref_frame])) continue;
if (!(cpi->ref_frame_flags & ref_frame_to_flag(second_ref_frame)))
continue;
// Do not allow compound prediction if the segment level reference frame
// feature is in use as in this case there can only be one reference.
if (segfeature_active(seg, mi->segment_id, SEG_LVL_REF_FRAME)) continue;
@@ -2101,7 +2108,7 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, TileDataEnc *tile_data,
(!cpi->use_svc && sse_zeromv_normalized < thresh_skip_golden)))
continue;
if (!(cpi->ref_frame_flags & flag_list[ref_frame])) continue;
if (!(cpi->ref_frame_flags & ref_frame_to_flag(ref_frame))) continue;
// For screen content. If zero_temp_sad source is computed: skip
// non-zero motion check for stationary blocks. If the superblock is
@@ -2184,7 +2191,7 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, TileDataEnc *tile_data,
if (usable_ref_frame < ALTREF_FRAME) {
if (!force_skip_low_temp_var && usable_ref_frame > LAST_FRAME) {
i = (ref_frame == LAST_FRAME) ? GOLDEN_FRAME : LAST_FRAME;
if ((cpi->ref_frame_flags & flag_list[i]))
if ((cpi->ref_frame_flags & ref_frame_to_flag(i)))
if (x->pred_mv_sad[ref_frame] > (x->pred_mv_sad[i] << 1))
ref_frame_skip_mask |= (1 << ref_frame);
}
@@ -2193,9 +2200,9 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, TileDataEnc *tile_data,
ref_frame == ALTREF_FRAME)) {
int ref1 = (ref_frame == GOLDEN_FRAME) ? LAST_FRAME : GOLDEN_FRAME;
int ref2 = (ref_frame == ALTREF_FRAME) ? LAST_FRAME : ALTREF_FRAME;
if (((cpi->ref_frame_flags & flag_list[ref1]) &&
if (((cpi->ref_frame_flags & ref_frame_to_flag(ref1)) &&
(x->pred_mv_sad[ref_frame] > (x->pred_mv_sad[ref1] << 1))) ||
((cpi->ref_frame_flags & flag_list[ref2]) &&
((cpi->ref_frame_flags & ref_frame_to_flag(ref2)) &&
(x->pred_mv_sad[ref_frame] > (x->pred_mv_sad[ref2] << 1))))
ref_frame_skip_mask |= (1 << ref_frame);
}
@@ -2482,7 +2489,7 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, TileDataEnc *tile_data,
perform_intra_pred =
svc->temporal_layer_id == 0 ||
svc->layer_context[svc->temporal_layer_id].is_key_frame ||
!(cpi->ref_frame_flags & flag_list[GOLDEN_FRAME]) ||
!(cpi->ref_frame_flags & VP9_GOLD_FLAG) ||
(!svc->layer_context[svc->temporal_layer_id].is_key_frame &&
svc_force_zero_mode[best_pickmode.best_ref_frame - 1]);
inter_mode_thresh = (inter_mode_thresh << 1) + inter_mode_thresh;
@@ -2554,6 +2561,10 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, TileDataEnc *tile_data,
if (!((1 << this_mode) & cpi->sf.intra_y_mode_bsize_mask[bsize]))
continue;
if (cpi->sf.rt_intra_dc_only_low_content && this_mode != DC_PRED &&
x->content_state_sb != kVeryHighSad)
continue;
if ((cpi->sf.adaptive_rd_thresh_row_mt &&
rd_less_than_thresh_row_mt(best_rdc.rdcost, mode_rd_thresh,
&rd_thresh_freq_fact[mode_index])) ||
@@ -2737,8 +2748,6 @@ void vp9_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x, int mi_row,
MV_REFERENCE_FRAME best_ref_frame = NONE;
unsigned char segment_id = mi->segment_id;
struct buf_2d yv12_mb[4][MAX_MB_PLANE];
static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
VP9_ALT_FLAG };
int64_t best_rd = INT64_MAX;
b_mode_info bsi[MAX_REF_FRAMES][4];
int ref_frame_skip_mask = 0;
@@ -2754,7 +2763,8 @@ void vp9_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x, int mi_row,
int_mv dummy_mv[2];
x->pred_mv_sad[ref_frame] = INT_MAX;
if ((cpi->ref_frame_flags & flag_list[ref_frame]) && (yv12 != NULL)) {
if ((cpi->ref_frame_flags & ref_frame_to_flag(ref_frame)) &&
(yv12 != NULL)) {
int_mv *const candidates = mbmi_ext->ref_mvs[ref_frame];
const struct scale_factors *const sf = &cm->frame_refs[ref_frame - 1].sf;
vp9_setup_pred_block(xd, yv12_mb[ref_frame], yv12, mi_row, mi_col, sf,
+23 -29
View File
@@ -22,15 +22,12 @@
#include "vp9/encoder/vp9_rd.h"
void vp9_quantize_fp_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
int skip_block, const int16_t *round_ptr,
const int16_t *quant_ptr, tran_low_t *qcoeff_ptr,
tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr,
uint16_t *eob_ptr, const int16_t *scan,
const int16_t *iscan) {
const int16_t *round_ptr, const int16_t *quant_ptr,
tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
const int16_t *dequant_ptr, uint16_t *eob_ptr,
const int16_t *scan, const int16_t *iscan) {
int i, eob = -1;
(void)iscan;
(void)skip_block;
assert(!skip_block);
memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
@@ -56,7 +53,7 @@ void vp9_quantize_fp_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
#if CONFIG_VP9_HIGHBITDEPTH
void vp9_highbd_quantize_fp_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
int skip_block, const int16_t *round_ptr,
const int16_t *round_ptr,
const int16_t *quant_ptr, tran_low_t *qcoeff_ptr,
tran_low_t *dqcoeff_ptr,
const int16_t *dequant_ptr, uint16_t *eob_ptr,
@@ -65,8 +62,6 @@ void vp9_highbd_quantize_fp_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
int eob = -1;
(void)iscan;
(void)skip_block;
assert(!skip_block);
memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
@@ -91,15 +86,12 @@ void vp9_highbd_quantize_fp_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
// TODO(jingning) Refactor this file and combine functions with similar
// operations.
void vp9_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
int skip_block, const int16_t *round_ptr,
const int16_t *quant_ptr, tran_low_t *qcoeff_ptr,
tran_low_t *dqcoeff_ptr,
const int16_t *round_ptr, const int16_t *quant_ptr,
tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
const int16_t *dequant_ptr, uint16_t *eob_ptr,
const int16_t *scan, const int16_t *iscan) {
int i, eob = -1;
(void)iscan;
(void)skip_block;
assert(!skip_block);
memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
@@ -126,15 +118,13 @@ void vp9_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
#if CONFIG_VP9_HIGHBITDEPTH
void vp9_highbd_quantize_fp_32x32_c(
const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block,
const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr,
tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr,
const int16_t *scan, const int16_t *iscan) {
const tran_low_t *coeff_ptr, intptr_t n_coeffs, const int16_t *round_ptr,
const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan,
const int16_t *iscan) {
int i, eob = -1;
(void)iscan;
(void)skip_block;
assert(!skip_block);
memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
@@ -176,16 +166,15 @@ void vp9_regular_quantize_b_4x4(MACROBLOCK *x, int plane, int block,
#if CONFIG_VP9_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
vpx_highbd_quantize_b(BLOCK_OFFSET(p->coeff, block), n_coeffs,
x->skip_block, p->zbin, p->round, p->quant,
p->quant_shift, qcoeff, dqcoeff, pd->dequant,
&p->eobs[block], scan, iscan);
vpx_highbd_quantize_b(BLOCK_OFFSET(p->coeff, block), n_coeffs, p->zbin,
p->round, p->quant, p->quant_shift, qcoeff, dqcoeff,
pd->dequant, &p->eobs[block], scan, iscan);
return;
}
#endif
vpx_quantize_b(BLOCK_OFFSET(p->coeff, block), n_coeffs, x->skip_block,
p->zbin, p->round, p->quant, p->quant_shift, qcoeff, dqcoeff,
pd->dequant, &p->eobs[block], scan, iscan);
vpx_quantize_b(BLOCK_OFFSET(p->coeff, block), n_coeffs, p->zbin, p->round,
p->quant, p->quant_shift, qcoeff, dqcoeff, pd->dequant,
&p->eobs[block], scan, iscan);
}
static void invert_quant(int16_t *quant, int16_t *shift, int d) {
@@ -323,13 +312,18 @@ void vp9_frame_init_quantizer(VP9_COMP *cpi) {
vp9_init_plane_quantizers(cpi, &cpi->td.mb);
}
void vp9_set_quantizer(VP9_COMMON *cm, int q) {
void vp9_set_quantizer(VP9_COMP *cpi, int q) {
VP9_COMMON *cm = &cpi->common;
// quantizer has to be reinitialized with vp9_init_quantizer() if any
// delta_q changes.
cm->base_qindex = q;
cm->y_dc_delta_q = 0;
cm->uv_dc_delta_q = 0;
cm->uv_ac_delta_q = 0;
if (cpi->oxcf.delta_q_uv != 0) {
cm->uv_dc_delta_q = cm->uv_ac_delta_q = cpi->oxcf.delta_q_uv;
vp9_init_quantizer(cpi);
}
}
// Table that converts 0-63 Q-range values passed in outside to the Qindex
+1 -1
View File
@@ -49,7 +49,7 @@ void vp9_init_plane_quantizers(struct VP9_COMP *cpi, MACROBLOCK *x);
void vp9_init_quantizer(struct VP9_COMP *cpi);
void vp9_set_quantizer(struct VP9Common *cm, int q);
void vp9_set_quantizer(struct VP9_COMP *cm, int q);
int vp9_quantizer_to_qindex(int quantizer);
+279 -144
View File
@@ -39,9 +39,6 @@
#define MAX_MB_RATE 250
#define MAXRATE_1080P 4000000
#define DEFAULT_KF_BOOST 2000
#define DEFAULT_GF_BOOST 2000
#define LIMIT_QRANGE_FOR_ALTREF_AND_KEY 1
#define MIN_BPB_FACTOR 0.005
@@ -226,9 +223,10 @@ int vp9_rc_clamp_pframe_target_size(const VP9_COMP *const cpi, int target) {
if (target > rc->max_frame_bandwidth) target = rc->max_frame_bandwidth;
if (oxcf->rc_max_inter_bitrate_pct) {
const int max_rate =
rc->avg_frame_bandwidth * oxcf->rc_max_inter_bitrate_pct / 100;
target = VPXMIN(target, max_rate);
const int64_t max_rate =
(int64_t)rc->avg_frame_bandwidth * oxcf->rc_max_inter_bitrate_pct / 100;
// target is of type int and VPXMIN cannot evaluate to larger than target
target = (int)VPXMIN(target, max_rate);
}
return target;
}
@@ -237,19 +235,19 @@ int vp9_rc_clamp_iframe_target_size(const VP9_COMP *const cpi, int target) {
const RATE_CONTROL *rc = &cpi->rc;
const VP9EncoderConfig *oxcf = &cpi->oxcf;
if (oxcf->rc_max_intra_bitrate_pct) {
const int max_rate =
rc->avg_frame_bandwidth * oxcf->rc_max_intra_bitrate_pct / 100;
target = VPXMIN(target, max_rate);
const int64_t max_rate =
(int64_t)rc->avg_frame_bandwidth * oxcf->rc_max_intra_bitrate_pct / 100;
target = (int)VPXMIN(target, max_rate);
}
if (target > rc->max_frame_bandwidth) target = rc->max_frame_bandwidth;
return target;
}
// TODO(marpan/jianj): bits_off_target and buffer_level are used in the saame
// TODO(marpan/jianj): bits_off_target and buffer_level are used in the same
// way for CBR mode, for the buffering updates below. Look into removing one
// of these (i.e., bits_off_target).
// Update the buffer level before encoding with the per-frame-bandwidth,
static void update_buffer_level_preencode(VP9_COMP *cpi) {
void vp9_update_buffer_level_preencode(VP9_COMP *cpi) {
RATE_CONTROL *const rc = &cpi->rc;
rc->bits_off_target += rc->avg_frame_bandwidth;
// Clip the buffer level to the maximum specified buffer size.
@@ -280,9 +278,9 @@ static void update_buffer_level_svc_preencode(VP9_COMP *cpi) {
svc->current_superframe > 0) {
// TODO(marpan): This may need to be modified for temporal layers.
const double framerate_pts = 10000000.0 / ts_delta;
lrc->bits_off_target += (int)(lc->target_bandwidth / framerate_pts);
lrc->bits_off_target += (int)round(lc->target_bandwidth / framerate_pts);
} else {
lrc->bits_off_target += (int)(lc->target_bandwidth / lc->framerate);
lrc->bits_off_target += (int)round(lc->target_bandwidth / lc->framerate);
}
// Clip buffer level to maximum buffer size for the layer.
lrc->bits_off_target =
@@ -402,6 +400,7 @@ void vp9_rc_init(const VP9EncoderConfig *oxcf, int pass, RATE_CONTROL *rc) {
rc->fac_active_worst_gf = 100;
rc->force_qpmin = 0;
for (i = 0; i < MAX_LAG_BUFFERS; ++i) rc->avg_source_sad[i] = 0;
rc->frames_to_key = 0;
rc->frames_since_key = 8; // Sensible default for first frame.
rc->this_key_frame_forced = 0;
rc->next_key_frame_forced = 0;
@@ -409,6 +408,7 @@ void vp9_rc_init(const VP9EncoderConfig *oxcf, int pass, RATE_CONTROL *rc) {
rc->source_alt_ref_active = 0;
rc->frames_till_gf_update_due = 0;
rc->constrain_gf_key_freq_onepass_vbr = 1;
rc->ni_av_qi = oxcf->worst_allowed_q;
rc->ni_tot_qi = 0;
rc->ni_frames = 0;
@@ -430,13 +430,19 @@ void vp9_rc_init(const VP9EncoderConfig *oxcf, int pass, RATE_CONTROL *rc) {
rc->max_gf_interval = vp9_rc_get_default_max_gf_interval(
oxcf->init_framerate, rc->min_gf_interval);
rc->baseline_gf_interval = (rc->min_gf_interval + rc->max_gf_interval) / 2;
if ((oxcf->pass == 0) && (oxcf->rc_mode == VPX_Q)) {
rc->static_scene_max_gf_interval = FIXED_GF_INTERVAL;
} else {
rc->static_scene_max_gf_interval = MAX_STATIC_GF_GROUP_LENGTH;
}
rc->force_max_q = 0;
rc->last_post_encode_dropped_scene_change = 0;
rc->use_post_encode_drop = 0;
rc->ext_use_post_encode_drop = 0;
rc->disable_overshoot_maxq_cbr = 0;
rc->arf_active_best_quality_adjustment_factor = 1.0;
rc->arf_increase_active_best_quality = 0;
rc->preserve_arf_as_gld = 0;
rc->preserve_next_arf_as_gld = 0;
rc->show_arf_as_gld = 0;
@@ -504,7 +510,7 @@ static int check_buffer_below_thresh(VP9_COMP *cpi, int drop_mark) {
}
}
static int drop_frame(VP9_COMP *cpi) {
int vp9_test_drop(VP9_COMP *cpi) {
const VP9EncoderConfig *oxcf = &cpi->oxcf;
RATE_CONTROL *const rc = &cpi->rc;
SVC *svc = &cpi->svc;
@@ -609,13 +615,15 @@ int vp9_rc_drop_frame(VP9_COMP *cpi) {
SVC *svc = &cpi->svc;
int svc_prev_layer_dropped = 0;
// In the constrained or full_superframe framedrop mode for svc
// (framedrop_mode != LAYER_DROP), if the previous spatial layer was
// dropped, drop the current spatial layer.
// (framedrop_mode != (LAYER_DROP && CONSTRAINED_FROM_ABOVE)),
// if the previous spatial layer was dropped, drop the current spatial layer.
if (cpi->use_svc && svc->spatial_layer_id > 0 &&
svc->drop_spatial_layer[svc->spatial_layer_id - 1])
svc_prev_layer_dropped = 1;
if ((svc_prev_layer_dropped && svc->framedrop_mode != LAYER_DROP) ||
drop_frame(cpi)) {
if ((svc_prev_layer_dropped && svc->framedrop_mode != LAYER_DROP &&
svc->framedrop_mode != CONSTRAINED_FROM_ABOVE_DROP) ||
svc->force_drop_constrained_from_above[svc->spatial_layer_id] ||
vp9_test_drop(cpi)) {
vp9_rc_postencode_update_drop_frame(cpi);
cpi->ext_refresh_frame_flags_pending = 0;
cpi->last_frame_dropped = 1;
@@ -625,14 +633,17 @@ int vp9_rc_drop_frame(VP9_COMP *cpi) {
svc->drop_count[svc->spatial_layer_id]++;
svc->skip_enhancement_layer = 1;
if (svc->framedrop_mode == LAYER_DROP ||
(svc->framedrop_mode == CONSTRAINED_FROM_ABOVE_DROP &&
svc->force_drop_constrained_from_above[svc->number_spatial_layers -
1] == 0) ||
svc->drop_spatial_layer[0] == 0) {
// For the case of constrained drop mode where the base is dropped
// (drop_spatial_layer[0] == 1), which means full superframe dropped,
// we don't increment the svc frame counters. In particular temporal
// layer counter (which is incremented in vp9_inc_frame_in_layer())
// won't be incremented, so on a dropped frame we try the same
// temporal_layer_id on next incoming frame. This is to avoid an
// issue with temporal alignement with full superframe dropping.
// For the case of constrained drop mode where full superframe is
// dropped, we don't increment the svc frame counters.
// In particular temporal layer counter (which is incremented in
// vp9_inc_frame_in_layer()) won't be incremented, so on a dropped
// frame we try the same temporal_layer_id on next incoming frame.
// This is to avoid an issue with temporal alignment with full
// superframe dropping.
vp9_inc_frame_in_layer(cpi);
}
if (svc->spatial_layer_id == svc->number_spatial_layers - 1) {
@@ -821,8 +832,7 @@ int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame,
i = active_best_quality;
do {
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && cm->seg.enabled &&
cr->apply_cyclic_refresh &&
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && cr->apply_cyclic_refresh &&
(!cpi->oxcf.gf_cbr_boost_pct || !cpi->refresh_golden_frame)) {
bits_per_mb_at_this_q =
(int)vp9_cyclic_refresh_rc_bits_per_mb(cpi, i, correction_factor);
@@ -1420,8 +1430,8 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi, int *bottom_index,
int active_worst_quality = cpi->twopass.active_worst_quality;
int q;
int *inter_minq;
int arf_active_best_quality_adjustment, arf_active_best_quality_max;
int *arfgf_high_motion_minq;
int arf_active_best_quality_hl;
int *arfgf_high_motion_minq, *arfgf_low_motion_minq;
const int boost_frame =
!rc->is_src_frame_alt_ref &&
(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame);
@@ -1448,14 +1458,20 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi, int *bottom_index,
if (q < cq_level) q = cq_level;
}
active_best_quality = get_gf_active_quality(cpi, q, cm->bit_depth);
arf_active_best_quality_hl = active_best_quality;
ASSIGN_MINQ_TABLE(cm->bit_depth, arfgf_high_motion_minq);
arf_active_best_quality_max = arfgf_high_motion_minq[q];
arf_active_best_quality_adjustment =
arf_active_best_quality_max - active_best_quality;
active_best_quality = arf_active_best_quality_max -
(int)(arf_active_best_quality_adjustment *
rc->arf_active_best_quality_adjustment_factor);
if (rc->arf_increase_active_best_quality == 1) {
ASSIGN_MINQ_TABLE(cm->bit_depth, arfgf_high_motion_minq);
arf_active_best_quality_hl = arfgf_high_motion_minq[q];
} else if (rc->arf_increase_active_best_quality == -1) {
ASSIGN_MINQ_TABLE(cm->bit_depth, arfgf_low_motion_minq);
arf_active_best_quality_hl = arfgf_low_motion_minq[q];
}
active_best_quality =
(int)((double)active_best_quality *
rc->arf_active_best_quality_adjustment_factor +
(double)arf_active_best_quality_hl *
(1.0 - rc->arf_active_best_quality_adjustment_factor));
// Modify best quality for second level arfs. For mode VPX_Q this
// becomes the baseline frame q.
@@ -1480,17 +1496,30 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi, int *bottom_index,
// Extension to max or min Q if undershoot or overshoot is outside
// the permitted range.
if (frame_is_intra_only(cm) || boost_frame) {
const int layer_depth = gf_group->layer_depth[gf_group_index];
active_best_quality -=
(cpi->twopass.extend_minq + cpi->twopass.extend_minq_fast);
active_worst_quality += (cpi->twopass.extend_maxq / 2);
if (gf_group->rf_level[gf_group_index] == GF_ARF_LOW) {
assert(layer_depth > 1);
active_best_quality =
VPXMAX(active_best_quality,
cpi->twopass.last_qindex_of_arf_layer[layer_depth - 1]);
}
} else {
const int max_layer_depth = gf_group->max_layer_depth;
assert(max_layer_depth > 0);
active_best_quality -=
(cpi->twopass.extend_minq + cpi->twopass.extend_minq_fast) / 2;
active_worst_quality += cpi->twopass.extend_maxq;
// For normal frames do not allow an active minq lower than the q used for
// the last boosted frame.
active_best_quality = VPXMAX(active_best_quality, rc->last_boosted_qindex);
active_best_quality =
VPXMAX(active_best_quality,
cpi->twopass.last_qindex_of_arf_layer[max_layer_depth - 1]);
}
#if LIMIT_QRANGE_FOR_ALTREF_AND_KEY
@@ -1666,8 +1695,10 @@ void vp9_rc_compute_frame_size_bounds(const VP9_COMP *cpi, int frame_target,
} else {
// For very small rate targets where the fractional adjustment
// may be tiny make sure there is at least a minimum range.
const int tol_low = (cpi->sf.recode_tolerance_low * frame_target) / 100;
const int tol_high = (cpi->sf.recode_tolerance_high * frame_target) / 100;
const int tol_low =
(int)(((int64_t)cpi->sf.recode_tolerance_low * frame_target) / 100);
const int tol_high =
(int)(((int64_t)cpi->sf.recode_tolerance_high * frame_target) / 100);
*frame_under_shoot_limit = VPXMAX(frame_target - tol_low - 100, 0);
*frame_over_shoot_limit =
VPXMIN(frame_target + tol_high + 100, cpi->rc.max_frame_bandwidth);
@@ -1682,9 +1713,18 @@ void vp9_rc_set_frame_target(VP9_COMP *cpi, int target) {
// Modify frame size target when down-scaling.
if (cpi->oxcf.resize_mode == RESIZE_DYNAMIC &&
rc->frame_size_selector != UNSCALED)
rc->frame_size_selector != UNSCALED) {
rc->this_frame_target = (int)(rc->this_frame_target *
rate_thresh_mult[rc->frame_size_selector]);
}
#if CONFIG_RATE_CTRL
if (cpi->oxcf.use_simple_encode_api) {
if (cpi->encode_command.use_external_target_frame_bits) {
rc->this_frame_target = cpi->encode_command.target_frame_bits;
}
}
#endif // CONFIG_RATE_CTRL
// Target rate per SB64 (including partial SB64s.
rc->sb64_target_rate = (int)(((int64_t)rc->this_frame_target * 64 * 64) /
@@ -1763,8 +1803,9 @@ static void update_altref_usage(VP9_COMP *const cpi) {
}
}
static void compute_frame_low_motion(VP9_COMP *const cpi) {
void vp9_compute_frame_low_motion(VP9_COMP *const cpi) {
VP9_COMMON *const cm = &cpi->common;
SVC *const svc = &cpi->svc;
int mi_row, mi_col;
MODE_INFO **mi = cm->mi_grid_visible;
RATE_CONTROL *const rc = &cpi->rc;
@@ -1781,6 +1822,19 @@ static void compute_frame_low_motion(VP9_COMP *const cpi) {
}
cnt_zeromv = 100 * cnt_zeromv / (rows * cols);
rc->avg_frame_low_motion = (3 * rc->avg_frame_low_motion + cnt_zeromv) >> 2;
// For SVC: set avg_frame_low_motion (only computed on top spatial layer)
// to all lower spatial layers.
if (cpi->use_svc && svc->spatial_layer_id == svc->number_spatial_layers - 1) {
int i;
for (i = 0; i < svc->number_spatial_layers - 1; ++i) {
const int layer = LAYER_IDS_TO_IDX(i, svc->temporal_layer_id,
svc->number_temporal_layers);
LAYER_CONTEXT *const lc = &svc->layer_context[layer];
RATE_CONTROL *const lrc = &lc->rc;
lrc->avg_frame_low_motion = rc->avg_frame_low_motion;
}
}
}
void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
@@ -1789,6 +1843,9 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
RATE_CONTROL *const rc = &cpi->rc;
SVC *const svc = &cpi->svc;
const int qindex = cm->base_qindex;
const GF_GROUP *gf_group = &cpi->twopass.gf_group;
const int gf_group_index = cpi->twopass.gf_group.index;
const int layer_depth = gf_group->layer_depth[gf_group_index];
// Update rate control heuristics
rc->projected_frame_size = (int)(bytes_used << 3);
@@ -1843,6 +1900,15 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
(cpi->refresh_golden_frame && !rc->is_src_frame_alt_ref)))) {
rc->last_boosted_qindex = qindex;
}
if ((qindex < cpi->twopass.last_qindex_of_arf_layer[layer_depth]) ||
(cm->frame_type == KEY_FRAME) ||
(!rc->constrained_gf_group &&
(cpi->refresh_alt_ref_frame ||
(cpi->refresh_golden_frame && !rc->is_src_frame_alt_ref)))) {
cpi->twopass.last_qindex_of_arf_layer[layer_depth] = qindex;
}
if (frame_is_intra_only(cm)) rc->last_kf_qindex = qindex;
update_buffer_level_postencode(cpi, rc->projected_frame_size);
@@ -1850,14 +1916,15 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
// Rolling monitors of whether we are over or underspending used to help
// regulate min and Max Q in two pass.
if (!frame_is_intra_only(cm)) {
rc->rolling_target_bits = ROUND_POWER_OF_TWO(
rc->rolling_target_bits * 3 + rc->this_frame_target, 2);
rc->rolling_actual_bits = ROUND_POWER_OF_TWO(
rc->rolling_actual_bits * 3 + rc->projected_frame_size, 2);
rc->long_rolling_target_bits = ROUND_POWER_OF_TWO(
rc->long_rolling_target_bits * 31 + rc->this_frame_target, 5);
rc->long_rolling_actual_bits = ROUND_POWER_OF_TWO(
rc->long_rolling_actual_bits * 31 + rc->projected_frame_size, 5);
rc->rolling_target_bits = (int)ROUND64_POWER_OF_TWO(
(int64_t)rc->rolling_target_bits * 3 + rc->this_frame_target, 2);
rc->rolling_actual_bits = (int)ROUND64_POWER_OF_TWO(
(int64_t)rc->rolling_actual_bits * 3 + rc->projected_frame_size, 2);
rc->long_rolling_target_bits = (int)ROUND64_POWER_OF_TWO(
(int64_t)rc->long_rolling_target_bits * 31 + rc->this_frame_target, 5);
rc->long_rolling_actual_bits = (int)ROUND64_POWER_OF_TWO(
(int64_t)rc->long_rolling_actual_bits * 31 + rc->projected_frame_size,
5);
}
// Actual bits spent
@@ -1911,29 +1978,11 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
}
if (oxcf->pass == 0) {
if (!frame_is_intra_only(cm) &&
(!cpi->use_svc ||
(cpi->use_svc &&
!svc->layer_context[svc->temporal_layer_id].is_key_frame &&
svc->spatial_layer_id == svc->number_spatial_layers - 1))) {
compute_frame_low_motion(cpi);
if (!frame_is_intra_only(cm))
if (cpi->sf.use_altref_onepass) update_altref_usage(cpi);
}
// For SVC: set avg_frame_low_motion (only computed on top spatial layer)
// to all lower spatial layers.
if (cpi->use_svc &&
svc->spatial_layer_id == svc->number_spatial_layers - 1) {
int i;
for (i = 0; i < svc->number_spatial_layers - 1; ++i) {
const int layer = LAYER_IDS_TO_IDX(i, svc->temporal_layer_id,
svc->number_temporal_layers);
LAYER_CONTEXT *const lc = &svc->layer_context[layer];
RATE_CONTROL *const lrc = &lc->rc;
lrc->avg_frame_low_motion = rc->avg_frame_low_motion;
}
}
cpi->rc.last_frame_is_src_altref = cpi->rc.is_src_frame_alt_ref;
}
if (!frame_is_intra_only(cm)) rc->reset_high_source_sad = 0;
rc->last_avg_frame_bandwidth = rc->avg_frame_bandwidth;
@@ -1948,6 +1997,7 @@ void vp9_rc_postencode_update_drop_frame(VP9_COMP *cpi) {
cpi->rc.rc_2_frame = 0;
cpi->rc.rc_1_frame = 0;
cpi->rc.last_avg_frame_bandwidth = cpi->rc.avg_frame_bandwidth;
cpi->rc.last_q[INTER_FRAME] = cpi->common.base_qindex;
// For SVC on dropped frame when framedrop_mode != LAYER_DROP:
// in this mode the whole superframe may be dropped if only a single layer
// has buffer underflow (below threshold). Since this can then lead to
@@ -1960,20 +2010,22 @@ void vp9_rc_postencode_update_drop_frame(VP9_COMP *cpi) {
}
}
static int calc_pframe_target_size_one_pass_vbr(const VP9_COMP *const cpi) {
int vp9_calc_pframe_target_size_one_pass_vbr(const VP9_COMP *cpi) {
const RATE_CONTROL *const rc = &cpi->rc;
const int af_ratio = rc->af_ratio_onepass_vbr;
int target =
int64_t target =
(!rc->is_src_frame_alt_ref &&
(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame))
? (rc->avg_frame_bandwidth * rc->baseline_gf_interval * af_ratio) /
? ((int64_t)rc->avg_frame_bandwidth * rc->baseline_gf_interval *
af_ratio) /
(rc->baseline_gf_interval + af_ratio - 1)
: (rc->avg_frame_bandwidth * rc->baseline_gf_interval) /
: ((int64_t)rc->avg_frame_bandwidth * rc->baseline_gf_interval) /
(rc->baseline_gf_interval + af_ratio - 1);
return vp9_rc_clamp_pframe_target_size(cpi, target);
if (target > INT_MAX) target = INT_MAX;
return vp9_rc_clamp_pframe_target_size(cpi, (int)target);
}
static int calc_iframe_target_size_one_pass_vbr(const VP9_COMP *const cpi) {
int vp9_calc_iframe_target_size_one_pass_vbr(const VP9_COMP *cpi) {
static const int kf_ratio = 25;
const RATE_CONTROL *rc = &cpi->rc;
const int target = rc->avg_frame_bandwidth * kf_ratio;
@@ -1999,22 +2051,9 @@ static void adjust_gfint_frame_constraint(VP9_COMP *cpi, int frame_constraint) {
}
}
void vp9_rc_get_one_pass_vbr_params(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
void vp9_set_gf_update_one_pass_vbr(VP9_COMP *const cpi) {
RATE_CONTROL *const rc = &cpi->rc;
int target;
if (!cpi->refresh_alt_ref_frame &&
(cm->current_video_frame == 0 || (cpi->frame_flags & FRAMEFLAGS_KEY) ||
rc->frames_to_key == 0)) {
cm->frame_type = KEY_FRAME;
rc->this_key_frame_forced =
cm->current_video_frame != 0 && rc->frames_to_key == 0;
rc->frames_to_key = cpi->oxcf.key_freq;
rc->kf_boost = DEFAULT_KF_BOOST;
rc->source_alt_ref_active = 0;
} else {
cm->frame_type = INTER_FRAME;
}
VP9_COMMON *const cm = &cpi->common;
if (rc->frames_till_gf_update_due == 0) {
double rate_err = 1.0;
rc->gfu_boost = DEFAULT_GF_BOOST;
@@ -2033,18 +2072,23 @@ void vp9_rc_get_one_pass_vbr_params(VP9_COMP *cpi) {
rate_err > 3.5) {
rc->baseline_gf_interval =
VPXMIN(15, (3 * rc->baseline_gf_interval) >> 1);
} else if (rc->avg_frame_low_motion < 20) {
} else if (rc->avg_frame_low_motion > 0 &&
rc->avg_frame_low_motion < 20) {
// Decrease gf interval for high motion case.
rc->baseline_gf_interval = VPXMAX(6, rc->baseline_gf_interval >> 1);
}
// Adjust boost and af_ratio based on avg_frame_low_motion, which varies
// between 0 and 100 (stationary, 100% zero/small motion).
rc->gfu_boost =
VPXMAX(500, DEFAULT_GF_BOOST * (rc->avg_frame_low_motion << 1) /
(rc->avg_frame_low_motion + 100));
// Adjust boost and af_ratio based on avg_frame_low_motion, which
// varies between 0 and 100 (stationary, 100% zero/small motion).
if (rc->avg_frame_low_motion > 0)
rc->gfu_boost =
VPXMAX(500, DEFAULT_GF_BOOST * (rc->avg_frame_low_motion << 1) /
(rc->avg_frame_low_motion + 100));
else if (rc->avg_frame_low_motion == 0 && rate_err > 1.0)
rc->gfu_boost = DEFAULT_GF_BOOST >> 1;
rc->af_ratio_onepass_vbr = VPXMIN(15, VPXMAX(5, 3 * rc->gfu_boost / 400));
}
adjust_gfint_frame_constraint(cpi, rc->frames_to_key);
if (rc->constrain_gf_key_freq_onepass_vbr)
adjust_gfint_frame_constraint(cpi, rc->frames_to_key);
rc->frames_till_gf_update_due = rc->baseline_gf_interval;
cpi->refresh_golden_frame = 1;
rc->source_alt_ref_pending = 0;
@@ -2054,16 +2098,35 @@ void vp9_rc_get_one_pass_vbr_params(VP9_COMP *cpi) {
rc->alt_ref_gf_group = 1;
}
}
}
void vp9_rc_get_one_pass_vbr_params(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
int target;
if (!cpi->refresh_alt_ref_frame &&
(cm->current_video_frame == 0 || (cpi->frame_flags & FRAMEFLAGS_KEY) ||
rc->frames_to_key == 0)) {
cm->frame_type = KEY_FRAME;
rc->this_key_frame_forced =
cm->current_video_frame != 0 && rc->frames_to_key == 0;
rc->frames_to_key = cpi->oxcf.key_freq;
rc->kf_boost = DEFAULT_KF_BOOST;
rc->source_alt_ref_active = 0;
} else {
cm->frame_type = INTER_FRAME;
}
vp9_set_gf_update_one_pass_vbr(cpi);
if (cm->frame_type == KEY_FRAME)
target = calc_iframe_target_size_one_pass_vbr(cpi);
target = vp9_calc_iframe_target_size_one_pass_vbr(cpi);
else
target = calc_pframe_target_size_one_pass_vbr(cpi);
target = vp9_calc_pframe_target_size_one_pass_vbr(cpi);
vp9_rc_set_frame_target(cpi, target);
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && cpi->oxcf.pass == 0)
vp9_cyclic_refresh_update_parameters(cpi);
}
static int calc_pframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
int vp9_calc_pframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
const VP9EncoderConfig *oxcf = &cpi->oxcf;
const RATE_CONTROL *rc = &cpi->rc;
const SVC *const svc = &cpi->svc;
@@ -2112,7 +2175,7 @@ static int calc_pframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
return VPXMAX(min_frame_target, target);
}
static int calc_iframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
int vp9_calc_iframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
const RATE_CONTROL *rc = &cpi->rc;
const VP9EncoderConfig *oxcf = &cpi->oxcf;
const SVC *const svc = &cpi->svc;
@@ -2151,7 +2214,6 @@ static void set_intra_only_frame(VP9_COMP *cpi) {
// only 3 reference buffers can be updated, but for temporal layers > 1
// we generally need to use buffer slots 4 and 5.
if ((cm->current_video_frame == 0 && svc->number_temporal_layers > 1) ||
svc->temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS ||
svc->number_spatial_layers > 3 || svc->number_temporal_layers > 3 ||
svc->number_spatial_layers == 1)
return;
@@ -2172,11 +2234,15 @@ static void set_intra_only_frame(VP9_COMP *cpi) {
cpi->lst_fb_idx = -1;
cpi->gld_fb_idx = -1;
cpi->alt_fb_idx = -1;
svc->update_buffer_slot[0] = 0;
// For intra-only frame we need to refresh all slots that were
// being used for the base layer (fb_idx_base[i] == 1).
// Start with assigning last first, then golden and then alt.
for (i = 0; i < REF_FRAMES; ++i) {
if (svc->fb_idx_base[i] == 1) count++;
if (svc->fb_idx_base[i] == 1) {
svc->update_buffer_slot[0] |= 1 << i;
count++;
}
if (count == 1 && cpi->lst_fb_idx == -1) cpi->lst_fb_idx = i;
if (count == 2 && cpi->gld_fb_idx == -1) cpi->gld_fb_idx = i;
if (count == 3 && cpi->alt_fb_idx == -1) cpi->alt_fb_idx = i;
@@ -2185,6 +2251,12 @@ static void set_intra_only_frame(VP9_COMP *cpi) {
// to the lst_fb_idx.
if (cpi->gld_fb_idx == -1) cpi->gld_fb_idx = cpi->lst_fb_idx;
if (cpi->alt_fb_idx == -1) cpi->alt_fb_idx = cpi->lst_fb_idx;
if (svc->temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
cpi->ext_refresh_last_frame = 0;
cpi->ext_refresh_golden_frame = 0;
cpi->ext_refresh_alt_ref_frame = 0;
cpi->ref_frame_flags = 0;
}
}
}
@@ -2200,7 +2272,7 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) {
// Periodic key frames is based on the super-frame counter
// (svc.current_superframe), also only base spatial layer is key frame.
// Key frame is set for any of the following: very first frame, frame flags
// indicates key, superframe counter hits key frequencey, or (non-intra) sync
// indicates key, superframe counter hits key frequency, or (non-intra) sync
// flag is set for spatial layer 0.
if ((cm->current_video_frame == 0 && !svc->previous_frame_is_intra_only) ||
(cpi->frame_flags & FRAMEFLAGS_KEY) ||
@@ -2218,7 +2290,7 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) {
cpi->ref_frame_flags &= (~VP9_LAST_FLAG & ~VP9_GOLD_FLAG & ~VP9_ALT_FLAG);
// Assumption here is that LAST_FRAME is being updated for a keyframe.
// Thus no change in update flags.
target = calc_iframe_target_size_one_pass_cbr(cpi);
target = vp9_calc_iframe_target_size_one_pass_cbr(cpi);
}
} else {
cm->frame_type = INTER_FRAME;
@@ -2231,7 +2303,7 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) {
(svc->spatial_layer_id == 0 && cm->current_video_frame > 0)
? 0
: svc->layer_context[svc->temporal_layer_id].is_key_frame;
target = calc_pframe_target_size_one_pass_cbr(cpi);
target = vp9_calc_pframe_target_size_one_pass_cbr(cpi);
}
}
@@ -2240,7 +2312,7 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) {
svc->layer_context[layer].is_key_frame == 1) {
cm->frame_type = KEY_FRAME;
cpi->ref_frame_flags &= (~VP9_LAST_FLAG & ~VP9_GOLD_FLAG & ~VP9_ALT_FLAG);
target = calc_iframe_target_size_one_pass_cbr(cpi);
target = vp9_calc_iframe_target_size_one_pass_cbr(cpi);
}
// Set the buffer idx and refresh flags for key frames in simulcast mode.
// Note the buffer slot for long-term reference is set below (line 2255),
@@ -2325,8 +2397,11 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) {
}
if (svc->set_intra_only_frame) {
set_intra_only_frame(cpi);
target = calc_iframe_target_size_one_pass_cbr(cpi);
target = vp9_calc_iframe_target_size_one_pass_cbr(cpi);
}
// Overlay frame predicts from LAST (intra-only)
if (svc->previous_frame_is_intra_only) cpi->ref_frame_flags |= VP9_LAST_FLAG;
// Any update/change of global cyclic refresh parameters (amount/delta-qp)
// should be done here, before the frame qp is selected.
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
@@ -2334,6 +2409,43 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) {
vp9_rc_set_frame_target(cpi, target);
if (cm->show_frame) update_buffer_level_svc_preencode(cpi);
if (cpi->oxcf.resize_mode == RESIZE_DYNAMIC && svc->single_layer_svc == 1 &&
svc->spatial_layer_id == svc->first_spatial_layer_to_encode &&
svc->temporal_layer_id == 0) {
LAYER_CONTEXT *lc = NULL;
cpi->resize_pending = vp9_resize_one_pass_cbr(cpi);
if (cpi->resize_pending) {
int tl, width, height;
// Apply the same scale to all temporal layers.
for (tl = 0; tl < svc->number_temporal_layers; tl++) {
lc = &svc->layer_context[svc->spatial_layer_id *
svc->number_temporal_layers +
tl];
lc->scaling_factor_num_resize =
cpi->resize_scale_num * lc->scaling_factor_num;
lc->scaling_factor_den_resize =
cpi->resize_scale_den * lc->scaling_factor_den;
// Reset rate control for all temporal layers.
lc->rc.buffer_level = lc->rc.optimal_buffer_level;
lc->rc.bits_off_target = lc->rc.optimal_buffer_level;
lc->rc.rate_correction_factors[INTER_FRAME] =
rc->rate_correction_factors[INTER_FRAME];
}
// Set the size for this current temporal layer.
lc = &svc->layer_context[svc->spatial_layer_id *
svc->number_temporal_layers +
svc->temporal_layer_id];
get_layer_resolution(cpi->oxcf.width, cpi->oxcf.height,
lc->scaling_factor_num_resize,
lc->scaling_factor_den_resize, &width, &height);
vp9_set_size_literal(cpi, width, height);
svc->resize_set = 1;
}
} else {
cpi->resize_pending = 0;
svc->resize_set = 0;
}
}
void vp9_rc_get_one_pass_cbr_params(VP9_COMP *cpi) {
@@ -2369,13 +2481,13 @@ void vp9_rc_get_one_pass_cbr_params(VP9_COMP *cpi) {
vp9_cyclic_refresh_update_parameters(cpi);
if (frame_is_intra_only(cm))
target = calc_iframe_target_size_one_pass_cbr(cpi);
target = vp9_calc_iframe_target_size_one_pass_cbr(cpi);
else
target = calc_pframe_target_size_one_pass_cbr(cpi);
target = vp9_calc_pframe_target_size_one_pass_cbr(cpi);
vp9_rc_set_frame_target(cpi, target);
if (cm->show_frame) update_buffer_level_preencode(cpi);
if (cm->show_frame) vp9_update_buffer_level_preencode(cpi);
if (cpi->oxcf.resize_mode == RESIZE_DYNAMIC)
cpi->resize_pending = vp9_resize_one_pass_cbr(cpi);
@@ -2438,15 +2550,25 @@ void vp9_rc_set_gf_interval_range(const VP9_COMP *const cpi,
rc->min_gf_interval = FIXED_GF_INTERVAL;
rc->static_scene_max_gf_interval = FIXED_GF_INTERVAL;
} else {
double framerate = cpi->framerate;
// Set Maximum gf/arf interval
rc->max_gf_interval = oxcf->max_gf_interval;
rc->min_gf_interval = oxcf->min_gf_interval;
if (rc->min_gf_interval == 0)
#if CONFIG_RATE_CTRL
if (oxcf->use_simple_encode_api) {
// In this experiment, we avoid framerate being changed dynamically during
// encoding.
framerate = oxcf->init_framerate;
}
#endif // CONFIG_RATE_CTRL
if (rc->min_gf_interval == 0) {
rc->min_gf_interval = vp9_rc_get_default_min_gf_interval(
oxcf->width, oxcf->height, cpi->framerate);
if (rc->max_gf_interval == 0)
rc->max_gf_interval = vp9_rc_get_default_max_gf_interval(
cpi->framerate, rc->min_gf_interval);
oxcf->width, oxcf->height, framerate);
}
if (rc->max_gf_interval == 0) {
rc->max_gf_interval =
vp9_rc_get_default_max_gf_interval(framerate, rc->min_gf_interval);
}
// Extended max interval for genuinely static scenes like slide shows.
rc->static_scene_max_gf_interval = MAX_STATIC_GF_GROUP_LENGTH;
@@ -2494,7 +2616,7 @@ void vp9_rc_update_framerate(VP9_COMP *cpi) {
// A maximum bitrate for a frame is defined.
// However this limit is extended if a very high rate is given on the command
// line or the the rate cannnot be acheived because of a user specificed max q
// line or the rate can not be achieved because of a user specified max q
// (e.g. when the user specifies lossless encode).
//
// If a level is specified that requires a lower maximum rate then the level
@@ -2578,9 +2700,11 @@ int vp9_resize_one_pass_cbr(VP9_COMP *cpi) {
RESIZE_ACTION resize_action = NO_RESIZE;
int avg_qp_thr1 = 70;
int avg_qp_thr2 = 50;
int min_width = 180;
int min_height = 180;
// Don't allow for resized frame to go below 320x180, resize in steps of 3/4.
int min_width = (320 * 4) / 3;
int min_height = (180 * 4) / 3;
int down_size_on = 1;
int force_downsize_rate = 0;
cpi->resize_scale_num = 1;
cpi->resize_scale_den = 1;
// Don't resize on key frame; reset the counters on key frame.
@@ -2589,20 +2713,9 @@ int vp9_resize_one_pass_cbr(VP9_COMP *cpi) {
cpi->resize_count = 0;
return 0;
}
// Check current frame reslution to avoid generating frames smaller than
// the minimum resolution.
if (ONEHALFONLY_RESIZE) {
if ((cm->width >> 1) < min_width || (cm->height >> 1) < min_height)
down_size_on = 0;
} else {
if (cpi->resize_state == ORIG &&
(cm->width * 3 / 4 < min_width || cm->height * 3 / 4 < min_height))
return 0;
else if (cpi->resize_state == THREE_QUARTER &&
((cpi->oxcf.width >> 1) < min_width ||
(cpi->oxcf.height >> 1) < min_height))
down_size_on = 0;
}
// No resizing down if frame size is below some limit.
if ((cm->width * cm->height) < min_width * min_height) down_size_on = 0;
#if CONFIG_VP9_TEMPORAL_DENOISING
// If denoiser is on, apply a smaller qp threshold.
@@ -2612,11 +2725,32 @@ int vp9_resize_one_pass_cbr(VP9_COMP *cpi) {
}
#endif
// Force downsize based on per-frame-bandwidth, for extreme case,
// for HD input.
if (cpi->resize_state == ORIG && cm->width * cm->height >= 1280 * 720) {
if (rc->avg_frame_bandwidth < 300000 / 30) {
resize_action = DOWN_ONEHALF;
cpi->resize_state = ONE_HALF;
force_downsize_rate = 1;
} else if (rc->avg_frame_bandwidth < 400000 / 30) {
resize_action = ONEHALFONLY_RESIZE ? DOWN_ONEHALF : DOWN_THREEFOUR;
cpi->resize_state = ONEHALFONLY_RESIZE ? ONE_HALF : THREE_QUARTER;
force_downsize_rate = 1;
}
} else if (cpi->resize_state == THREE_QUARTER &&
cm->width * cm->height >= 960 * 540) {
if (rc->avg_frame_bandwidth < 300000 / 30) {
resize_action = DOWN_ONEHALF;
cpi->resize_state = ONE_HALF;
force_downsize_rate = 1;
}
}
// Resize based on average buffer underflow and QP over some window.
// Ignore samples close to key frame, since QP is usually high after key.
if (cpi->rc.frames_since_key > 2 * cpi->framerate) {
const int window = (int)(4 * cpi->framerate);
cpi->resize_avg_qp += cm->base_qindex;
if (!force_downsize_rate && cpi->rc.frames_since_key > cpi->framerate) {
const int window = VPXMIN(30, (int)(2 * cpi->framerate));
cpi->resize_avg_qp += rc->last_q[INTER_FRAME];
if (cpi->rc.buffer_level < (int)(30 * rc->optimal_buffer_level / 100))
++cpi->resize_buffer_underflow;
++cpi->resize_count;
@@ -2628,8 +2762,9 @@ int vp9_resize_one_pass_cbr(VP9_COMP *cpi) {
// Resize back up if average QP is low, and we are currently in a resized
// down state, i.e. 1/2 or 3/4 of original resolution.
// Currently, use a flag to turn 3/4 resizing feature on/off.
if (cpi->resize_buffer_underflow > (cpi->resize_count >> 2)) {
if (cpi->resize_state == THREE_QUARTER && down_size_on) {
if (cpi->resize_buffer_underflow > (cpi->resize_count >> 2) &&
down_size_on) {
if (cpi->resize_state == THREE_QUARTER) {
resize_action = DOWN_ONEHALF;
cpi->resize_state = ONE_HALF;
} else if (cpi->resize_state == ORIG) {
@@ -2676,7 +2811,7 @@ int vp9_resize_one_pass_cbr(VP9_COMP *cpi) {
// Reset buffer level to optimal, update target size.
rc->buffer_level = rc->optimal_buffer_level;
rc->bits_off_target = rc->optimal_buffer_level;
rc->this_frame_target = calc_pframe_target_size_one_pass_cbr(cpi);
rc->this_frame_target = vp9_calc_pframe_target_size_one_pass_cbr(cpi);
// Get the projected qindex, based on the scaled target frame size (scaled
// so target_bits_per_mb in vp9_rc_regulate_q will be correct target).
target_bits_per_frame = (resize_action >= 0)
@@ -2841,7 +2976,7 @@ static void adjust_gf_boost_lag_one_pass_vbr(VP9_COMP *cpi,
}
}
}
target = calc_pframe_target_size_one_pass_vbr(cpi);
target = vp9_calc_pframe_target_size_one_pass_vbr(cpi);
vp9_rc_set_frame_target(cpi, target);
}
rc->prev_avg_source_sad_lag = avg_source_sad_lag;
@@ -2894,7 +3029,7 @@ void vp9_scene_detection_onepass(VP9_COMP *cpi) {
int scene_cut_force_key_frame = 0;
int num_zero_temp_sad = 0;
uint64_t avg_sad_current = 0;
uint32_t min_thresh = 10000;
uint32_t min_thresh = 20000; // ~5 * 64 * 64
float thresh = 8.0f;
uint32_t thresh_key = 140000;
if (cpi->oxcf.speed <= 5) thresh_key = 240000;
@@ -3051,7 +3186,7 @@ void vp9_scene_detection_onepass(VP9_COMP *cpi) {
VPXMIN(20, VPXMAX(10, rc->baseline_gf_interval));
adjust_gfint_frame_constraint(cpi, rc->frames_to_key);
rc->frames_till_gf_update_due = rc->baseline_gf_interval;
target = calc_pframe_target_size_one_pass_vbr(cpi);
target = vp9_calc_pframe_target_size_one_pass_vbr(cpi);
vp9_rc_set_frame_target(cpi, target);
rc->count_last_scene_change = 0;
} else {
@@ -3151,7 +3286,7 @@ int vp9_encodedframe_overshoot(VP9_COMP *cpi, int frame_size, int *q) {
int tl = 0;
int sl = 0;
SVC *svc = &cpi->svc;
for (sl = 0; sl < svc->first_spatial_layer_to_encode; ++sl) {
for (sl = 0; sl < VPXMAX(1, svc->first_spatial_layer_to_encode); ++sl) {
for (tl = 0; tl < svc->number_temporal_layers; ++tl) {
const int layer =
LAYER_IDS_TO_IDX(sl, tl, svc->number_temporal_layers);
+21 -3
View File
@@ -27,6 +27,9 @@ extern "C" {
// Bits Per MB at different Q (Multiplied by 512)
#define BPER_MB_NORMBITS 9
#define DEFAULT_KF_BOOST 2000
#define DEFAULT_GF_BOOST 2000
#define MIN_GF_INTERVAL 4
#define MAX_GF_INTERVAL 16
#define FIXED_GF_INTERVAL 8 // Used in some testing modes only
@@ -83,7 +86,7 @@ static const double rate_thresh_mult[FRAME_SCALE_STEPS] = { 1.0, 2.0 };
static const double rcf_mult[FRAME_SCALE_STEPS] = { 1.0, 2.0 };
typedef struct {
// Rate targetting variables
// Rate targeting variables
int base_frame_target; // A baseline frame target before adjustment
// for previous under or over shoot.
int this_frame_target; // Actual frame target after rc adjustment.
@@ -195,14 +198,19 @@ typedef struct {
int use_post_encode_drop;
// External flag to enable post encode frame dropping, controlled by user.
int ext_use_post_encode_drop;
// Flag to disable CBR feature to increase Q on overshoot detection.
int disable_overshoot_maxq_cbr;
int damped_adjustment[RATE_FACTOR_LEVELS];
double arf_active_best_quality_adjustment_factor;
int arf_active_best_quality_adjustment_window;
int arf_increase_active_best_quality;
int preserve_arf_as_gld;
int preserve_next_arf_as_gld;
int show_arf_as_gld;
// Flag to constrain golden frame interval on key frame frequency for 1 pass
// VBR.
int constrain_gf_key_freq_onepass_vbr;
} RATE_CONTROL;
struct VP9_COMP;
@@ -252,6 +260,12 @@ int vp9_rc_get_default_max_gf_interval(double framerate, int min_gf_interval);
// encode_frame_to_data_rate() function.
void vp9_rc_get_one_pass_vbr_params(struct VP9_COMP *cpi);
void vp9_rc_get_one_pass_cbr_params(struct VP9_COMP *cpi);
int vp9_calc_pframe_target_size_one_pass_cbr(const struct VP9_COMP *cpi);
int vp9_calc_iframe_target_size_one_pass_cbr(const struct VP9_COMP *cpi);
int vp9_calc_pframe_target_size_one_pass_vbr(const struct VP9_COMP *cpi);
int vp9_calc_iframe_target_size_one_pass_vbr(const struct VP9_COMP *cpi);
void vp9_set_gf_update_one_pass_vbr(struct VP9_COMP *const cpi);
void vp9_update_buffer_level_preencode(struct VP9_COMP *cpi);
void vp9_rc_get_svc_params(struct VP9_COMP *cpi);
// Post encode update of the rate control parameters based
@@ -267,6 +281,8 @@ void vp9_rc_update_rate_correction_factors(struct VP9_COMP *cpi);
// Post encode drop for CBR mode.
int post_encode_drop_cbr(struct VP9_COMP *cpi, size_t *size);
int vp9_test_drop(struct VP9_COMP *cpi);
// Decide if we should drop this frame: For 1-pass CBR.
// Changes only the decimation count in the rate control structure
int vp9_rc_drop_frame(struct VP9_COMP *cpi);
@@ -328,6 +344,8 @@ void vp9_configure_buffer_updates(struct VP9_COMP *cpi, int gf_group_index);
void vp9_estimate_qp_gop(struct VP9_COMP *cpi);
void vp9_compute_frame_low_motion(struct VP9_COMP *const cpi);
#ifdef __cplusplus
} // extern "C"
#endif
+60 -20
View File
@@ -197,28 +197,68 @@ static const int rd_boost_factor[16] = { 64, 32, 32, 32, 24, 16, 12, 12,
static const int rd_frame_type_factor[FRAME_UPDATE_TYPES] = { 128, 144, 128,
128, 144, 144 };
int vp9_compute_rd_mult_based_on_qindex(const VP9_COMP *cpi, int qindex) {
// largest dc_quant is 21387, therefore rdmult should always fit in int32_t
const int q = vp9_dc_quant(qindex, 0, cpi->common.bit_depth);
uint32_t rdmult = q * q;
// Configure Vizier RD parameters.
// Later this function will use passed in command line values.
void vp9_init_rd_parameters(VP9_COMP *cpi) {
RD_CONTROL *const rdc = &cpi->rd_ctrl;
if (cpi->common.frame_type != KEY_FRAME) {
if (qindex < 128)
rdmult = rdmult * 4;
else if (qindex < 190)
rdmult = rdmult * 4 + rdmult / 2;
else
rdmult = rdmult * 3;
// When |use_vizier_rc_params| is 1, we expect the rd parameters have been
// initialized by the pass in values.
// Be careful that parameters below are only initialized to 1, if we do not
// pass values to them. It is desired to take care of each parameter when
// using |use_vizier_rc_params|.
if (cpi->twopass.use_vizier_rc_params) return;
// Make sure this function is floating point safe.
vpx_clear_system_state();
rdc->rd_mult_inter_qp_fac = 1.0;
rdc->rd_mult_arf_qp_fac = 1.0;
rdc->rd_mult_key_qp_fac = 1.0;
}
// Returns the default rd multiplier for inter frames for a given qindex.
// The function here is a first pass estimate based on data from
// a previous Vizer run
static double def_inter_rd_multiplier(int qindex) {
return 4.15 + (0.001 * (double)qindex);
}
// Returns the default rd multiplier for ARF/Golden Frames for a given qindex.
// The function here is a first pass estimate based on data from
// a previous Vizer run
static double def_arf_rd_multiplier(int qindex) {
return 4.25 + (0.001 * (double)qindex);
}
// Returns the default rd multiplier for key frames for a given qindex.
// The function here is a first pass estimate based on data from
// a previous Vizer run
static double def_kf_rd_multiplier(int qindex) {
return 4.35 + (0.001 * (double)qindex);
}
int vp9_compute_rd_mult_based_on_qindex(const VP9_COMP *cpi, int qindex) {
const RD_CONTROL *rdc = &cpi->rd_ctrl;
const int q = vp9_dc_quant(qindex, 0, cpi->common.bit_depth);
// largest dc_quant is 21387, therefore rdmult should fit in int32_t
int rdmult = q * q;
// Make sure this function is floating point safe.
vpx_clear_system_state();
if (cpi->common.frame_type == KEY_FRAME) {
double def_rd_q_mult = def_kf_rd_multiplier(qindex);
rdmult = (int)((double)rdmult * def_rd_q_mult * rdc->rd_mult_key_qp_fac);
} else if (!cpi->rc.is_src_frame_alt_ref &&
(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
double def_rd_q_mult = def_arf_rd_multiplier(qindex);
rdmult = (int)((double)rdmult * def_rd_q_mult * rdc->rd_mult_arf_qp_fac);
} else {
if (qindex < 64)
rdmult = rdmult * 4;
else if (qindex <= 128)
rdmult = rdmult * 3 + rdmult / 2;
else if (qindex < 190)
rdmult = rdmult * 4 + rdmult / 2;
else
rdmult = rdmult * 7 + rdmult / 2;
double def_rd_q_mult = def_inter_rd_multiplier(qindex);
rdmult = (int)((double)rdmult * def_rd_q_mult * rdc->rd_mult_inter_qp_fac);
}
#if CONFIG_VP9_HIGHBITDEPTH
switch (cpi->common.bit_depth) {
case VPX_BITS_10: rdmult = ROUND_POWER_OF_TWO(rdmult, 4); break;
@@ -589,7 +629,7 @@ void vp9_mv_pred(VP9_COMP *cpi, MACROBLOCK *x, uint8_t *ref_y_buffer,
x->mbmi_ext->ref_mvs[ref_frame][1].as_int;
// Get the sad for each candidate reference mv.
for (i = 0; i < num_mv_refs && i < MAX_MV_REF_CANDIDATES + 1; ++i) {
for (i = 0; i < num_mv_refs; ++i) {
const MV *this_mv = &pred_mv[i];
int fp_row, fp_col;
if (this_mv->row == INT16_MAX || this_mv->col == INT16_MAX) continue;
+11 -4
View File
@@ -38,8 +38,6 @@ extern "C" {
#define MV_COST_WEIGHT 108
#define MV_COST_WEIGHT_SUB 120
#define INVALID_MV 0x80008000
#define MAX_MODES 30
#define MAX_REFS 6
@@ -103,6 +101,13 @@ typedef enum {
THR_INTRA,
} THR_MODES_SUB8X8;
typedef struct {
// RD multiplier control factors added for Vizier project.
double rd_mult_inter_qp_fac;
double rd_mult_arf_qp_fac;
double rd_mult_key_qp_fac;
} RD_CONTROL;
typedef struct RD_OPT {
// Thresh_mult is used to set a threshold for the rd score. A higher value
// means that we will accept the best mode so far more often. This number
@@ -116,11 +121,11 @@ typedef struct RD_OPT {
int64_t prediction_type_threshes[MAX_REF_FRAMES][REFERENCE_MODES];
int64_t filter_threshes[MAX_REF_FRAMES][SWITCHABLE_FILTER_CONTEXTS];
#if CONFIG_CONSISTENT_RECODE
#if CONFIG_CONSISTENT_RECODE || CONFIG_RATE_CTRL
int64_t prediction_type_threshes_prev[MAX_REF_FRAMES][REFERENCE_MODES];
int64_t filter_threshes_prev[MAX_REF_FRAMES][SWITCHABLE_FILTER_CONTEXTS];
#endif
#endif // CONFIG_CONSISTENT_RECODE || CONFIG_RATE_CTRL
int RDMULT;
int RDDIV;
double r0;
@@ -146,6 +151,8 @@ struct TileDataEnc;
struct VP9_COMP;
struct macroblock;
void vp9_init_rd_parameters(struct VP9_COMP *cpi);
int vp9_compute_rd_mult_based_on_qindex(const struct VP9_COMP *cpi, int qindex);
int vp9_compute_rd_mult(const struct VP9_COMP *cpi, int qindex);
+48 -43
View File
@@ -745,8 +745,8 @@ static void block_rd_txfm(int plane, int block, int blk_row, int blk_col,
MODE_INFO *const mi = xd->mi[0];
int64_t rd1, rd2, rd;
int rate;
int64_t dist;
int64_t sse;
int64_t dist = INT64_MAX;
int64_t sse = INT64_MAX;
const int coeff_ctx =
combine_entropy_contexts(args->t_left[blk_row], args->t_above[blk_col]);
struct buf_2d *recon = args->this_recon;
@@ -799,6 +799,13 @@ static void block_rd_txfm(int plane, int block, int blk_row, int blk_col,
if (max_txsize_lookup[plane_bsize] == tx_size)
skip_txfm_flag = x->skip_txfm[(plane << 2) + (block >> (tx_size << 1))];
// This reduces the risk of bad perceptual quality due to bad prediction.
// We always force the encoder to perform transform and quantization.
if (!args->cpi->sf.allow_skip_txfm_ac_dc &&
skip_txfm_flag == SKIP_TXFM_AC_DC) {
skip_txfm_flag = SKIP_TXFM_NONE;
}
if (skip_txfm_flag == SKIP_TXFM_NONE ||
(recon && skip_txfm_flag == SKIP_TXFM_AC_ONLY)) {
// full forward transform and quantization
@@ -827,17 +834,7 @@ static void block_rd_txfm(int plane, int block, int blk_row, int blk_col,
dist = VPXMAX(0, sse - dc_correct);
}
} else {
// SKIP_TXFM_AC_DC
// skip forward transform. Because this is handled here, the quantization
// does not need to do it.
x->plane[plane].eobs[block] = 0;
sse = x->bsse[(plane << 2) + (block >> (tx_size << 1))] << 4;
dist = sse;
if (recon) {
uint8_t *rec_ptr = &recon->buf[4 * (blk_row * recon->stride + blk_col)];
copy_block_visible(xd, pd, dst, dst_stride, rec_ptr, recon->stride,
blk_row, blk_col, plane_bsize, tx_bsize);
}
assert(0 && "allow_skip_txfm_ac_dc does not allow SKIP_TXFM_AC_DC.");
}
}
@@ -2494,19 +2491,19 @@ static void single_motion_search(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize,
const int ph = num_4x4_blocks_high_lookup[bsize] << 2;
MV pred_mv[3];
int bestsme = INT_MAX;
#if CONFIG_NON_GREEDY_MV
double bestsme;
int_mv nb_full_mvs[NB_MVS_NUM];
const int nb_full_mv_num = NB_MVS_NUM;
int gf_group_idx = cpi->twopass.gf_group.index;
int gf_rf_idx = ref_frame_to_gf_rf_idx(ref);
BLOCK_SIZE square_bsize = get_square_block_size(bsize);
int_mv nb_full_mvs[NB_MVS_NUM] = { 0 };
MotionField *motion_field = vp9_motion_field_info_get_motion_field(
&cpi->motion_field_info, gf_group_idx, gf_rf_idx, square_bsize);
const int nb_full_mv_num =
vp9_prepare_nb_full_mvs(motion_field, mi_row, mi_col, nb_full_mvs);
const int lambda = (pw * ph) / 4;
assert(pw * ph == lambda << 2);
vp9_prepare_nb_full_mvs(&cpi->tpl_stats[gf_group_idx], mi_row, mi_col,
gf_rf_idx, square_bsize, nb_full_mvs);
#else // CONFIG_NON_GREEDY_MV
int bestsme = INT_MAX;
int sadpb = x->sadperbit16;
#endif // CONFIG_NON_GREEDY_MV
@@ -2580,9 +2577,9 @@ static void single_motion_search(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize,
mvp_full.row >>= 3;
#if CONFIG_NON_GREEDY_MV
bestsme = vp9_full_pixel_diamond_new(cpi, x, &mvp_full, step_param, lambda, 1,
&cpi->fn_ptr[bsize], nb_full_mvs,
nb_full_mv_num, &tmp_mv->as_mv);
bestsme = vp9_full_pixel_diamond_new(cpi, x, bsize, &mvp_full, step_param,
lambda, 1, nb_full_mvs, nb_full_mv_num,
&tmp_mv->as_mv);
#else // CONFIG_NON_GREEDY_MV
bestsme = vp9_full_pixel_search(
cpi, x, bsize, &mvp_full, step_param, cpi->sf.mv.search_method, sadpb,
@@ -2592,11 +2589,7 @@ static void single_motion_search(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize,
if (cpi->sf.enhanced_full_pixel_motion_search) {
int i;
for (i = 0; i < 3; ++i) {
#if CONFIG_NON_GREEDY_MV
double this_me;
#else // CONFIG_NON_GREEDY_MV
int this_me;
#endif // CONFIG_NON_GREEDY_MV
MV this_mv;
int diff_row;
int diff_col;
@@ -2622,9 +2615,9 @@ static void single_motion_search(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize,
mvp_full.row >>= 3;
#if CONFIG_NON_GREEDY_MV
this_me = vp9_full_pixel_diamond_new(
cpi, x, &mvp_full, VPXMAX(step_param, MAX_MVSEARCH_STEPS - step),
lambda, 1, &cpi->fn_ptr[bsize], nb_full_mvs, nb_full_mv_num,
&this_mv);
cpi, x, bsize, &mvp_full,
VPXMAX(step_param, MAX_MVSEARCH_STEPS - step), lambda, 1, nb_full_mvs,
nb_full_mv_num, &this_mv);
#else // CONFIG_NON_GREEDY_MV
this_me = vp9_full_pixel_search(
cpi, x, bsize, &mvp_full,
@@ -2678,8 +2671,7 @@ static INLINE void restore_dst_buf(MACROBLOCKD *xd,
// However, once established that vector may be usable through the nearest and
// near mv modes to reduce distortion in subsequent blocks and also improve
// visual quality.
static int discount_newmv_test(const VP9_COMP *cpi, int this_mode,
int_mv this_mv,
static int discount_newmv_test(VP9_COMP *cpi, int this_mode, int_mv this_mv,
int_mv (*mode_mv)[MAX_REF_FRAMES], int ref_frame,
int mi_row, int mi_col, BLOCK_SIZE bsize) {
#if CONFIG_NON_GREEDY_MV
@@ -2689,6 +2681,8 @@ static int discount_newmv_test(const VP9_COMP *cpi, int this_mode,
const int gf_group_idx = cpi->twopass.gf_group.index;
const int gf_rf_idx = ref_frame_to_gf_rf_idx(ref_frame);
const TplDepFrame tpl_frame = cpi->tpl_stats[gf_group_idx];
const MotionField *motion_field = vp9_motion_field_info_get_motion_field(
&cpi->motion_field_info, gf_group_idx, gf_rf_idx, cpi->tpl_bsize);
const int tpl_block_mi_h = num_8x8_blocks_high_lookup[cpi->tpl_bsize];
const int tpl_block_mi_w = num_8x8_blocks_wide_lookup[cpi->tpl_bsize];
const int tpl_mi_row = mi_row - (mi_row % tpl_block_mi_h);
@@ -2697,8 +2691,8 @@ static int discount_newmv_test(const VP9_COMP *cpi, int this_mode,
tpl_frame
.mv_mode_arr[gf_rf_idx][tpl_mi_row * tpl_frame.stride + tpl_mi_col];
if (mv_mode == NEW_MV_MODE) {
int_mv tpl_new_mv = *get_pyramid_mv(&tpl_frame, gf_rf_idx, cpi->tpl_bsize,
tpl_mi_row, tpl_mi_col);
int_mv tpl_new_mv =
vp9_motion_field_mi_get_mv(motion_field, tpl_mi_row, tpl_mi_col);
int row_diff = abs(tpl_new_mv.as_mv.row - this_mv.as_mv.row);
int col_diff = abs(tpl_new_mv.as_mv.col - this_mv.as_mv.col);
if (VPXMAX(row_diff, col_diff) <= 8) {
@@ -3321,8 +3315,6 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, TileDataEnc *tile_data,
int_mv single_newmv[MAX_REF_FRAMES] = { { 0 } };
INTERP_FILTER single_inter_filter[MB_MODE_COUNT][MAX_REF_FRAMES];
int single_skippable[MB_MODE_COUNT][MAX_REF_FRAMES];
static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
VP9_ALT_FLAG };
int64_t best_rd = best_rd_so_far;
int64_t best_pred_diff[REFERENCE_MODES];
int64_t best_pred_rd[REFERENCE_MODES];
@@ -3398,7 +3390,7 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, TileDataEnc *tile_data,
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
x->pred_mv_sad[ref_frame] = INT_MAX;
if ((cpi->ref_frame_flags & flag_list[ref_frame]) &&
if ((cpi->ref_frame_flags & ref_frame_to_flag(ref_frame)) &&
!(is_rect_partition && (ctx->skip_ref_frame_mask & (1 << ref_frame)))) {
assert(get_ref_frame_buffer(cpi, ref_frame) != NULL);
setup_buffer_inter(cpi, x, ref_frame, bsize, mi_row, mi_col,
@@ -3409,7 +3401,7 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, TileDataEnc *tile_data,
}
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
if (!(cpi->ref_frame_flags & flag_list[ref_frame])) {
if (!(cpi->ref_frame_flags & ref_frame_to_flag(ref_frame))) {
// Skip checking missing references in both single and compound reference
// modes. Note that a mode will be skipped if both reference frames
// are masked out.
@@ -3455,7 +3447,7 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, TileDataEnc *tile_data,
if (cpi->rc.is_src_frame_alt_ref) {
if (sf->alt_ref_search_fp) {
mode_skip_mask[ALTREF_FRAME] = 0;
ref_frame_skip_mask[0] = ~(1 << ALTREF_FRAME);
ref_frame_skip_mask[0] = ~(1 << ALTREF_FRAME) & 0xff;
ref_frame_skip_mask[1] = SECOND_REF_FRAME_MASK;
}
}
@@ -3615,7 +3607,8 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, TileDataEnc *tile_data,
continue;
// Skip compound inter modes if ARF is not available.
if (!(cpi->ref_frame_flags & flag_list[second_ref_frame])) continue;
if (!(cpi->ref_frame_flags & ref_frame_to_flag(second_ref_frame)))
continue;
// Do not allow compound prediction if the segment level reference frame
// feature is in use as in this case there can only be one reference.
@@ -4146,8 +4139,6 @@ void vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, TileDataEnc *tile_data,
int comp_pred, i;
int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES];
struct buf_2d yv12_mb[4][MAX_MB_PLANE];
static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
VP9_ALT_FLAG };
int64_t best_rd = best_rd_so_far;
int64_t best_yrd = best_rd_so_far; // FIXME(rbultje) more precise
int64_t best_pred_diff[REFERENCE_MODES];
@@ -4197,7 +4188,7 @@ void vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, TileDataEnc *tile_data,
rd_cost->rate = INT_MAX;
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
if (cpi->ref_frame_flags & flag_list[ref_frame]) {
if (cpi->ref_frame_flags & ref_frame_to_flag(ref_frame)) {
setup_buffer_inter(cpi, x, ref_frame, bsize, mi_row, mi_col,
frame_mv[NEARESTMV], frame_mv[NEARMV], yv12_mb);
} else {
@@ -4282,7 +4273,8 @@ void vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, TileDataEnc *tile_data,
cm->ref_frame_sign_bias[second_ref_frame])
continue;
if (!(cpi->ref_frame_flags & flag_list[second_ref_frame])) continue;
if (!(cpi->ref_frame_flags & ref_frame_to_flag(second_ref_frame)))
continue;
// Do not allow compound prediction if the segment level reference frame
// feature is in use as in this case there can only be one reference.
if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) continue;
@@ -4446,6 +4438,7 @@ void vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, TileDataEnc *tile_data,
tmp_best_sse = total_sse;
tmp_best_skippable = skippable;
tmp_best_mbmode = *mi;
x->sum_y_eobs[TX_4X4] = 0;
for (i = 0; i < 4; i++) {
tmp_best_bmodes[i] = xd->mi[0]->bmi[i];
x->zcoeff_blk[TX_4X4][i] = !x->plane[0].eobs[i];
@@ -4479,6 +4472,11 @@ void vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, TileDataEnc *tile_data,
&rate, &rate_y, &distortion, &skippable, &total_sse,
(int)this_rd_thresh, seg_mvs, bsi, 0, mi_row, mi_col);
if (tmp_rd == INT64_MAX) continue;
x->sum_y_eobs[TX_4X4] = 0;
for (i = 0; i < 4; i++) {
x->zcoeff_blk[TX_4X4][i] = !x->plane[0].eobs[i];
x->sum_y_eobs[TX_4X4] += x->plane[0].eobs[i];
}
} else {
total_sse = tmp_best_sse;
rate = tmp_best_rate;
@@ -4736,6 +4734,13 @@ void vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, TileDataEnc *tile_data,
mi->mv[0].as_int = xd->mi[0]->bmi[3].as_mv[0].as_int;
mi->mv[1].as_int = xd->mi[0]->bmi[3].as_mv[1].as_int;
}
// If the second reference does not exist, set the corresponding mv to zero.
if (mi->ref_frame[1] == NONE) {
mi->mv[1].as_int = 0;
for (i = 0; i < 4; ++i) {
mi->bmi[i].as_mv[1].as_int = 0;
}
}
for (i = 0; i < REFERENCE_MODES; ++i) {
if (best_pred_rd[i] == INT64_MAX)
+53 -37
View File
@@ -345,7 +345,6 @@ static void set_good_speed_feature_framesize_independent(VP9_COMP *cpi,
sf->intra_y_mode_mask[TX_32X32] = INTRA_DC;
sf->intra_uv_mode_mask[TX_32X32] = INTRA_DC;
sf->adaptive_interp_filter_search = 1;
sf->allow_partition_search_skip = 1;
if (cpi->twopass.fr_content_type == FC_GRAPHICS_ANIMATION) {
for (i = 0; i < MAX_MESH_STEP; ++i) {
@@ -456,6 +455,8 @@ static void set_rt_speed_feature_framesize_independent(
sf->variance_part_thresh_mult = 1;
sf->cb_pred_filter_search = 0;
sf->force_smooth_interpol = 0;
sf->rt_intra_dc_only_low_content = 0;
sf->mv.enable_adaptive_subpel_force_stop = 0;
if (speed >= 1) {
sf->allow_txfm_domain_distortion = 1;
@@ -494,11 +495,10 @@ static void set_rt_speed_feature_framesize_independent(
(cpi->external_resize == 1 ||
cpi->oxcf.resize_mode == RESIZE_DYNAMIC)) {
MV_REFERENCE_FRAME ref_frame;
static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
VP9_ALT_FLAG };
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, ref_frame);
if (yv12 != NULL && (cpi->ref_frame_flags & flag_list[ref_frame])) {
if (yv12 != NULL &&
(cpi->ref_frame_flags & ref_frame_to_flag(ref_frame))) {
const struct scale_factors *const scale_fac =
&cm->frame_refs[ref_frame - 1].sf;
if (vp9_is_scaled(scale_fac)) sf->reference_masking = 0;
@@ -535,13 +535,6 @@ static void set_rt_speed_feature_framesize_independent(
int i;
if (cpi->oxcf.rc_mode == VPX_VBR && cpi->oxcf.lag_in_frames > 0)
sf->use_altref_onepass = 1;
sf->last_partitioning_redo_frequency = 4;
sf->adaptive_rd_thresh = 5;
sf->use_fast_coef_costing = 0;
sf->auto_min_max_partition_size = STRICT_NEIGHBORING_MIN_MAX;
sf->adjust_partitioning_from_last_frame =
cm->last_frame_type != cm->frame_type ||
(0 == (frames_since_key + 1) % sf->last_partitioning_redo_frequency);
sf->mv.subpel_force_stop = QUARTER_PEL;
for (i = 0; i < TX_SIZES; i++) {
sf->intra_y_mode_mask[i] = INTRA_DC_H_V;
@@ -550,13 +543,19 @@ static void set_rt_speed_feature_framesize_independent(
sf->intra_y_mode_mask[TX_32X32] = INTRA_DC;
sf->frame_parameter_update = 0;
sf->mv.search_method = FAST_HEX;
sf->inter_mode_mask[BLOCK_32X32] = INTER_NEAREST_NEAR_NEW;
sf->inter_mode_mask[BLOCK_32X64] = INTER_NEAREST;
sf->inter_mode_mask[BLOCK_64X32] = INTER_NEAREST;
sf->inter_mode_mask[BLOCK_64X64] = INTER_NEAREST;
sf->allow_skip_recode = 0;
sf->max_intra_bsize = BLOCK_32X32;
sf->allow_skip_recode = 1;
sf->use_fast_coef_costing = 0;
sf->use_quant_fp = !is_keyframe;
sf->inter_mode_mask[BLOCK_32X32] = INTER_NEAREST_NEW_ZERO;
sf->inter_mode_mask[BLOCK_32X64] = INTER_NEAREST_NEW_ZERO;
sf->inter_mode_mask[BLOCK_64X32] = INTER_NEAREST_NEW_ZERO;
sf->inter_mode_mask[BLOCK_64X64] = INTER_NEAREST_NEW_ZERO;
sf->adaptive_rd_thresh = 2;
sf->use_fast_coef_updates = is_keyframe ? TWO_LOOP : ONE_LOOP_REDUCED;
sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH;
sf->tx_size_search_method = is_keyframe ? USE_LARGESTALL : USE_TX_8X8;
sf->partition_search_type = VAR_BASED_PARTITION;
}
if (speed >= 5) {
@@ -620,7 +619,7 @@ static void set_rt_speed_feature_framesize_independent(
// increase in encoding time.
if (cpi->use_svc && svc->spatial_layer_id > 0) sf->nonrd_keyframe = 1;
if (cm->frame_type != KEY_FRAME && cpi->resize_state == ORIG &&
cpi->oxcf.rc_mode == VPX_CBR) {
cpi->oxcf.rc_mode == VPX_CBR && !cpi->rc.disable_overshoot_maxq_cbr) {
if (cm->width * cm->height <= 352 * 288 && !cpi->use_svc &&
cpi->oxcf.content != VP9E_CONTENT_SCREEN)
sf->overshoot_detection_cbr_rt = RE_ENCODE_MAXQ;
@@ -633,6 +632,7 @@ static void set_rt_speed_feature_framesize_independent(
sf->use_compound_nonrd_pickmode = 1;
}
if (cm->width * cm->height > 1280 * 720) sf->cb_pred_filter_search = 1;
if (!cpi->external_resize) sf->use_source_sad = 1;
}
if (speed >= 6) {
@@ -645,8 +645,6 @@ static void set_rt_speed_feature_framesize_independent(
sf->mv.reduce_first_step_size = 1;
sf->skip_encode_sb = 0;
if (!cpi->external_resize) sf->use_source_sad = 1;
if (sf->use_source_sad) {
sf->adapt_partition_source_sad = 1;
sf->adapt_partition_thresh =
@@ -654,8 +652,10 @@ static void set_rt_speed_feature_framesize_independent(
if (cpi->content_state_sb_fd == NULL &&
(!cpi->use_svc ||
svc->spatial_layer_id == svc->number_spatial_layers - 1)) {
cpi->content_state_sb_fd = (uint8_t *)vpx_calloc(
(cm->mi_stride >> 3) * ((cm->mi_rows >> 3) + 1), sizeof(uint8_t));
CHECK_MEM_ERROR(cm, cpi->content_state_sb_fd,
(uint8_t *)vpx_calloc(
(cm->mi_stride >> 3) * ((cm->mi_rows >> 3) + 1),
sizeof(uint8_t)));
}
}
if (cpi->oxcf.rc_mode == VPX_CBR && content != VP9E_CONTENT_SCREEN) {
@@ -668,7 +668,7 @@ static void set_rt_speed_feature_framesize_independent(
sf->base_mv_aggressive = 1;
}
if (cm->frame_type != KEY_FRAME && cpi->resize_state == ORIG &&
cpi->oxcf.rc_mode == VPX_CBR)
cpi->oxcf.rc_mode == VPX_CBR && !cpi->rc.disable_overshoot_maxq_cbr)
sf->overshoot_detection_cbr_rt = FAST_DETECTION_MAXQ;
}
@@ -727,7 +727,10 @@ static void set_rt_speed_feature_framesize_independent(
if (speed >= 8) {
sf->adaptive_rd_thresh = 4;
sf->skip_encode_sb = 1;
sf->nonrd_keyframe = 1;
if (cpi->svc.number_spatial_layers > 1 && !cpi->svc.simulcast_mode)
sf->nonrd_keyframe = 0;
else
sf->nonrd_keyframe = 1;
if (!cpi->use_svc) cpi->max_copied_frame = 4;
if (cpi->row_mt && cpi->oxcf.max_threads > 1)
sf->adaptive_rd_thresh_row_mt = 1;
@@ -740,12 +743,7 @@ static void set_rt_speed_feature_framesize_independent(
sf->nonrd_use_ml_partition = 0;
#endif
if (content == VP9E_CONTENT_SCREEN) sf->mv.subpel_force_stop = HALF_PEL;
// Only keep INTRA_DC mode for speed 8.
if (!is_keyframe) {
int i = 0;
for (i = 0; i < BLOCK_SIZES; ++i)
sf->intra_y_mode_bsize_mask[i] = INTRA_DC;
}
sf->rt_intra_dc_only_low_content = 1;
if (!cpi->use_svc && cpi->oxcf.rc_mode == VPX_CBR &&
content != VP9E_CONTENT_SCREEN) {
// More aggressive short circuit for speed 8.
@@ -771,6 +769,12 @@ static void set_rt_speed_feature_framesize_independent(
}
if (speed >= 9) {
// Only keep INTRA_DC mode for speed 9.
if (!is_keyframe) {
int i = 0;
for (i = 0; i < BLOCK_SIZES; ++i)
sf->intra_y_mode_bsize_mask[i] = INTRA_DC;
}
sf->cb_pred_filter_search = 1;
sf->mv.enable_adaptive_subpel_force_stop = 1;
sf->mv.adapt_subpel_force_stop.mv_thresh = 1;
@@ -785,6 +789,15 @@ static void set_rt_speed_feature_framesize_independent(
if (cm->width * cm->height >= 640 * 360) sf->variance_part_thresh_mult = 2;
}
// Disable split to 8x8 for low-resolution at very high Q.
// For variance partition (speed >= 6). Ignore the first few frames
// as avg_frame_qindex starts at max_q (worst_quality).
if (cm->frame_type != KEY_FRAME && cm->width * cm->height <= 320 * 240 &&
sf->partition_search_type == VAR_BASED_PARTITION &&
cpi->rc.avg_frame_qindex[INTER_FRAME] > 208 &&
cpi->common.current_video_frame > 8)
sf->disable_16x16part_nonkey = 1;
if (sf->nonrd_use_ml_partition)
sf->partition_search_type = ML_BASED_PARTITION;
@@ -793,14 +806,17 @@ static void set_rt_speed_feature_framesize_independent(
sf->partition_search_type = FIXED_PARTITION;
sf->always_this_block_size = BLOCK_64X64;
}
if (cpi->count_arf_frame_usage == NULL)
cpi->count_arf_frame_usage =
if (cpi->count_arf_frame_usage == NULL) {
CHECK_MEM_ERROR(
cm, cpi->count_arf_frame_usage,
(uint8_t *)vpx_calloc((cm->mi_stride >> 3) * ((cm->mi_rows >> 3) + 1),
sizeof(*cpi->count_arf_frame_usage));
sizeof(*cpi->count_arf_frame_usage)));
}
if (cpi->count_lastgolden_frame_usage == NULL)
cpi->count_lastgolden_frame_usage =
CHECK_MEM_ERROR(
cm, cpi->count_lastgolden_frame_usage,
(uint8_t *)vpx_calloc((cm->mi_stride >> 3) * ((cm->mi_rows >> 3) + 1),
sizeof(*cpi->count_lastgolden_frame_usage));
sizeof(*cpi->count_lastgolden_frame_usage)));
}
if (svc->previous_frame_is_intra_only) {
sf->partition_search_type = FIXED_PARTITION;
@@ -817,7 +833,7 @@ static void set_rt_speed_feature_framesize_independent(
}
// TODO(marpan): There is regression for aq-mode=3 speed <= 4, force it
// off for now.
if (speed <= 4 && cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
if (speed <= 3 && cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
cpi->oxcf.aq_mode = 0;
}
@@ -918,7 +934,6 @@ void vp9_set_speed_features_framesize_independent(VP9_COMP *cpi, int speed) {
sf->max_delta_qindex = 0;
sf->disable_filter_search_var_thresh = 0;
sf->adaptive_interp_filter_search = 0;
sf->allow_partition_search_skip = 0;
sf->allow_txfm_domain_distortion = 0;
sf->tx_domain_thresh = 99.0;
sf->allow_quant_coeff_opt = sf->optimize_coefficients;
@@ -927,6 +942,7 @@ void vp9_set_speed_features_framesize_independent(VP9_COMP *cpi, int speed) {
sf->enable_tpl_model = oxcf->enable_tpl_model;
sf->prune_ref_frame_for_rect_partitions = 0;
sf->temporal_filter_search_method = MESH;
sf->allow_skip_txfm_ac_dc = 0;
for (i = 0; i < TX_SIZES; i++) {
sf->intra_y_mode_mask[i] = INTRA_ALL;
+10 -3
View File
@@ -525,9 +525,6 @@ typedef struct SPEED_FEATURES {
int prune_rect_thresh[4];
} rd_ml_partition;
// Allow skipping partition search for still image frame
int allow_partition_search_skip;
// Fast approximation of vp9_model_rd_from_var_lapndz
int simple_model_rd_from_var;
@@ -608,6 +605,16 @@ typedef struct SPEED_FEATURES {
// Force subpel motion filter to always use SMOOTH_FILTER.
int force_smooth_interpol;
// For real-time mode: force DC only under intra search when content
// does not have high souce SAD.
int rt_intra_dc_only_low_content;
// The encoder has a feature that skips forward transform and quantization
// based on a model rd estimation to reduce encoding time.
// However, this feature is dangerous since it could lead to bad perceptual
// quality. This flag is added to guard the feature.
int allow_skip_txfm_ac_dc;
} SPEED_FEATURES;
struct VP9_COMP;
+22 -21
View File
@@ -75,7 +75,7 @@ static int remap_prob(int v, int m) {
i = recenter_nonneg(MAX_PROB - 1 - v, MAX_PROB - 1 - m) - 1;
assert(i >= 0 && (size_t)i < sizeof(map_table));
if (i >= 0 && (size_t)i < sizeof(map_table)) i = map_table[i];
i = map_table[i];
return i;
}
@@ -117,19 +117,20 @@ void vp9_write_prob_diff_update(vpx_writer *w, vpx_prob newp, vpx_prob oldp) {
encode_term_subexp(w, delp);
}
int vp9_prob_diff_update_savings_search(const unsigned int *ct, vpx_prob oldp,
vpx_prob *bestp, vpx_prob upd) {
const int old_b = cost_branch256(ct, oldp);
int bestsavings = 0;
int64_t vp9_prob_diff_update_savings_search(const unsigned int *ct,
vpx_prob oldp, vpx_prob *bestp,
vpx_prob upd) {
const int64_t old_b = cost_branch256(ct, oldp);
int64_t bestsavings = 0;
vpx_prob newp, bestnewp = oldp;
const int step = *bestp > oldp ? -1 : 1;
const int upd_cost = vp9_cost_one(upd) - vp9_cost_zero(upd);
if (old_b > upd_cost + (MIN_DELP_BITS << VP9_PROB_COST_SHIFT)) {
for (newp = *bestp; newp != oldp; newp += step) {
const int new_b = cost_branch256(ct, newp);
const int update_b = prob_diff_update_cost(newp, oldp) + upd_cost;
const int savings = old_b - new_b - update_b;
const int64_t new_b = cost_branch256(ct, newp);
const int64_t update_b = prob_diff_update_cost(newp, oldp) + upd_cost;
const int64_t savings = old_b - new_b - update_b;
if (savings > bestsavings) {
bestsavings = savings;
bestnewp = newp;
@@ -140,15 +141,15 @@ int vp9_prob_diff_update_savings_search(const unsigned int *ct, vpx_prob oldp,
return bestsavings;
}
int vp9_prob_diff_update_savings_search_model(const unsigned int *ct,
const vpx_prob oldp,
vpx_prob *bestp, vpx_prob upd,
int stepsize) {
int i, old_b, new_b, update_b, savings, bestsavings;
int newp;
const int step_sign = *bestp > oldp ? -1 : 1;
const int step = stepsize * step_sign;
const int upd_cost = vp9_cost_one(upd) - vp9_cost_zero(upd);
int64_t vp9_prob_diff_update_savings_search_model(const unsigned int *ct,
const vpx_prob oldp,
vpx_prob *bestp, vpx_prob upd,
int stepsize) {
int64_t i, old_b, new_b, update_b, savings, bestsavings;
int64_t newp;
const int64_t step_sign = *bestp > oldp ? -1 : 1;
const int64_t step = stepsize * step_sign;
const int64_t upd_cost = vp9_cost_one(upd) - vp9_cost_zero(upd);
const vpx_prob *newplist, *oldplist;
vpx_prob bestnewp;
oldplist = vp9_pareto8_full[oldp - 1];
@@ -165,14 +166,14 @@ int vp9_prob_diff_update_savings_search_model(const unsigned int *ct,
for (newp = *bestp; (newp - oldp) * step_sign < 0; newp += step) {
if (newp < 1 || newp > 255) continue;
newplist = vp9_pareto8_full[newp - 1];
new_b = cost_branch256(ct + 2 * PIVOT_NODE, newp);
new_b = cost_branch256(ct + 2 * PIVOT_NODE, (vpx_prob)newp);
for (i = UNCONSTRAINED_NODES; i < ENTROPY_NODES; ++i)
new_b += cost_branch256(ct + 2 * i, newplist[i - UNCONSTRAINED_NODES]);
update_b = prob_diff_update_cost(newp, oldp) + upd_cost;
update_b = prob_diff_update_cost((vpx_prob)newp, oldp) + upd_cost;
savings = old_b - new_b - update_b;
if (savings > bestsavings) {
bestsavings = savings;
bestnewp = newp;
bestnewp = (vpx_prob)newp;
}
}
}
@@ -185,7 +186,7 @@ void vp9_cond_prob_diff_update(vpx_writer *w, vpx_prob *oldp,
const unsigned int ct[2]) {
const vpx_prob upd = DIFF_UPDATE_PROB;
vpx_prob newp = get_binary_prob(ct[0], ct[1]);
const int savings =
const int64_t savings =
vp9_prob_diff_update_savings_search(ct, *oldp, &newp, upd);
assert(newp >= 1);
if (savings > 0) {
+7 -6
View File
@@ -25,13 +25,14 @@ void vp9_write_prob_diff_update(struct vpx_writer *w, vpx_prob newp,
void vp9_cond_prob_diff_update(struct vpx_writer *w, vpx_prob *oldp,
const unsigned int ct[2]);
int vp9_prob_diff_update_savings_search(const unsigned int *ct, vpx_prob oldp,
vpx_prob *bestp, vpx_prob upd);
int64_t vp9_prob_diff_update_savings_search(const unsigned int *ct,
vpx_prob oldp, vpx_prob *bestp,
vpx_prob upd);
int vp9_prob_diff_update_savings_search_model(const unsigned int *ct,
const vpx_prob oldp,
vpx_prob *bestp, vpx_prob upd,
int stepsize);
int64_t vp9_prob_diff_update_savings_search_model(const unsigned int *ct,
const vpx_prob oldp,
vpx_prob *bestp, vpx_prob upd,
int stepsize);
#ifdef __cplusplus
} // extern "C"
+83 -36
View File
@@ -55,10 +55,12 @@ void vp9_init_layer_context(VP9_COMP *const cpi) {
svc->use_set_ref_frame_config = 0;
svc->num_encoded_top_layer = 0;
svc->simulcast_mode = 0;
svc->single_layer_svc = 0;
svc->resize_set = 0;
for (i = 0; i < REF_FRAMES; ++i) {
svc->fb_idx_spatial_layer_id[i] = -1;
svc->fb_idx_temporal_layer_id[i] = -1;
svc->fb_idx_spatial_layer_id[i] = 0xff;
svc->fb_idx_temporal_layer_id[i] = 0xff;
svc->fb_idx_base[i] = 0;
}
for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
@@ -74,6 +76,7 @@ void vp9_init_layer_context(VP9_COMP *const cpi) {
svc->fb_idx_upd_tl0[sl] = -1;
svc->drop_count[sl] = 0;
svc->spatial_layer_sync[sl] = 0;
svc->force_drop_constrained_from_above[sl] = 0;
}
svc->max_consec_drop = INT_MAX;
@@ -192,6 +195,7 @@ void vp9_update_layer_context_change_config(VP9_COMP *const cpi,
const RATE_CONTROL *const rc = &cpi->rc;
int sl, tl, layer = 0, spatial_layer_target;
float bitrate_alloc = 1.0;
int num_spatial_layers_nonzero_rate = 0;
cpi->svc.temporal_layering_mode = oxcf->temporal_layering_mode;
@@ -272,6 +276,17 @@ void vp9_update_layer_context_change_config(VP9_COMP *const cpi,
lrc->best_quality = rc->best_quality;
}
}
for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
// Check bitrate of spatia layer.
layer = LAYER_IDS_TO_IDX(sl, oxcf->ts_number_layers - 1,
oxcf->ts_number_layers);
if (oxcf->layer_target_bitrate[layer] > 0)
num_spatial_layers_nonzero_rate += 1;
}
if (num_spatial_layers_nonzero_rate == 1)
svc->single_layer_svc = 1;
else
svc->single_layer_svc = 0;
}
static LAYER_CONTEXT *get_layer_context(VP9_COMP *const cpi) {
@@ -307,8 +322,8 @@ void vp9_update_temporal_layer_framerate(VP9_COMP *const cpi) {
const int prev_layer_target_bandwidth =
oxcf->layer_target_bitrate[st_idx - 1];
lc->avg_frame_size =
(int)((lc->target_bandwidth - prev_layer_target_bandwidth) /
(lc->framerate - prev_layer_framerate));
(int)round((lc->target_bandwidth - prev_layer_target_bandwidth) /
(lc->framerate - prev_layer_framerate));
}
}
@@ -342,6 +357,7 @@ void vp9_restore_layer_context(VP9_COMP *const cpi) {
if (is_one_pass_cbr_svc(cpi) && lc->speed > 0) {
cpi->oxcf.speed = lc->speed;
}
cpi->loopfilter_ctrl = lc->loopfilter_ctrl;
// Reset the frames_since_key and frames_to_key counters to their values
// before the layer restore. Keep these defined for the stream (not layer).
if (cpi->svc.number_temporal_layers > 1 ||
@@ -446,30 +462,27 @@ static void reset_fb_idx_unused(VP9_COMP *const cpi) {
// fb_idx for that reference to the first one used/referenced.
// This is to avoid setting fb_idx for a reference to a slot that is not
// used/needed (i.e., since that reference is not referenced or refreshed).
static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
VP9_ALT_FLAG };
MV_REFERENCE_FRAME ref_frame;
MV_REFERENCE_FRAME first_ref = 0;
int first_fb_idx = 0;
int fb_idx[3] = { cpi->lst_fb_idx, cpi->gld_fb_idx, cpi->alt_fb_idx };
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
if (cpi->ref_frame_flags & flag_list[ref_frame]) {
if (cpi->ref_frame_flags & ref_frame_to_flag(ref_frame)) {
first_ref = ref_frame;
first_fb_idx = fb_idx[ref_frame - 1];
break;
}
}
if (first_ref > 0) {
if (first_ref != LAST_FRAME &&
!(cpi->ref_frame_flags & flag_list[LAST_FRAME]) &&
if (first_ref != LAST_FRAME && !(cpi->ref_frame_flags & VP9_LAST_FLAG) &&
!cpi->ext_refresh_last_frame)
cpi->lst_fb_idx = first_fb_idx;
else if (first_ref != GOLDEN_FRAME &&
!(cpi->ref_frame_flags & flag_list[GOLDEN_FRAME]) &&
!(cpi->ref_frame_flags & VP9_GOLD_FLAG) &&
!cpi->ext_refresh_golden_frame)
cpi->gld_fb_idx = first_fb_idx;
else if (first_ref != ALTREF_FRAME &&
!(cpi->ref_frame_flags & flag_list[ALTREF_FRAME]) &&
!(cpi->ref_frame_flags & VP9_ALT_FLAG) &&
!cpi->ext_refresh_alt_ref_frame)
cpi->alt_fb_idx = first_fb_idx;
}
@@ -714,8 +727,6 @@ static void set_flags_and_fb_idx_bypass_via_set_ref_frame_config(
void vp9_copy_flags_ref_update_idx(VP9_COMP *const cpi) {
SVC *const svc = &cpi->svc;
static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
VP9_ALT_FLAG };
int sl = svc->spatial_layer_id;
svc->lst_fb_idx[sl] = cpi->lst_fb_idx;
svc->gld_fb_idx[sl] = cpi->gld_fb_idx;
@@ -738,25 +749,22 @@ void vp9_copy_flags_ref_update_idx(VP9_COMP *const cpi) {
svc->update_golden[sl] = (uint8_t)cpi->refresh_golden_frame;
svc->update_altref[sl] = (uint8_t)cpi->refresh_alt_ref_frame;
svc->reference_last[sl] =
(uint8_t)(cpi->ref_frame_flags & flag_list[LAST_FRAME]);
svc->reference_golden[sl] =
(uint8_t)(cpi->ref_frame_flags & flag_list[GOLDEN_FRAME]);
svc->reference_altref[sl] =
(uint8_t)(cpi->ref_frame_flags & flag_list[ALTREF_FRAME]);
svc->reference_last[sl] = (uint8_t)(cpi->ref_frame_flags & VP9_LAST_FLAG);
svc->reference_golden[sl] = (uint8_t)(cpi->ref_frame_flags & VP9_GOLD_FLAG);
svc->reference_altref[sl] = (uint8_t)(cpi->ref_frame_flags & VP9_ALT_FLAG);
}
int vp9_one_pass_cbr_svc_start_layer(VP9_COMP *const cpi) {
int width = 0, height = 0;
SVC *const svc = &cpi->svc;
LAYER_CONTEXT *lc = NULL;
int scaling_factor_num = 1;
int scaling_factor_den = 1;
svc->skip_enhancement_layer = 0;
if (svc->disable_inter_layer_pred == INTER_LAYER_PRED_OFF &&
svc->number_spatial_layers > 1 && svc->number_spatial_layers <= 3 &&
svc->number_temporal_layers <= 3 &&
!(svc->temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS &&
svc->use_set_ref_frame_config))
svc->number_temporal_layers <= 3)
svc->simulcast_mode = 1;
else
svc->simulcast_mode = 0;
@@ -770,6 +778,32 @@ int vp9_one_pass_cbr_svc_start_layer(VP9_COMP *const cpi) {
svc->mi_rows[svc->spatial_layer_id] = cpi->common.mi_rows;
svc->mi_cols[svc->spatial_layer_id] = cpi->common.mi_cols;
// For constrained_from_above drop mode: before encoding superframe (i.e.,
// at SL0 frame) check all spatial layers (starting from top) for possible
// drop, and if so, set a flag to force drop of that layer and all its lower
// layers.
if (svc->spatial_layer_to_encode == svc->first_spatial_layer_to_encode) {
int sl;
for (sl = 0; sl < svc->number_spatial_layers; sl++)
svc->force_drop_constrained_from_above[sl] = 0;
if (svc->framedrop_mode == CONSTRAINED_FROM_ABOVE_DROP) {
for (sl = svc->number_spatial_layers - 1;
sl >= svc->first_spatial_layer_to_encode; sl--) {
int layer = sl * svc->number_temporal_layers + svc->temporal_layer_id;
LAYER_CONTEXT *const lc = &svc->layer_context[layer];
cpi->rc = lc->rc;
cpi->oxcf.target_bandwidth = lc->target_bandwidth;
if (vp9_test_drop(cpi)) {
int sl2;
// Set flag to force drop in encoding for this mode.
for (sl2 = sl; sl2 >= svc->first_spatial_layer_to_encode; sl2--)
svc->force_drop_constrained_from_above[sl2] = 1;
break;
}
}
}
}
if (svc->temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_0212) {
set_flags_and_fb_idx_for_temporal_mode3(cpi);
} else if (svc->temporal_layering_mode ==
@@ -824,8 +858,9 @@ int vp9_one_pass_cbr_svc_start_layer(VP9_COMP *const cpi) {
}
}
// Reset the drop flags for all spatial layers, on the base layer.
if (svc->spatial_layer_id == 0) {
// Reset the drop flags for all spatial layers, on the
// first_spatial_layer_to_encode.
if (svc->spatial_layer_id == svc->first_spatial_layer_to_encode) {
vp9_zero(svc->drop_spatial_layer);
// TODO(jianj/marpan): Investigate why setting svc->lst/gld/alt_fb_idx
// causes an issue with frame dropping and temporal layers, when the frame
@@ -861,18 +896,25 @@ int vp9_one_pass_cbr_svc_start_layer(VP9_COMP *const cpi) {
lrc->best_quality = vp9_quantizer_to_qindex(lc->min_q);
}
get_layer_resolution(cpi->oxcf.width, cpi->oxcf.height,
lc->scaling_factor_num, lc->scaling_factor_den, &width,
&height);
if (cpi->oxcf.resize_mode == RESIZE_DYNAMIC && svc->single_layer_svc == 1 &&
svc->spatial_layer_id == svc->first_spatial_layer_to_encode &&
cpi->resize_state != ORIG) {
scaling_factor_num = lc->scaling_factor_num_resize;
scaling_factor_den = lc->scaling_factor_den_resize;
} else {
scaling_factor_num = lc->scaling_factor_num;
scaling_factor_den = lc->scaling_factor_den;
}
get_layer_resolution(cpi->oxcf.width, cpi->oxcf.height, scaling_factor_num,
scaling_factor_den, &width, &height);
// Use Eightap_smooth for low resolutions.
if (width * height <= 320 * 240)
svc->downsample_filter_type[svc->spatial_layer_id] = EIGHTTAP_SMOOTH;
// For scale factors > 0.75, set the phase to 0 (aligns decimated pixel
// to source pixel).
lc = &svc->layer_context[svc->spatial_layer_id * svc->number_temporal_layers +
svc->temporal_layer_id];
if (lc->scaling_factor_num > (3 * lc->scaling_factor_den) >> 2)
if (scaling_factor_num > (3 * scaling_factor_den) >> 2)
svc->downsample_filter_phase[svc->spatial_layer_id] = 0;
// The usage of use_base_mv or partition_reuse assumes down-scale of 2x2.
@@ -906,7 +948,7 @@ int vp9_one_pass_cbr_svc_start_layer(VP9_COMP *const cpi) {
if (cpi->common.frame_type != KEY_FRAME && !cpi->ext_refresh_last_frame &&
!cpi->ext_refresh_golden_frame && !cpi->ext_refresh_alt_ref_frame)
svc->non_reference_frame = 1;
// For non-flexible mode, where update_buffer_slot is used, need to check if
// For flexible mode, where update_buffer_slot is used, need to check if
// all buffer slots are not refreshed.
if (svc->temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
if (svc->update_buffer_slot[svc->spatial_layer_id] != 0)
@@ -1030,15 +1072,14 @@ void vp9_svc_constrain_inter_layer_pred(VP9_COMP *const cpi) {
svc->disable_inter_layer_pred == INTER_LAYER_PRED_OFF ||
svc->drop_spatial_layer[sl - 1]) {
MV_REFERENCE_FRAME ref_frame;
static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
VP9_ALT_FLAG };
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, ref_frame);
if (yv12 != NULL && (cpi->ref_frame_flags & flag_list[ref_frame])) {
if (yv12 != NULL &&
(cpi->ref_frame_flags & ref_frame_to_flag(ref_frame))) {
const struct scale_factors *const scale_fac =
&cm->frame_refs[ref_frame - 1].sf;
if (vp9_is_scaled(scale_fac)) {
cpi->ref_frame_flags &= (~flag_list[ref_frame]);
cpi->ref_frame_flags &= (~ref_frame_to_flag(ref_frame));
// Point golden/altref frame buffer index to last.
if (!svc->simulcast_mode) {
if (ref_frame == GOLDEN_FRAME)
@@ -1193,6 +1234,7 @@ void vp9_svc_check_spatial_layer_sync(VP9_COMP *const cpi) {
void vp9_svc_update_ref_frame_buffer_idx(VP9_COMP *const cpi) {
SVC *const svc = &cpi->svc;
int i = 0;
// Update the usage of frame buffer index for base spatial layers.
if (svc->spatial_layer_id == 0) {
if ((cpi->ref_frame_flags & VP9_LAST_FLAG) || cpi->refresh_last_frame)
@@ -1201,6 +1243,11 @@ void vp9_svc_update_ref_frame_buffer_idx(VP9_COMP *const cpi) {
svc->fb_idx_base[cpi->gld_fb_idx] = 1;
if ((cpi->ref_frame_flags & VP9_ALT_FLAG) || cpi->refresh_alt_ref_frame)
svc->fb_idx_base[cpi->alt_fb_idx] = 1;
// For bypass/flexible mode: check for refresh slots.
if (svc->temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
for (i = 0; i < REF_FRAMES; ++i)
if (svc->update_buffer_slot[0] & (1 << i)) svc->fb_idx_base[i] = 1;
}
}
}
@@ -1212,7 +1259,7 @@ static void vp9_svc_update_ref_frame_bypass_mode(VP9_COMP *const cpi) {
BufferPool *const pool = cm->buffer_pool;
int i;
for (i = 0; i < REF_FRAMES; i++) {
if (cm->frame_type == KEY_FRAME ||
if ((cm->frame_type == KEY_FRAME && !svc->simulcast_mode) ||
svc->update_buffer_slot[svc->spatial_layer_id] & (1 << i)) {
ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[i], cm->new_fb_idx);
svc->fb_idx_spatial_layer_id[i] = svc->spatial_layer_id;
+11 -1
View File
@@ -47,6 +47,9 @@ typedef struct {
int min_q;
int scaling_factor_num;
int scaling_factor_den;
// Scaling factors used for internal resize scaling for single layer SVC.
int scaling_factor_num_resize;
int scaling_factor_den_resize;
TWO_PASS twopass;
vpx_fixed_buf_t rc_twopass_stats_in;
unsigned int current_video_frame_in_layer;
@@ -58,7 +61,6 @@ typedef struct {
int gold_ref_idx;
int has_alt_frame;
size_t layer_size;
struct vpx_psnr_pkt psnr_pkt;
// Cyclic refresh parameters (aq-mode=3), that need to be updated per-frame.
// TODO(jianj/marpan): Is it better to use the full cyclic refresh struct.
int sb_index;
@@ -69,6 +71,7 @@ typedef struct {
int actual_num_seg2_blocks;
int counter_encode_maxq_scene_change;
uint8_t speed;
int loopfilter_ctrl;
} LAYER_CONTEXT;
typedef struct SVC {
@@ -138,6 +141,7 @@ typedef struct SVC {
int drop_spatial_layer[VPX_MAX_LAYERS];
int framedrop_thresh[VPX_MAX_LAYERS];
int drop_count[VPX_MAX_LAYERS];
int force_drop_constrained_from_above[VPX_MAX_LAYERS];
int max_consec_drop;
SVC_LAYER_DROP_MODE framedrop_mode;
@@ -169,6 +173,8 @@ typedef struct SVC {
uint8_t fb_idx_temporal_layer_id[REF_FRAMES];
int spatial_layer_sync[VPX_SS_MAX_LAYERS];
// Quantizer for each spatial layer.
int base_qindex[VPX_SS_MAX_LAYERS];
uint8_t set_intra_only_frame;
uint8_t previous_frame_is_intra_only;
uint8_t superframe_has_layer_sync;
@@ -192,6 +198,10 @@ typedef struct SVC {
// Every spatial layer on a superframe whose base is key is key too.
int simulcast_mode;
// Flag to indicate SVC is dynamically switched to a single layer.
int single_layer_svc;
int resize_set;
} SVC;
struct VP9_COMP;
@@ -270,13 +270,11 @@ static INLINE void add_luma_dist_to_8_chroma_mod(const uint16_t *y_dist,
// size 4 for the weights for each of the 4 subblocks if blk_fw is not NULL,
// else use top_weight for top half, and bottom weight for bottom half.
static void vp9_apply_temporal_filter_luma_16(
const uint8_t *y_src, int y_src_stride, const uint8_t *y_pre,
int y_pre_stride, const uint8_t *u_src, const uint8_t *v_src,
int uv_src_stride, const uint8_t *u_pre, const uint8_t *v_pre,
int uv_pre_stride, unsigned int block_width, unsigned int block_height,
int ss_x, int ss_y, int strength, int use_whole_blk, uint32_t *y_accum,
uint16_t *y_count, const uint16_t *y_dist, const uint16_t *u_dist,
const uint16_t *v_dist, const int16_t *const *neighbors_first,
const uint8_t *y_pre, int y_pre_stride, unsigned int block_width,
unsigned int block_height, int ss_x, int ss_y, int strength,
int use_whole_blk, uint32_t *y_accum, uint16_t *y_count,
const uint16_t *y_dist, const uint16_t *u_dist, const uint16_t *v_dist,
const int16_t *const *neighbors_first,
const int16_t *const *neighbors_second, int top_weight, int bottom_weight,
const int *blk_fw) {
const int rounding = (1 << strength) >> 1;
@@ -301,7 +299,6 @@ static void vp9_apply_temporal_filter_luma_16(
assert(strength <= 6);
assert(block_width == 16);
(void)block_width;
// Initialize the weights
@@ -342,17 +339,12 @@ static void vp9_apply_temporal_filter_luma_16(
accumulate_and_store_16(sum_row_first, sum_row_second, y_pre, y_count,
y_accum);
y_src += y_src_stride;
y_pre += y_pre_stride;
y_count += y_pre_stride;
y_accum += y_pre_stride;
y_dist += DIST_STRIDE;
u_src += uv_src_stride;
u_pre += uv_pre_stride;
u_dist += DIST_STRIDE;
v_src += uv_src_stride;
v_pre += uv_pre_stride;
v_dist += DIST_STRIDE;
// Then all the rows except the last one
@@ -392,11 +384,7 @@ static void vp9_apply_temporal_filter_luma_16(
read_chroma_dist_row_16(ss_x, u_dist, v_dist, &u_first, &u_second,
&v_first, &v_second);
u_src += uv_src_stride;
u_pre += uv_pre_stride;
u_dist += DIST_STRIDE;
v_src += uv_src_stride;
v_pre += uv_pre_stride;
v_dist += DIST_STRIDE;
}
@@ -413,7 +401,6 @@ static void vp9_apply_temporal_filter_luma_16(
accumulate_and_store_16(sum_row_first, sum_row_second, y_pre, y_count,
y_accum);
y_src += y_src_stride;
y_pre += y_pre_stride;
y_count += y_pre_stride;
y_accum += y_pre_stride;
@@ -458,13 +445,10 @@ static void vp9_apply_temporal_filter_luma_16(
// Perform temporal filter for the luma component.
static void vp9_apply_temporal_filter_luma(
const uint8_t *y_src, int y_src_stride, const uint8_t *y_pre,
int y_pre_stride, const uint8_t *u_src, const uint8_t *v_src,
int uv_src_stride, const uint8_t *u_pre, const uint8_t *v_pre,
int uv_pre_stride, unsigned int block_width, unsigned int block_height,
int ss_x, int ss_y, int strength, const int *blk_fw, int use_whole_blk,
uint32_t *y_accum, uint16_t *y_count, const uint16_t *y_dist,
const uint16_t *u_dist, const uint16_t *v_dist) {
const uint8_t *y_pre, int y_pre_stride, unsigned int block_width,
unsigned int block_height, int ss_x, int ss_y, int strength,
const int *blk_fw, int use_whole_blk, uint32_t *y_accum, uint16_t *y_count,
const uint16_t *y_dist, const uint16_t *u_dist, const uint16_t *v_dist) {
unsigned int blk_col = 0, uv_blk_col = 0;
const unsigned int blk_col_step = 16, uv_blk_col_step = 16 >> ss_x;
const unsigned int mid_width = block_width >> 1,
@@ -476,27 +460,22 @@ static void vp9_apply_temporal_filter_luma(
if (block_width == 16) {
// Special Case: The blockwidth is 16 and we are operating on a row of 16
// chroma pixels. In this case, we can't use the usualy left-midle-right
// chroma pixels. In this case, we can't use the usual left-middle-right
// pattern. We also don't support splitting now.
neighbors_first = LUMA_LEFT_COLUMN_NEIGHBORS;
neighbors_second = LUMA_RIGHT_COLUMN_NEIGHBORS;
if (use_whole_blk) {
vp9_apply_temporal_filter_luma_16(
y_src + blk_col, y_src_stride, y_pre + blk_col, y_pre_stride,
u_src + uv_blk_col, v_src + uv_blk_col, uv_src_stride,
u_pre + uv_blk_col, v_pre + uv_blk_col, uv_pre_stride, 16,
block_height, ss_x, ss_y, strength, use_whole_blk, y_accum + blk_col,
y_count + blk_col, y_dist + blk_col, u_dist + uv_blk_col,
v_dist + uv_blk_col, neighbors_first, neighbors_second, top_weight,
bottom_weight, NULL);
y_pre + blk_col, y_pre_stride, 16, block_height, ss_x, ss_y, strength,
use_whole_blk, y_accum + blk_col, y_count + blk_col, y_dist + blk_col,
u_dist + uv_blk_col, v_dist + uv_blk_col, neighbors_first,
neighbors_second, top_weight, bottom_weight, NULL);
} else {
vp9_apply_temporal_filter_luma_16(
y_src + blk_col, y_src_stride, y_pre + blk_col, y_pre_stride,
u_src + uv_blk_col, v_src + uv_blk_col, uv_src_stride,
u_pre + uv_blk_col, v_pre + uv_blk_col, uv_pre_stride, 16,
block_height, ss_x, ss_y, strength, use_whole_blk, y_accum + blk_col,
y_count + blk_col, y_dist + blk_col, u_dist + uv_blk_col,
v_dist + uv_blk_col, neighbors_first, neighbors_second, 0, 0, blk_fw);
y_pre + blk_col, y_pre_stride, 16, block_height, ss_x, ss_y, strength,
use_whole_blk, y_accum + blk_col, y_count + blk_col, y_dist + blk_col,
u_dist + uv_blk_col, v_dist + uv_blk_col, neighbors_first,
neighbors_second, 0, 0, blk_fw);
}
return;
@@ -506,9 +485,7 @@ static void vp9_apply_temporal_filter_luma(
neighbors_first = LUMA_LEFT_COLUMN_NEIGHBORS;
neighbors_second = LUMA_MIDDLE_COLUMN_NEIGHBORS;
vp9_apply_temporal_filter_luma_16(
y_src + blk_col, y_src_stride, y_pre + blk_col, y_pre_stride,
u_src + uv_blk_col, v_src + uv_blk_col, uv_src_stride, u_pre + uv_blk_col,
v_pre + uv_blk_col, uv_pre_stride, 16, block_height, ss_x, ss_y, strength,
y_pre + blk_col, y_pre_stride, 16, block_height, ss_x, ss_y, strength,
use_whole_blk, y_accum + blk_col, y_count + blk_col, y_dist + blk_col,
u_dist + uv_blk_col, v_dist + uv_blk_col, neighbors_first,
neighbors_second, top_weight, bottom_weight, NULL);
@@ -521,13 +498,10 @@ static void vp9_apply_temporal_filter_luma(
for (; blk_col < mid_width;
blk_col += blk_col_step, uv_blk_col += uv_blk_col_step) {
vp9_apply_temporal_filter_luma_16(
y_src + blk_col, y_src_stride, y_pre + blk_col, y_pre_stride,
u_src + uv_blk_col, v_src + uv_blk_col, uv_src_stride,
u_pre + uv_blk_col, v_pre + uv_blk_col, uv_pre_stride, 16, block_height,
ss_x, ss_y, strength, use_whole_blk, y_accum + blk_col,
y_count + blk_col, y_dist + blk_col, u_dist + uv_blk_col,
v_dist + uv_blk_col, neighbors_first, neighbors_second, top_weight,
bottom_weight, NULL);
y_pre + blk_col, y_pre_stride, 16, block_height, ss_x, ss_y, strength,
use_whole_blk, y_accum + blk_col, y_count + blk_col, y_dist + blk_col,
u_dist + uv_blk_col, v_dist + uv_blk_col, neighbors_first,
neighbors_second, top_weight, bottom_weight, NULL);
}
if (!use_whole_blk) {
@@ -539,21 +513,16 @@ static void vp9_apply_temporal_filter_luma(
for (; blk_col < last_width;
blk_col += blk_col_step, uv_blk_col += uv_blk_col_step) {
vp9_apply_temporal_filter_luma_16(
y_src + blk_col, y_src_stride, y_pre + blk_col, y_pre_stride,
u_src + uv_blk_col, v_src + uv_blk_col, uv_src_stride,
u_pre + uv_blk_col, v_pre + uv_blk_col, uv_pre_stride, 16, block_height,
ss_x, ss_y, strength, use_whole_blk, y_accum + blk_col,
y_count + blk_col, y_dist + blk_col, u_dist + uv_blk_col,
v_dist + uv_blk_col, neighbors_first, neighbors_second, top_weight,
bottom_weight, NULL);
y_pre + blk_col, y_pre_stride, 16, block_height, ss_x, ss_y, strength,
use_whole_blk, y_accum + blk_col, y_count + blk_col, y_dist + blk_col,
u_dist + uv_blk_col, v_dist + uv_blk_col, neighbors_first,
neighbors_second, top_weight, bottom_weight, NULL);
}
// Right
neighbors_second = LUMA_RIGHT_COLUMN_NEIGHBORS;
vp9_apply_temporal_filter_luma_16(
y_src + blk_col, y_src_stride, y_pre + blk_col, y_pre_stride,
u_src + uv_blk_col, v_src + uv_blk_col, uv_src_stride, u_pre + uv_blk_col,
v_pre + uv_blk_col, uv_pre_stride, 16, block_height, ss_x, ss_y, strength,
y_pre + blk_col, y_pre_stride, 16, block_height, ss_x, ss_y, strength,
use_whole_blk, y_accum + blk_col, y_count + blk_col, y_dist + blk_col,
u_dist + uv_blk_col, v_dist + uv_blk_col, neighbors_first,
neighbors_second, top_weight, bottom_weight, NULL);
@@ -564,10 +533,7 @@ static void vp9_apply_temporal_filter_luma(
// blk_fw as an array of size 4 for the weights for each of the 4 subblocks,
// else use top_weight for top half, and bottom weight for bottom half.
static void vp9_apply_temporal_filter_chroma_8(
const uint8_t *y_src, int y_src_stride, const uint8_t *y_pre,
int y_pre_stride, const uint8_t *u_src, const uint8_t *v_src,
int uv_src_stride, const uint8_t *u_pre, const uint8_t *v_pre,
int uv_pre_stride, unsigned int uv_block_width,
const uint8_t *u_pre, const uint8_t *v_pre, int uv_pre_stride,
unsigned int uv_block_height, int ss_x, int ss_y, int strength,
uint32_t *u_accum, uint16_t *u_count, uint32_t *v_accum, uint16_t *v_count,
const uint16_t *y_dist, const uint16_t *u_dist, const uint16_t *v_dist,
@@ -587,9 +553,7 @@ static void vp9_apply_temporal_filter_chroma_8(
// Loop variable
unsigned int h;
(void)uv_block_width;
// Initilize weight
// Initialize weight
if (blk_fw) {
weight = _mm_setr_epi16(blk_fw[0], blk_fw[0], blk_fw[0], blk_fw[0],
blk_fw[1], blk_fw[1], blk_fw[1], blk_fw[1]);
@@ -621,10 +585,8 @@ static void vp9_apply_temporal_filter_chroma_8(
accumulate_and_store_8(u_sum_row, u_pre, u_count, u_accum);
accumulate_and_store_8(v_sum_row, v_pre, v_count, v_accum);
u_src += uv_src_stride;
u_pre += uv_pre_stride;
u_dist += DIST_STRIDE;
v_src += uv_src_stride;
v_pre += uv_pre_stride;
v_dist += DIST_STRIDE;
u_count += uv_pre_stride;
@@ -632,8 +594,6 @@ static void vp9_apply_temporal_filter_chroma_8(
v_count += uv_pre_stride;
v_accum += uv_pre_stride;
y_src += y_src_stride * (1 + ss_y);
y_pre += y_pre_stride * (1 + ss_y);
y_dist += DIST_STRIDE * (1 + ss_y);
// Then all the rows except the last one
@@ -676,10 +636,8 @@ static void vp9_apply_temporal_filter_chroma_8(
accumulate_and_store_8(u_sum_row, u_pre, u_count, u_accum);
accumulate_and_store_8(v_sum_row, v_pre, v_count, v_accum);
u_src += uv_src_stride;
u_pre += uv_pre_stride;
u_dist += DIST_STRIDE;
v_src += uv_src_stride;
v_pre += uv_pre_stride;
v_dist += DIST_STRIDE;
u_count += uv_pre_stride;
@@ -687,8 +645,6 @@ static void vp9_apply_temporal_filter_chroma_8(
v_count += uv_pre_stride;
v_accum += uv_pre_stride;
y_src += y_src_stride * (1 + ss_y);
y_pre += y_pre_stride * (1 + ss_y);
y_dist += DIST_STRIDE * (1 + ss_y);
}
@@ -719,12 +675,10 @@ static void vp9_apply_temporal_filter_chroma_8(
// Perform temporal filter for the chroma components.
static void vp9_apply_temporal_filter_chroma(
const uint8_t *y_src, int y_src_stride, const uint8_t *y_pre,
int y_pre_stride, const uint8_t *u_src, const uint8_t *v_src,
int uv_src_stride, const uint8_t *u_pre, const uint8_t *v_pre,
int uv_pre_stride, unsigned int block_width, unsigned int block_height,
int ss_x, int ss_y, int strength, const int *blk_fw, int use_whole_blk,
uint32_t *u_accum, uint16_t *u_count, uint32_t *v_accum, uint16_t *v_count,
const uint8_t *u_pre, const uint8_t *v_pre, int uv_pre_stride,
unsigned int block_width, unsigned int block_height, int ss_x, int ss_y,
int strength, const int *blk_fw, int use_whole_blk, uint32_t *u_accum,
uint16_t *u_count, uint32_t *v_accum, uint16_t *v_count,
const uint16_t *y_dist, const uint16_t *u_dist, const uint16_t *v_dist) {
const unsigned int uv_width = block_width >> ss_x,
uv_height = block_height >> ss_y;
@@ -751,22 +705,17 @@ static void vp9_apply_temporal_filter_chroma(
if (use_whole_blk) {
vp9_apply_temporal_filter_chroma_8(
y_src + blk_col, y_src_stride, y_pre + blk_col, y_pre_stride,
u_src + uv_blk_col, v_src + uv_blk_col, uv_src_stride,
u_pre + uv_blk_col, v_pre + uv_blk_col, uv_pre_stride, uv_width,
uv_height, ss_x, ss_y, strength, u_accum + uv_blk_col,
u_count + uv_blk_col, v_accum + uv_blk_col, v_count + uv_blk_col,
y_dist + blk_col, u_dist + uv_blk_col, v_dist + uv_blk_col, neighbors,
top_weight, bottom_weight, NULL);
u_pre + uv_blk_col, v_pre + uv_blk_col, uv_pre_stride, uv_height,
ss_x, ss_y, strength, u_accum + uv_blk_col, u_count + uv_blk_col,
v_accum + uv_blk_col, v_count + uv_blk_col, y_dist + blk_col,
u_dist + uv_blk_col, v_dist + uv_blk_col, neighbors, top_weight,
bottom_weight, NULL);
} else {
vp9_apply_temporal_filter_chroma_8(
y_src + blk_col, y_src_stride, y_pre + blk_col, y_pre_stride,
u_src + uv_blk_col, v_src + uv_blk_col, uv_src_stride,
u_pre + uv_blk_col, v_pre + uv_blk_col, uv_pre_stride, uv_width,
uv_height, ss_x, ss_y, strength, u_accum + uv_blk_col,
u_count + uv_blk_col, v_accum + uv_blk_col, v_count + uv_blk_col,
y_dist + blk_col, u_dist + uv_blk_col, v_dist + uv_blk_col, neighbors,
0, 0, blk_fw);
u_pre + uv_blk_col, v_pre + uv_blk_col, uv_pre_stride, uv_height,
ss_x, ss_y, strength, u_accum + uv_blk_col, u_count + uv_blk_col,
v_accum + uv_blk_col, v_count + uv_blk_col, y_dist + blk_col,
u_dist + uv_blk_col, v_dist + uv_blk_col, neighbors, 0, 0, blk_fw);
}
return;
@@ -782,10 +731,8 @@ static void vp9_apply_temporal_filter_chroma(
}
vp9_apply_temporal_filter_chroma_8(
y_src + blk_col, y_src_stride, y_pre + blk_col, y_pre_stride,
u_src + uv_blk_col, v_src + uv_blk_col, uv_src_stride, u_pre + uv_blk_col,
v_pre + uv_blk_col, uv_pre_stride, uv_width, uv_height, ss_x, ss_y,
strength, u_accum + uv_blk_col, u_count + uv_blk_col,
u_pre + uv_blk_col, v_pre + uv_blk_col, uv_pre_stride, uv_height, ss_x,
ss_y, strength, u_accum + uv_blk_col, u_count + uv_blk_col,
v_accum + uv_blk_col, v_count + uv_blk_col, y_dist + blk_col,
u_dist + uv_blk_col, v_dist + uv_blk_col, neighbors, top_weight,
bottom_weight, NULL);
@@ -805,13 +752,11 @@ static void vp9_apply_temporal_filter_chroma(
for (; uv_blk_col < uv_mid_width;
blk_col += blk_col_step, uv_blk_col += uv_blk_col_step) {
vp9_apply_temporal_filter_chroma_8(
y_src + blk_col, y_src_stride, y_pre + blk_col, y_pre_stride,
u_src + uv_blk_col, v_src + uv_blk_col, uv_src_stride,
u_pre + uv_blk_col, v_pre + uv_blk_col, uv_pre_stride, uv_width,
uv_height, ss_x, ss_y, strength, u_accum + uv_blk_col,
u_count + uv_blk_col, v_accum + uv_blk_col, v_count + uv_blk_col,
y_dist + blk_col, u_dist + uv_blk_col, v_dist + uv_blk_col, neighbors,
top_weight, bottom_weight, NULL);
u_pre + uv_blk_col, v_pre + uv_blk_col, uv_pre_stride, uv_height, ss_x,
ss_y, strength, u_accum + uv_blk_col, u_count + uv_blk_col,
v_accum + uv_blk_col, v_count + uv_blk_col, y_dist + blk_col,
u_dist + uv_blk_col, v_dist + uv_blk_col, neighbors, top_weight,
bottom_weight, NULL);
}
if (!use_whole_blk) {
@@ -823,13 +768,11 @@ static void vp9_apply_temporal_filter_chroma(
for (; uv_blk_col < uv_last_width;
blk_col += blk_col_step, uv_blk_col += uv_blk_col_step) {
vp9_apply_temporal_filter_chroma_8(
y_src + blk_col, y_src_stride, y_pre + blk_col, y_pre_stride,
u_src + uv_blk_col, v_src + uv_blk_col, uv_src_stride,
u_pre + uv_blk_col, v_pre + uv_blk_col, uv_pre_stride, uv_width,
uv_height, ss_x, ss_y, strength, u_accum + uv_blk_col,
u_count + uv_blk_col, v_accum + uv_blk_col, v_count + uv_blk_col,
y_dist + blk_col, u_dist + uv_blk_col, v_dist + uv_blk_col, neighbors,
top_weight, bottom_weight, NULL);
u_pre + uv_blk_col, v_pre + uv_blk_col, uv_pre_stride, uv_height, ss_x,
ss_y, strength, u_accum + uv_blk_col, u_count + uv_blk_col,
v_accum + uv_blk_col, v_count + uv_blk_col, y_dist + blk_col,
u_dist + uv_blk_col, v_dist + uv_blk_col, neighbors, top_weight,
bottom_weight, NULL);
}
// Right
@@ -842,10 +785,8 @@ static void vp9_apply_temporal_filter_chroma(
}
vp9_apply_temporal_filter_chroma_8(
y_src + blk_col, y_src_stride, y_pre + blk_col, y_pre_stride,
u_src + uv_blk_col, v_src + uv_blk_col, uv_src_stride, u_pre + uv_blk_col,
v_pre + uv_blk_col, uv_pre_stride, uv_width, uv_height, ss_x, ss_y,
strength, u_accum + uv_blk_col, u_count + uv_blk_col,
u_pre + uv_blk_col, v_pre + uv_blk_col, uv_pre_stride, uv_height, ss_x,
ss_y, strength, u_accum + uv_blk_col, u_count + uv_blk_col,
v_accum + uv_blk_col, v_count + uv_blk_col, y_dist + blk_col,
u_dist + uv_blk_col, v_dist + uv_blk_col, neighbors, top_weight,
bottom_weight, NULL);
@@ -886,12 +827,12 @@ void vp9_apply_temporal_filter_sse4_1(
assert(
(use_whole_blk || (blk_fw[1] >= 0 && blk_fw[2] >= 0 && blk_fw[3] >= 0)) &&
"subblock filter weight must be positive");
assert(blk_fw[0] <= 2 && "sublock filter weight must be less than 2");
assert(blk_fw[0] <= 2 && "subblock filter weight must be less than 2");
assert(
(use_whole_blk || (blk_fw[1] <= 2 && blk_fw[2] <= 2 && blk_fw[3] <= 2)) &&
"subblock filter weight must be less than 2");
// Precompute the difference sqaured
// Precompute the difference squared
for (row = 0; row < block_height; row++) {
for (blk_col = 0; blk_col < block_width; blk_col += 16) {
store_dist_16(y_src_ptr + blk_col, y_pre_ptr + blk_col,
@@ -922,14 +863,12 @@ void vp9_apply_temporal_filter_sse4_1(
u_dist_ptr = u_dist + 1;
v_dist_ptr = v_dist + 1;
vp9_apply_temporal_filter_luma(
y_src, y_src_stride, y_pre, y_pre_stride, u_src, v_src, uv_src_stride,
u_pre, v_pre, uv_pre_stride, block_width, block_height, ss_x, ss_y,
strength, blk_fw_ptr, use_whole_blk, y_accum, y_count, y_dist_ptr,
u_dist_ptr, v_dist_ptr);
vp9_apply_temporal_filter_luma(y_pre, y_pre_stride, block_width, block_height,
ss_x, ss_y, strength, blk_fw_ptr,
use_whole_blk, y_accum, y_count, y_dist_ptr,
u_dist_ptr, v_dist_ptr);
vp9_apply_temporal_filter_chroma(
y_src, y_src_stride, y_pre, y_pre_stride, u_src, v_src, uv_src_stride,
u_pre, v_pre, uv_pre_stride, block_width, block_height, ss_x, ss_y,
strength, blk_fw_ptr, use_whole_blk, u_accum, u_count, v_accum, v_count,
y_dist_ptr, u_dist_ptr, v_dist_ptr);
@@ -114,7 +114,7 @@ int vp9_diamond_search_sad_avx(const MACROBLOCK *x,
// Work out the start point for the search
const uint8_t *best_address = in_what;
const uint8_t *new_best_address = best_address;
#if ARCH_X86_64
#if VPX_ARCH_X86_64
__m128i v_ba_q = _mm_set1_epi64x((intptr_t)best_address);
#else
__m128i v_ba_d = _mm_set1_epi32((intptr_t)best_address);
@@ -138,7 +138,7 @@ int vp9_diamond_search_sad_avx(const MACROBLOCK *x,
for (i = 0, step = 0; step < tot_steps; step++) {
for (j = 0; j < cfg->searches_per_step; j += 4, i += 4) {
__m128i v_sad_d, v_cost_d, v_outside_d, v_inside_d, v_diff_mv_w;
#if ARCH_X86_64
#if VPX_ARCH_X86_64
__m128i v_blocka[2];
#else
__m128i v_blocka[1];
@@ -175,7 +175,7 @@ int vp9_diamond_search_sad_avx(const MACROBLOCK *x,
// Compute the SIMD pointer offsets.
{
#if ARCH_X86_64 // sizeof(intptr_t) == 8
#if VPX_ARCH_X86_64 // sizeof(intptr_t) == 8
// Load the offsets
__m128i v_bo10_q = _mm_loadu_si128((const __m128i *)&ss_os[i + 0]);
__m128i v_bo32_q = _mm_loadu_si128((const __m128i *)&ss_os[i + 2]);
@@ -186,7 +186,7 @@ int vp9_diamond_search_sad_avx(const MACROBLOCK *x,
// Compute the candidate addresses
v_blocka[0] = _mm_add_epi64(v_ba_q, v_bo10_q);
v_blocka[1] = _mm_add_epi64(v_ba_q, v_bo32_q);
#else // ARCH_X86 // sizeof(intptr_t) == 4
#else // VPX_ARCH_X86 // sizeof(intptr_t) == 4
__m128i v_bo_d = _mm_loadu_si128((const __m128i *)&ss_os[i]);
v_bo_d = _mm_and_si128(v_bo_d, v_inside_d);
v_blocka[0] = _mm_add_epi32(v_ba_d, v_bo_d);
@@ -282,7 +282,14 @@ int vp9_diamond_search_sad_avx(const MACROBLOCK *x,
// Update the global minimum if the local minimum is smaller
if (LIKELY(local_best_sad < best_sad)) {
#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
new_bmv = ((const int_mv *)&v_these_mv_w)[local_best_idx];
#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
new_best_address = ((const uint8_t **)v_blocka)[local_best_idx];
best_sad = local_best_sad;
@@ -294,7 +301,7 @@ int vp9_diamond_search_sad_avx(const MACROBLOCK *x,
best_address = new_best_address;
v_bmv_w = _mm_set1_epi32(bmv.as_int);
#if ARCH_X86_64
#if VPX_ARCH_X86_64
v_ba_q = _mm_set1_epi64x((intptr_t)best_address);
#else
v_ba_d = _mm_set1_epi32((intptr_t)best_address);
@@ -58,7 +58,7 @@ cglobal block_error, 3, 3, 8, uqc, dqc, size, ssz
movhlps m7, m6
paddq m4, m5
paddq m6, m7
%if ARCH_X86_64
%if VPX_ARCH_X86_64
movq rax, m4
movq [sszq], m6
%else
@@ -105,7 +105,7 @@ cglobal block_error_fp, 3, 3, 6, uqc, dqc, size
; accumulate horizontally and store in return value
movhlps m5, m4
paddq m4, m5
%if ARCH_X86_64
%if VPX_ARCH_X86_64
movq rax, m4
%else
pshufd m5, m4, 0x1
@@ -47,18 +47,15 @@ static INLINE __m256i scan_eob_256(const __m256i *iscan_ptr,
}
void vp9_quantize_fp_avx2(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
int skip_block, const int16_t *round_ptr,
const int16_t *quant_ptr, tran_low_t *qcoeff_ptr,
tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr,
uint16_t *eob_ptr, const int16_t *scan,
const int16_t *iscan) {
const int16_t *round_ptr, const int16_t *quant_ptr,
tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
const int16_t *dequant_ptr, uint16_t *eob_ptr,
const int16_t *scan, const int16_t *iscan) {
__m128i eob;
__m256i round256, quant256, dequant256;
__m256i eob256, thr256;
(void)scan;
(void)skip_block;
assert(!skip_block);
coeff_ptr += n_coeffs;
iscan += n_coeffs;
@@ -18,20 +18,17 @@
#include "vpx_dsp/x86/bitdepth_conversion_sse2.h"
void vp9_quantize_fp_sse2(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
int skip_block, const int16_t *round_ptr,
const int16_t *quant_ptr, tran_low_t *qcoeff_ptr,
tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr,
uint16_t *eob_ptr, const int16_t *scan,
const int16_t *iscan) {
const int16_t *round_ptr, const int16_t *quant_ptr,
tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
const int16_t *dequant_ptr, uint16_t *eob_ptr,
const int16_t *scan, const int16_t *iscan) {
__m128i zero;
__m128i thr;
int16_t nzflag;
int nzflag;
__m128i eob;
__m128i round, quant, dequant;
(void)scan;
(void)skip_block;
assert(!skip_block);
coeff_ptr += n_coeffs;
iscan += n_coeffs;
@@ -19,18 +19,18 @@ pw_1: times 8 dw 1
SECTION .text
%macro QUANTIZE_FP 2
cglobal quantize_%1, 0, %2, 15, coeff, ncoeff, skip, round, quant, \
cglobal quantize_%1, 0, %2, 15, coeff, ncoeff, round, quant, \
qcoeff, dqcoeff, dequant, \
eob, scan, iscan
; actual quantize loop - setup pointers, rounders, etc.
movifnidn coeffq, coeffmp
movifnidn ncoeffq, ncoeffmp
mov r2, dequantmp
movifnidn roundq, roundmp
movifnidn quantq, quantmp
mova m1, [roundq] ; m1 = round
mova m2, [quantq] ; m2 = quant
mov r2, dequantmp
%ifidn %1, fp_32x32
pcmpeqw m5, m5
psrlw m5, 15