mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-29 06:34:19 +00:00
[libvpx] Update to v1.12.0
This commit is contained in:
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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 ||
|
||||
|
||||
@@ -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;
|
||||
|
||||
+1157
-701
File diff suppressed because it is too large.
Load diff
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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
@@ -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, ¢er_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, ¢er_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, ¢er_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, ¢er_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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user