* be found in the AUTHORS file in the root of the source tree.
*/
+
+#include "vp9/common/vp9_blockd.h"
#include "vp9/common/vp9_common_data.h"
// Log 2 conversion lookup tables for block width and height
{0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3};
const int mi_height_log2_lookup[BLOCK_SIZE_TYPES] =
{0, 0, 0, 0, 1, 0, 1, 2, 1, 2, 3, 2, 3};
+
+const BLOCK_SIZE_TYPE subsize_lookup[PARTITION_TYPES][BLOCK_SIZE_TYPES] = {
+ { // PARTITION_NONE
+ BLOCK_SIZE_AB4X4, BLOCK_SIZE_SB4X8, BLOCK_SIZE_SB8X4,
+ BLOCK_SIZE_SB8X8, BLOCK_SIZE_SB8X16, BLOCK_SIZE_SB16X8,
+ BLOCK_SIZE_MB16X16, BLOCK_SIZE_SB16X32, BLOCK_SIZE_SB32X16,
+ BLOCK_SIZE_SB32X32, BLOCK_SIZE_SB32X64, BLOCK_SIZE_SB64X32,
+ BLOCK_SIZE_SB64X64,
+ }, { // PARTITION_HORZ
+ BLOCK_SIZE_TYPES, BLOCK_SIZE_TYPES, BLOCK_SIZE_TYPES,
+ BLOCK_SIZE_SB8X4, BLOCK_SIZE_TYPES, BLOCK_SIZE_TYPES,
+ BLOCK_SIZE_SB16X8, BLOCK_SIZE_TYPES, BLOCK_SIZE_TYPES,
+ BLOCK_SIZE_SB32X16, BLOCK_SIZE_TYPES, BLOCK_SIZE_TYPES,
+ BLOCK_SIZE_SB64X32,
+ }, { // PARTITION_VERT
+ BLOCK_SIZE_TYPES, BLOCK_SIZE_TYPES, BLOCK_SIZE_TYPES,
+ BLOCK_SIZE_SB4X8, BLOCK_SIZE_TYPES, BLOCK_SIZE_TYPES,
+ BLOCK_SIZE_SB8X16, BLOCK_SIZE_TYPES, BLOCK_SIZE_TYPES,
+ BLOCK_SIZE_SB16X32, BLOCK_SIZE_TYPES, BLOCK_SIZE_TYPES,
+ BLOCK_SIZE_SB32X64,
+ }, { // PARTITION_SPLIT
+ BLOCK_SIZE_TYPES, BLOCK_SIZE_TYPES, BLOCK_SIZE_TYPES,
+ BLOCK_SIZE_AB4X4, BLOCK_SIZE_TYPES, BLOCK_SIZE_TYPES,
+ BLOCK_SIZE_SB8X8, BLOCK_SIZE_TYPES, BLOCK_SIZE_TYPES,
+ BLOCK_SIZE_MB16X16, BLOCK_SIZE_TYPES, BLOCK_SIZE_TYPES,
+ BLOCK_SIZE_SB32X32,
+ }
+};
+
+const TX_SIZE max_txsize_lookup[BLOCK_SIZE_TYPES] = {
+ TX_4X4, TX_4X4, TX_4X4,
+ TX_8X8, TX_8X8, TX_8X8,
+ TX_16X16, TX_16X16, TX_16X16,
+ TX_32X32, TX_32X32, TX_32X32, TX_32X32
+};
+const TX_SIZE max_uv_txsize_lookup[BLOCK_SIZE_TYPES] = {
+ TX_4X4, TX_4X4, TX_4X4,
+ TX_4X4, TX_4X4, TX_4X4,
+ TX_8X8, TX_8X8, TX_8X8,
+ TX_16X16, TX_16X16, TX_16X16, TX_32X32
+};
+
+const BLOCK_SIZE_TYPE bsize_from_dim_lookup[5][5] = {
+ {BLOCK_SIZE_AB4X4, BLOCK_SIZE_SB4X8, BLOCK_SIZE_SB4X8,
+ BLOCK_SIZE_SB4X8, BLOCK_SIZE_SB4X8},
+ {BLOCK_SIZE_SB8X4, BLOCK_SIZE_SB8X8, BLOCK_SIZE_SB8X16,
+ BLOCK_SIZE_SB8X16, BLOCK_SIZE_SB8X16},
+ {BLOCK_SIZE_SB16X8, BLOCK_SIZE_SB16X8, BLOCK_SIZE_MB16X16,
+ BLOCK_SIZE_SB16X32, BLOCK_SIZE_SB16X32},
+ {BLOCK_SIZE_SB32X16, BLOCK_SIZE_SB32X16, BLOCK_SIZE_SB32X16,
+ BLOCK_SIZE_SB32X32, BLOCK_SIZE_SB32X64},
+ {BLOCK_SIZE_SB64X32, BLOCK_SIZE_SB64X32, BLOCK_SIZE_SB64X32,
+ BLOCK_SIZE_SB64X32, BLOCK_SIZE_SB64X64}
+};
}
}
-static enum BlockSize get_block_size(int bw, int bh) {
- if (bw == 4 && bh == 4)
- return BLOCK_4X4;
-
- if (bw == 4 && bh == 8)
- return BLOCK_4X8;
-
- if (bw == 8 && bh == 4)
- return BLOCK_8X4;
-
- if (bw == 8 && bh == 8)
- return BLOCK_8X8;
-
- if (bw == 8 && bh == 16)
- return BLOCK_8X16;
-
- if (bw == 16 && bh == 8)
- return BLOCK_16X8;
-
- if (bw == 16 && bh == 16)
- return BLOCK_16X16;
-
- if (bw == 32 && bh == 32)
- return BLOCK_32X32;
-
- if (bw == 32 && bh == 16)
- return BLOCK_32X16;
-
- if (bw == 16 && bh == 32)
- return BLOCK_16X32;
-
- if (bw == 64 && bh == 32)
- return BLOCK_64X32;
-
- if (bw == 32 && bh == 64)
- return BLOCK_32X64;
-
- if (bw == 64 && bh == 64)
- return BLOCK_64X64;
-
- assert(0);
- return -1;
+static INLINE BLOCK_SIZE_TYPE get_block_size(int bwl, int bhl) {
+ return bsize_from_dim_lookup[bwl][bhl];
}
-static enum BlockSize get_plane_block_size(BLOCK_SIZE_TYPE bsize,
- struct macroblockd_plane *pd) {
- return get_block_size(plane_block_width(bsize, pd),
- plane_block_height(bsize, pd));
+static BLOCK_SIZE_TYPE get_plane_block_size(BLOCK_SIZE_TYPE bsize,
+ struct macroblockd_plane *pd) {
+ return get_block_size(plane_block_width_log2by4(bsize, pd),
+ plane_block_height_log2by4(bsize, pd));
}
-static double linear_interpolate(double x, int ntab, int inv_step,
- const double *tab) {
+static inline void linear_interpolate2(double x, int ntab, int inv_step,
+ const double *tab1, const double *tab2,
+ double *v1, double *v2) {
double y = x * inv_step;
int d = (int) y;
if (d >= ntab - 1) {
- return tab[ntab - 1];
+ *v1 = tab1[ntab - 1];
+ *v2 = tab2[ntab - 1];
} else {
double a = y - d;
- return tab[d] * (1 - a) + tab[d + 1] * a;
+ *v1 = tab1[d] * (1 - a) + tab1[d + 1] * a;
+ *v2 = tab2[d] * (1 - a) + tab2[d + 1] * a;
}
}
-static double model_rate_norm(double x) {
+static void model_rd_norm(double x, double *R, double *D) {
+ static const int inv_tab_step = 8;
+ static const int tab_size = 120;
+ // NOTE: The tables below must be of the same size
+ //
// Normalized rate
- // This function models the rate for a Laplacian source
+ // This table models the rate for a Laplacian source
// source with given variance when quantized with a uniform quantizer
// with given stepsize. The closed form expression is:
// Rn(x) = H(sqrt(r)) + sqrt(r)*[1 + H(r)/(1 - r)],
// where r = exp(-sqrt(2) * x) and x = qpstep / sqrt(variance),
// and H(x) is the binary entropy function.
- static const int inv_rate_tab_step = 8;
static const double rate_tab[] = {
64.00, 4.944, 3.949, 3.372, 2.966, 2.655, 2.403, 2.194,
2.014, 1.858, 1.720, 1.596, 1.485, 1.384, 1.291, 1.206,
0.002, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001,
0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.000,
};
- const int rate_tab_num = sizeof(rate_tab)/sizeof(rate_tab[0]);
- assert(x >= 0.0);
- return linear_interpolate(x, rate_tab_num, inv_rate_tab_step, rate_tab);
-}
-
-static double model_dist_norm(double x) {
// Normalized distortion
- // This function models the normalized distortion for a Laplacian source
+ // This table models the normalized distortion for a Laplacian source
// source with given variance when quantized with a uniform quantizer
// with given stepsize. The closed form expression is:
// Dn(x) = 1 - 1/sqrt(2) * x / sinh(x/sqrt(2))
// where x = qpstep / sqrt(variance)
// Note the actual distortion is Dn * variance.
- static const int inv_dist_tab_step = 8;
static const double dist_tab[] = {
0.000, 0.001, 0.005, 0.012, 0.021, 0.032, 0.045, 0.061,
0.079, 0.098, 0.119, 0.142, 0.166, 0.190, 0.216, 0.242,
0.998, 0.998, 0.998, 0.999, 0.999, 0.999, 0.999, 0.999,
0.999, 0.999, 0.999, 0.999, 0.999, 0.999, 0.999, 1.000,
};
- const int dist_tab_num = sizeof(dist_tab)/sizeof(dist_tab[0]);
+ /*
+ assert(sizeof(rate_tab) == tab_size * sizeof(rate_tab[0]);
+ assert(sizeof(dist_tab) == tab_size * sizeof(dist_tab[0]);
+ assert(sizeof(rate_tab) == sizeof(dist_tab));
+ */
assert(x >= 0.0);
- return linear_interpolate(x, dist_tab_num, inv_dist_tab_step, dist_tab);
+ linear_interpolate2(x, tab_size, inv_tab_step,
+ rate_tab, dist_tab, R, D);
}
static void model_rd_from_var_lapndz(int var, int n, int qstep,
double D, R;
double s2 = (double) var / n;
double x = qstep / sqrt(s2);
- D = model_dist_norm(x);
- R = model_rate_norm(x);
- if (R < 0) {
- R = 0;
- D = var;
- }
- *rate = (n * R * 256 + 0.5);
- *dist = (n * D * s2 + 0.5);
+ model_rd_norm(x, &R, &D);
+ *rate = ((n << 8) * R + 0.5);
+ *dist = (var * D + 0.5);
}
vp9_clear_system_state();
}
struct macroblockd_plane *const pd = &xd->plane[i];
// TODO(dkovalev) the same code in get_plane_block_size
- const int bw = plane_block_width(bsize, pd);
- const int bh = plane_block_height(bsize, pd);
- const enum BlockSize bs = get_block_size(bw, bh);
+ const int bwl = plane_block_width_log2by4(bsize, pd);
+ const int bhl = plane_block_height_log2by4(bsize, pd);
+ const BLOCK_SIZE_TYPE bs = get_block_size(bwl, bhl);
unsigned int sse;
int rate;
int64_t dist;
(void) cpi->fn_ptr[bs].vf(p->src.buf, p->src.stride,
pd->dst.buf, pd->dst.stride, &sse);
// sse works better than var, since there is no dc prediction used
- model_rd_from_var_lapndz(sse, bw * bh, pd->dequant[1] >> 3, &rate, &dist);
+ model_rd_from_var_lapndz(sse, 16 << (bwl + bhl),
+ pd->dequant[1] >> 3, &rate, &dist);
rate_sum += rate;
dist_sum += dist;
struct macroblockd_plane *const pd = &xd->plane[0];
// TODO(dkovalev) the same code in get_plane_block_size
- const int bw = plane_block_width(bsize, pd);
- const int bh = plane_block_height(bsize, pd);
- const enum BlockSize bs = get_block_size(bw, bh);
+ const int bwl = plane_block_width_log2by4(bsize, pd);
+ const int bhl = plane_block_height_log2by4(bsize, pd);
+ const BLOCK_SIZE_TYPE bs = get_block_size(bwl, bhl);
unsigned int sse;
int rate;
int64_t dist;
(void) cpi->fn_ptr[bs].vf(p->src.buf, p->src.stride,
pd->dst.buf, pd->dst.stride, &sse);
// sse works better than var, since there is no dc prediction used
- model_rd_from_var_lapndz(sse, bw * bh, pd->dequant[1] >> 3, &rate, &dist);
+ model_rd_from_var_lapndz(sse, 16 << (bwl + bhl),
+ pd->dequant[1] >> 3, &rate, &dist);
*out_rate_sum = rate;
*out_dist_sum = dist << 4;
int *out_rate_sum, int64_t *out_dist_sum,
int *out_skip) {
int t = 4, j, k;
- enum BlockSize bs = BLOCK_4X4;
+ BLOCK_SIZE_TYPE bs = BLOCK_SIZE_AB4X4;
struct macroblock_plane *const p = &x->plane[0];
struct macroblockd_plane *const pd = &xd->plane[0];
- const int bw = plane_block_width(bsize, pd);
- const int bh = plane_block_height(bsize, pd);
+ const int bwl = plane_block_width_log2by4(bsize, pd);
+ const int bhl = plane_block_height_log2by4(bsize, pd);
+ const int bw = 4 << bwl;
+ const int bh = 4 << bhl;
int rate_sum = 0;
int64_t dist_sum = 0;
} else {
assert(0);
}
- assert(bs <= get_block_size(bw, bh));
+ assert(bs <= get_block_size(bwl, bhl));
*out_skip = 1;
for (j = 0; j < bh; j+=t) {
for (k = 0; k < bw; k+=t) {
static int block_error_sby(MACROBLOCK *x, BLOCK_SIZE_TYPE bsize,
int shift, int64_t *sse) {
struct macroblockd_plane *p = &x->e_mbd.plane[0];
- const int bw = plane_block_width(bsize, p);
- const int bh = plane_block_height(bsize, p);
+ const int bwl = plane_block_width_log2by4(bsize, p);
+ const int bhl = plane_block_height_log2by4(bsize, p);
int64_t e = vp9_block_error(x->plane[0].coeff, x->e_mbd.plane[0].dqcoeff,
- bw * bh, sse) >> shift;
+ 16 << (bwl + bhl), sse) >> shift;
*sse >>= shift;
return e;
}
*sse = 0;
for (plane = 1; plane < MAX_MB_PLANE; plane++) {
struct macroblockd_plane *p = &x->e_mbd.plane[plane];
- const int bw = plane_block_width(bsize, p);
- const int bh = plane_block_height(bsize, p);
+ const int bwl = plane_block_width_log2by4(bsize, p);
+ const int bhl = plane_block_height_log2by4(bsize, p);
sum += vp9_block_error(x->plane[plane].coeff, x->e_mbd.plane[plane].dqcoeff,
- bw * bh, &this_sse);
+ 16 << (bwl + bhl), &this_sse);
*sse += this_sse;
}
*sse >>= shift;
static void choose_largest_txfm_size(VP9_COMP *cpi, MACROBLOCK *x,
int *rate, int64_t *distortion,
int *skip, int64_t *sse,
+ int64_t ref_best_rd,
BLOCK_SIZE_TYPE bs) {
const TX_SIZE max_txfm_size = TX_32X32
- (bs < BLOCK_SIZE_SB32X32) - (bs < BLOCK_SIZE_MB16X16);
mbmi->txfm_size = TX_4X4;
}
super_block_yrd_for_txfm(cm, x, rate, distortion, skip,
- &sse[mbmi->txfm_size], INT64_MAX, bs,
+ &sse[mbmi->txfm_size], ref_best_rd, bs,
mbmi->txfm_size);
cpi->txfm_stepdown_count[0]++;
}
int (*r)[2], int *rate,
int64_t *d, int64_t *distortion,
int *s, int *skip, int64_t *sse,
+ int64_t ref_best_rd,
BLOCK_SIZE_TYPE bs,
int *model_used) {
const TX_SIZE max_txfm_size = TX_32X32
// Actually encode using the chosen mode if a model was used, but do not
// update the r, d costs
super_block_yrd_for_txfm(cm, x, rate, distortion, skip,
- &sse[mbmi->txfm_size], INT64_MAX,
+ &sse[mbmi->txfm_size], ref_best_rd,
bs, mbmi->txfm_size);
} else {
*distortion = d[mbmi->txfm_size];
(cpi->sf.tx_size_search_method != USE_FULL_RD &&
mbmi->ref_frame[0] == INTRA_FRAME)) {
vpx_memset(txfm_cache, 0, NB_TXFM_MODES * sizeof(int64_t));
- choose_largest_txfm_size(cpi, x, rate, distortion, skip, sse, bs);
+ choose_largest_txfm_size(cpi, x, rate, distortion, skip, sse,
+ ref_best_rd, bs);
if (psse)
*psse = sse[mbmi->txfm_size];
return;
&sse[TX_4X4], INT64_MAX, bs, TX_4X4);
}
choose_txfm_size_from_modelrd(cpi, x, r, rate, d, distortion, s,
- skip, sse, bs, model_used);
+ skip, sse, ref_best_rd, bs, model_used);
} else {
if (bs >= BLOCK_SIZE_SB32X32)
super_block_yrd_for_txfm(cm, x, &r[TX_32X32][0], &d[TX_32X32],
VP9_COMMON *const cm = &cpi->common;
MACROBLOCKD *xd = &x->e_mbd;
BLOCK_SIZE_TYPE bsize = xd->mode_info_context->mbmi.sb_type;
- const int bw = plane_block_width(bsize, &xd->plane[0]);
- const int bh = plane_block_height(bsize, &xd->plane[0]);
+ const int bwl = plane_block_width_log2by4(bsize, &xd->plane[0]);
+ const int bhl = plane_block_height_log2by4(bsize, &xd->plane[0]);
+ const int bw = 4 << bwl;
+ const int bh = 4 << bhl;
int idx, idy;
const int src_stride = x->plane[0].src.stride;
uint8_t* const src = raster_block_offset_uint8(xd, BLOCK_SIZE_SB8X8, 0, i,
&xd->subpix, MV_PRECISION_Q3);
}
- // Turning this section off for now since it hurts quality and does not
- // improve speed much
- /*
- if (cpi->sf.use_rd_breakout &&
- best_yrd < INT64_MAX) {
- int64_t thisrd;
- model_rd_for_sb_y(cpi, bsize, x, xd, &thisrate, &thisdistortion);
- thisrd = RDCOST(x->rdmult, x->rddiv, thisrate, thisdistortion);
- if (thisrd / 2 > best_yrd) {
- *distortion = thisdistortion;
- *labelyrate = thisrate;
- return thisrd;
- }
- }
- */
-
vp9_subtract_block(bh, bw, src_diff, 8,
src, src_stride,
dst, xd->plane[0].dst.stride);
vpx_memcpy(t_above, x->e_mbd.plane[0].above_context, sizeof(t_above));
vpx_memcpy(t_left, x->e_mbd.plane[0].left_context, sizeof(t_left));
- v_fn_ptr = &cpi->fn_ptr[get_block_size(4 << bwl, 4 << bhl)];
+ v_fn_ptr = &cpi->fn_ptr[get_block_size(bwl, bhl)];
// 64 makes this threshold really big effectively
// making it so that we very rarely check mvs on
static void mv_pred(VP9_COMP *cpi, MACROBLOCK *x,
uint8_t *ref_y_buffer, int ref_y_stride,
- int ref_frame, enum BlockSize block_size ) {
+ int ref_frame, BLOCK_SIZE_TYPE block_size ) {
MACROBLOCKD *xd = &x->e_mbd;
MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
int_mv this_mv;
static void setup_buffer_inter(VP9_COMP *cpi, MACROBLOCK *x,
int idx, MV_REFERENCE_FRAME frame_type,
- enum BlockSize block_size,
+ BLOCK_SIZE_TYPE block_size,
int mi_row, int mi_col,
int_mv frame_nearest_mv[MAX_REF_FRAMES],
int_mv frame_near_mv[MAX_REF_FRAMES],
int_mv mvp_full;
int ref = mbmi->ref_frame[0];
int_mv ref_mv = mbmi->ref_mvs[ref][0];
- const enum BlockSize block_size = get_plane_block_size(bsize, &xd->plane[0]);
+ const BLOCK_SIZE_TYPE block_size = get_plane_block_size(bsize, &xd->plane[0]);
int tmp_col_min = x->mv_col_min;
int tmp_col_max = x->mv_col_max;
int refs[2] = { mbmi->ref_frame[0],
(mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]) };
int_mv ref_mv[2];
- const enum BlockSize block_size = get_plane_block_size(bsize, &xd->plane[0]);
+ const BLOCK_SIZE_TYPE block_size = get_plane_block_size(bsize, &xd->plane[0]);
int ite;
// Prediction buffer from second frame.
uint8_t *second_pred = vpx_memalign(16, pw * ph * sizeof(uint8_t));
if (cpi->active_map_enabled && x->active_ptr[0] == 0)
x->skip = 1;
else if (x->encode_breakout) {
- const enum BlockSize y_size = get_plane_block_size(bsize, &xd->plane[0]);
- const enum BlockSize uv_size = get_plane_block_size(bsize, &xd->plane[1]);
+ const BLOCK_SIZE_TYPE y_size = get_plane_block_size(bsize, &xd->plane[0]);
+ const BLOCK_SIZE_TYPE uv_size = get_plane_block_size(bsize, &xd->plane[1]);
unsigned int var, sse;
int threshold = (xd->plane[0].dequant[1] * xd->plane[0].dequant[1] >> 4);
VP9_COMMON *cm = &cpi->common;
MACROBLOCKD *xd = &x->e_mbd;
MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
- const enum BlockSize block_size = get_plane_block_size(bsize, &xd->plane[0]);
+ const BLOCK_SIZE_TYPE block_size = get_plane_block_size(bsize, &xd->plane[0]);
MB_PREDICTION_MODE this_mode;
MV_REFERENCE_FRAME ref_frame;
unsigned char segment_id = xd->mode_info_context->mbmi.segment_id;