diff --git a/vp10/common/blockd.h b/vp10/common/blockd.h index c4dce6020551c31e5dacc141b5a1592af095a481..03e34e0068054937da2104e44c0007d6d14fbee8 100644 --- a/vp10/common/blockd.h +++ b/vp10/common/blockd.h @@ -89,7 +89,6 @@ typedef struct { // 1: an ext intra mode is used; 0: otherwise. uint8_t use_ext_intra_mode[PLANE_TYPES]; EXT_INTRA_MODE ext_intra_mode[PLANE_TYPES]; - uint8_t ext_intra_angle[PLANE_TYPES]; } EXT_INTRA_MODE_INFO; #endif // CONFIG_EXT_INTRA @@ -124,6 +123,7 @@ typedef struct { #if CONFIG_EXT_INTRA EXT_INTRA_MODE_INFO ext_intra_mode_info; + int8_t angle_delta[2]; #endif // CONFIG_EXT_INTRA // TODO(slavarnway): Delete and use bmi[3].as_mv[] instead. @@ -328,14 +328,14 @@ static const int ext_tx_used_inter[EXT_TX_SETS_INTER][TX_TYPES] = { #endif // CONFIG_EXT_TX #if CONFIG_EXT_INTRA -// 0: use both directional and filter modes; 1: use directional modes only. -#define DR_ONLY 0 -// 0: use slow exhaustive search; 1: use fast sub-optimal search. +#define ALLOW_FILTER_INTRA_MODES 1 +#define ANGLE_STEP 3 +#define MAX_ANGLE_DELTAS 3 #define ANGLE_FAST_SEARCH 1 -// A parameter to adjust early termination in the fast search of angles. -#define RD_ADJUSTER 1.4 -// Number of different angles that are supported -#define EXT_INTRA_ANGLES 128 + +static uint8_t mode_to_angle_map[INTRA_MODES] = { + 0, 90, 180, 45, 135, 111, 157, 203, 67, 0, +}; static const TX_TYPE filter_intra_mode_to_tx_type_lookup[FILTER_INTRA_MODES] = { DCT_DCT, // FILTER_DC @@ -349,13 +349,6 @@ static const TX_TYPE filter_intra_mode_to_tx_type_lookup[FILTER_INTRA_MODES] = { ADST_DCT, // FILTER_D63 ADST_ADST, // FILTER_TM }; - -// Maps the angle index to the actual prediction angle (in degrees). -// Angle index is in the range [0, EXT_INTRA_ANGLES); the actual prediction -// angle is in the range (0, 270). -static INLINE int prediction_angle_map(int angle_in) { - return (10 + 2 * angle_in); -} #endif // CONFIG_EXT_INTRA static INLINE TX_TYPE get_tx_type(PLANE_TYPE plane_type, @@ -363,33 +356,44 @@ static INLINE TX_TYPE get_tx_type(PLANE_TYPE plane_type, int block_idx, TX_SIZE tx_size) { const MODE_INFO *const mi = xd->mi[0]; const MB_MODE_INFO *const mbmi = &mi->mbmi; + #if CONFIG_EXT_INTRA - const int use_ext_intra_mode_info = - mbmi->ext_intra_mode_info.use_ext_intra_mode[plane_type]; - const EXT_INTRA_MODE ext_intra_mode = - mbmi->ext_intra_mode_info.ext_intra_mode[plane_type]; + if (!is_inter_block(mbmi)) { + const int use_ext_intra_mode_info = + mbmi->ext_intra_mode_info.use_ext_intra_mode[plane_type]; + const EXT_INTRA_MODE ext_intra_mode = + mbmi->ext_intra_mode_info.ext_intra_mode[plane_type]; + const PREDICTION_MODE mode = (plane_type == PLANE_TYPE_Y) ? + get_y_mode(mi, block_idx) : mbmi->uv_mode; + + if (xd->lossless[mbmi->segment_id] || tx_size >= TX_32X32) + return DCT_DCT; - if (!is_inter_block(mbmi) && use_ext_intra_mode_info) { - if (!xd->lossless[mbmi->segment_id] && tx_size < TX_32X32 #if CONFIG_EXT_TX - && !(mbmi->sb_type >= BLOCK_8X8 && plane_type == PLANE_TYPE_Y) + if (mbmi->sb_type >= BLOCK_8X8 && plane_type == PLANE_TYPE_Y) + return mbmi->tx_type; #endif // CONFIG_EXT_TX - ) { - if (ext_intra_mode > FILTER_TM_PRED) { - int angle = mbmi->ext_intra_mode_info.ext_intra_angle[plane_type]; - angle = prediction_angle_map(angle); - assert(angle > 0 && angle < 270); - if (angle == 135) - return ADST_ADST; - else if (angle < 45 || angle > 225) - return DCT_DCT; - else if (angle < 135) - return ADST_DCT; - else - return DCT_ADST; - } else { - return filter_intra_mode_to_tx_type_lookup[ext_intra_mode]; - } + + if (use_ext_intra_mode_info) + return filter_intra_mode_to_tx_type_lookup[ext_intra_mode]; + + if (mode == DC_PRED) { + return DCT_DCT; + } else if (mode == TM_PRED) { + return ADST_ADST; + } else { + int angle = mode_to_angle_map[mode]; + if (mbmi->sb_type >= BLOCK_8X8) + angle += mbmi->angle_delta[plane_type] * ANGLE_STEP; + assert(angle > 0 && angle < 270); + if (angle == 135) + return ADST_ADST; + else if (angle < 45 || angle > 225) + return DCT_DCT; + else if (angle < 135) + return ADST_DCT; + else + return DCT_ADST; } } #endif // CONFIG_EXT_INTRA diff --git a/vp10/common/entropymode.c b/vp10/common/entropymode.c index f2502b9dbba980b94142ad6842bfe4eb3dcee413..862d086968a0699946574e5cabd5d4730342c7d8 100644 --- a/vp10/common/entropymode.c +++ b/vp10/common/entropymode.c @@ -967,7 +967,7 @@ static const struct segmentation_probs default_seg_probs = { #endif #if CONFIG_EXT_INTRA -static const vpx_prob default_ext_intra_probs[2] = {200, 200}; +static const vpx_prob default_ext_intra_probs[2] = {230, 230}; #endif // CONFIG_EXT_INTRA static void init_mode_probs(FRAME_CONTEXT *fc) { diff --git a/vp10/common/entropymode.h b/vp10/common/entropymode.h index 00eacc533f567d6137482440d344fcb09bfd30a4..2b5c948992e1891c0b07139140a0d73a25954297 100644 --- a/vp10/common/entropymode.h +++ b/vp10/common/entropymode.h @@ -32,11 +32,6 @@ extern "C" { #define PALETTE_BLOCK_SIZES (BLOCK_64X64 - BLOCK_8X8 + 1) #define PALETTE_Y_MODE_CONTEXTS 3 -#if CONFIG_EXT_INTRA -// Probability that an ext_intra mode is a directional prediction mode -#define DR_EXT_INTRA_PROB 144 -#endif // CONFIG_EXT_INTRA - struct VP10Common; struct tx_probs { diff --git a/vp10/common/enums.h b/vp10/common/enums.h index 56e9c90a5de0a4a9d5135d0c20b8fcc054184ca2..3f9395eecb1150a07599c1a074940ab8e12c5e31 100644 --- a/vp10/common/enums.h +++ b/vp10/common/enums.h @@ -168,7 +168,6 @@ typedef enum { FILTER_D207_PRED, FILTER_D63_PRED, FILTER_TM_PRED, - EXT_DR_PRED, EXT_INTRA_MODES, } EXT_INTRA_MODE; diff --git a/vp10/common/reconintra.c b/vp10/common/reconintra.c index 28aa9152a03c359372dfec23563f79d814e30a86..555bba6beedc80d22c9e62f6f86ae58e94a480a7 100644 --- a/vp10/common/reconintra.c +++ b/vp10/common/reconintra.c @@ -405,32 +405,11 @@ static void dr_prediction_z3(uint8_t *dst, ptrdiff_t stride, int bs, } } -static INLINE void v_predictor(uint8_t *dst, ptrdiff_t stride, int bs, - const uint8_t *above, const uint8_t *left) { - int r; - (void) left; - - for (r = 0; r < bs; r++) { - memcpy(dst, above, bs); - dst += stride; - } -} - -static INLINE void h_predictor(uint8_t *dst, ptrdiff_t stride, int bs, - const uint8_t *above, const uint8_t *left) { - int r; - (void) above; - - for (r = 0; r < bs; r++) { - memset(dst, left[r], bs); - dst += stride; - } -} - -static void dr_predictor(uint8_t *dst, ptrdiff_t stride, int bs, +static void dr_predictor(uint8_t *dst, ptrdiff_t stride, TX_SIZE tx_size, const uint8_t *above, const uint8_t *left, int angle) { double t = 0; int dx, dy; + int bs = 4 << tx_size; if (angle != 90 && angle != 180) t = tan(angle * PI / 180.0); @@ -448,9 +427,9 @@ static void dr_predictor(uint8_t *dst, ptrdiff_t stride, int bs, dy = -((int)(256 * t)); dr_prediction_z3(dst, stride, bs, above, left, dx, dy); } else if (angle == 90) { - v_predictor(dst, stride, bs, above, left); + pred[V_PRED][tx_size](dst, stride, above, left); } else if (angle == 180) { - h_predictor(dst, stride, bs, above, left); + pred[H_PRED][tx_size](dst, stride, above, left); } } @@ -915,11 +894,7 @@ static void build_intra_predictors_high(const MACROBLOCKD *xd, int i; uint16_t *dst = CONVERT_TO_SHORTPTR(dst8); uint16_t *ref = CONVERT_TO_SHORTPTR(ref8); -#if CONFIG_MISC_FIXES - DECLARE_ALIGNED(16, uint16_t, left_col[32]); -#else DECLARE_ALIGNED(16, uint16_t, left_col[64]); -#endif DECLARE_ALIGNED(16, uint16_t, above_data[64 + 16]); uint16_t *above_row = above_data + 16; const uint16_t *const_above_row = above_row; @@ -946,37 +921,38 @@ static void build_intra_predictors_high(const MACROBLOCKD *xd, &xd->mi[0]->mbmi.ext_intra_mode_info; const EXT_INTRA_MODE ext_intra_mode = ext_intra_mode_info->ext_intra_mode[plane != 0]; - const int angle = - prediction_angle_map(ext_intra_mode_info->ext_intra_angle[plane != 0]); + int p_angle = 0; - if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) { - EXT_INTRA_MODE ext_intra_mode = - ext_intra_mode_info->ext_intra_mode[plane != 0]; - if (ext_intra_mode <= FILTER_TM_PRED) { - need_left = ext_intra_extend_modes[ext_intra_mode] & NEED_LEFT; - need_above = ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVE; - need_aboveright = - ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVERIGHT; - } else { - assert(angle > 0 && angle < 270); + if (mode != DC_PRED && mode != TM_PRED && + xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) { + p_angle = mode_to_angle_map[mode] + + xd->mi[0]->mbmi.angle_delta[plane != 0] * ANGLE_STEP; #if CONFIG_MISC_FIXES - if (angle <= 90) - need_above = 1, need_left = 0; - else if (angle < 180) - need_above = 1, need_left = 1; - else - need_above = 0, need_left = 1; + if (p_angle <= 90) + need_above = 1, need_left = 0; + else if (p_angle < 180) + need_above = 1, need_left = 1; + else + need_above = 0, need_left = 1; #else - if (angle < 90) - need_above = 0, need_aboveright = 1, need_left = 0; - else if (angle == 90) - need_above = 1, need_aboveright = 0, need_left = 0; - else if (angle < 180) - need_above = 1, need_aboveright = 0, need_left = 1; - else - need_above = 0, need_aboveright = 0, need_left = 1; + if (p_angle < 90) + need_above = 0, need_aboveright = 1, need_left = 0; + else if (p_angle == 90) + need_above = 1, need_aboveright = 0, need_left = 0; + else if (p_angle < 180) + need_above = 1, need_aboveright = 0, need_left = 1; + else + need_above = 0, need_aboveright = 0, need_left = 1; #endif // CONFIG_MISC_FIXES - } + } + + if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) { + EXT_INTRA_MODE ext_intra_mode = + ext_intra_mode_info->ext_intra_mode[plane != 0]; + need_left = ext_intra_extend_modes[ext_intra_mode] & NEED_LEFT; + need_above = ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVE; + need_aboveright = + ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVERIGHT; } #endif // CONFIG_EXT_INTRA @@ -993,10 +969,10 @@ static void build_intra_predictors_high(const MACROBLOCKD *xd, #if CONFIG_EXT_INTRA int need_bottom; if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) { - if (ext_intra_mode <= FILTER_TM_PRED) need_bottom = 0; - else - need_bottom = angle > 180; + } else if (mode != DC_PRED && mode != TM_PRED && + xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) { + need_bottom = p_angle > 180; } else { need_bottom = !!(extend_modes[mode] & NEED_BOTTOMLEFT); } @@ -1024,10 +1000,10 @@ static void build_intra_predictors_high(const MACROBLOCKD *xd, #if CONFIG_EXT_INTRA int need_right; if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) { - if (ext_intra_mode <= FILTER_TM_PRED) - need_right = 1; - else - need_right = angle < 90; + need_right = 1; + } else if (mode != DC_PRED && mode != TM_PRED && + xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) { + need_right = p_angle < 90; } else { need_right = !!(extend_modes[mode] & NEED_ABOVERIGHT); } @@ -1052,7 +1028,9 @@ static void build_intra_predictors_high(const MACROBLOCKD *xd, (void)need_aboveright; #if CONFIG_EXT_INTRA if (ext_intra_mode_info->use_ext_intra_mode[plane != 0] || - (extend_modes[mode] & NEED_ABOVELEFT)) { + (extend_modes[mode] & NEED_ABOVELEFT) || + (mode != DC_PRED && mode != TM_PRED && + xd->mi[0]->mbmi.sb_type >= BLOCK_8X8)) { above_row[-1] = n_top_px > 0 ? (n_left_px > 0 ? above_ref[-1] : base + 1) : base - 1; } @@ -1185,13 +1163,15 @@ static void build_intra_predictors_high(const MACROBLOCKD *xd, #if CONFIG_EXT_INTRA if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) { - if (ext_intra_mode <= FILTER_TM_PRED) - highbd_filter_intra_predictors[ext_intra_mode](dst, dst_stride, bs, - const_above_row, left_col, - bd); - else - highbd_dr_predictor(dst, dst_stride, bs, const_above_row, left_col, - angle, bd); + highbd_filter_intra_predictors[ext_intra_mode](dst, dst_stride, bs, + const_above_row, left_col, bd); + return; + } + + if (mode != DC_PRED && mode != TM_PRED && + xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) { + highbd_dr_predictor(dst, dst_stride, bs, const_above_row, left_col, + p_angle, bd); return; } #endif // CONFIG_EXT_INTRA @@ -1247,37 +1227,39 @@ static void build_intra_predictors(const MACROBLOCKD *xd, const uint8_t *ref, &xd->mi[0]->mbmi.ext_intra_mode_info; const EXT_INTRA_MODE ext_intra_mode = ext_intra_mode_info->ext_intra_mode[plane != 0]; - const int angle = - prediction_angle_map(ext_intra_mode_info->ext_intra_angle[plane != 0]); + int p_angle = 0; + + if (mode != DC_PRED && mode != TM_PRED && + xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) { + p_angle = mode_to_angle_map[mode] + + xd->mi[0]->mbmi.angle_delta[plane != 0] * ANGLE_STEP; - if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) { - EXT_INTRA_MODE ext_intra_mode = - ext_intra_mode_info->ext_intra_mode[plane != 0]; - if (ext_intra_mode <= FILTER_TM_PRED) { - need_left = ext_intra_extend_modes[ext_intra_mode] & NEED_LEFT; - need_above = ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVE; - need_aboveright = - ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVERIGHT; - } else { - assert(angle > 0 && angle < 270); #if CONFIG_MISC_FIXES - if (angle <= 90) - need_above = 1, need_left = 0; - else if (angle < 180) - need_above = 1, need_left = 1; - else - need_above = 0, need_left = 1; + if (p_angle <= 90) + need_above = 1, need_left = 0; + else if (p_angle < 180) + need_above = 1, need_left = 1; + else + need_above = 0, need_left = 1; #else - if (angle < 90) - need_above = 0, need_aboveright = 1, need_left = 0; - else if (angle == 90) - need_above = 1, need_aboveright = 0, need_left = 0; - else if (angle < 180) - need_above = 1, need_aboveright = 0, need_left = 1; - else - need_above = 0, need_aboveright = 0, need_left = 1; + if (p_angle < 90) + need_above = 0, need_aboveright = 1, need_left = 0; + else if (p_angle == 90) + need_above = 1, need_aboveright = 0, need_left = 0; + else if (p_angle < 180) + need_above = 1, need_aboveright = 0, need_left = 1; + else + need_above = 0, need_aboveright = 0, need_left = 1; #endif // CONFIG_MISC_FIXES - } + } + + if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) { + EXT_INTRA_MODE ext_intra_mode = + ext_intra_mode_info->ext_intra_mode[plane != 0]; + need_left = ext_intra_extend_modes[ext_intra_mode] & NEED_LEFT; + need_above = ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVE; + need_aboveright = + ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVERIGHT; } #endif // CONFIG_EXT_INTRA @@ -1318,10 +1300,10 @@ static void build_intra_predictors(const MACROBLOCKD *xd, const uint8_t *ref, #if CONFIG_EXT_INTRA int need_bottom; if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) { - if (ext_intra_mode <= FILTER_TM_PRED) - need_bottom = 0; - else - need_bottom = angle > 180; + need_bottom = 0; + } else if (mode != DC_PRED && mode != TM_PRED && + xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) { + need_bottom = p_angle > 180; } else { need_bottom = !!(extend_modes[mode] & NEED_BOTTOMLEFT); } @@ -1373,10 +1355,10 @@ static void build_intra_predictors(const MACROBLOCKD *xd, const uint8_t *ref, #if CONFIG_EXT_INTRA int need_right; if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) { - if (ext_intra_mode <= FILTER_TM_PRED) - need_right = 1; - else - need_right = angle < 90; + need_right = 1; + } else if (mode != DC_PRED && mode != TM_PRED && + xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) { + need_right = p_angle < 90; } else { need_right = !!(extend_modes[mode] & NEED_ABOVERIGHT); } @@ -1428,7 +1410,9 @@ static void build_intra_predictors(const MACROBLOCKD *xd, const uint8_t *ref, (void)need_aboveright; #if CONFIG_EXT_INTRA if (ext_intra_mode_info->use_ext_intra_mode[plane != 0] || - (extend_modes[mode] & NEED_ABOVELEFT)) { + (extend_modes[mode] & NEED_ABOVELEFT) || + (mode != DC_PRED && mode != TM_PRED && + xd->mi[0]->mbmi.sb_type >= BLOCK_8X8)) { above_row[-1] = n_top_px > 0 ? (n_left_px > 0 ? above_ref[-1] : 129) : 127; } #else @@ -1486,11 +1470,14 @@ static void build_intra_predictors(const MACROBLOCKD *xd, const uint8_t *ref, #if CONFIG_EXT_INTRA if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) { - if (ext_intra_mode <= FILTER_TM_PRED) - filter_intra_predictors[ext_intra_mode](dst, dst_stride, bs, - const_above_row, left_col); - else - dr_predictor(dst, dst_stride, bs, const_above_row, left_col, angle); + filter_intra_predictors[ext_intra_mode](dst, dst_stride, bs, + const_above_row, left_col); + return; + } + + if (mode != DC_PRED && mode != TM_PRED && + xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) { + dr_predictor(dst, dst_stride, tx_size, const_above_row, left_col, p_angle); return; } #endif // CONFIG_EXT_INTRA @@ -1510,10 +1497,10 @@ static void build_intra_predictors(const MACROBLOCKD *xd, const uint8_t *ref, } void vp10_predict_intra_block(const MACROBLOCKD *xd, int bwl_in, int bhl_in, - TX_SIZE tx_size, PREDICTION_MODE mode, - const uint8_t *ref, int ref_stride, - uint8_t *dst, int dst_stride, - int aoff, int loff, int plane) { + TX_SIZE tx_size, PREDICTION_MODE mode, + const uint8_t *ref, int ref_stride, + uint8_t *dst, int dst_stride, + int aoff, int loff, int plane) { const int txw = (1 << tx_size); const int have_top = loff || xd->up_available; const int have_left = aoff || xd->left_available; diff --git a/vp10/decoder/decodemv.c b/vp10/decoder/decodemv.c index cc0f3f09c66725f0c5c4696851d1d5d8894b18ec..a8868d41bb861035f4241358bb17a39ebef617aa 100644 --- a/vp10/decoder/decodemv.c +++ b/vp10/decoder/decodemv.c @@ -346,18 +346,16 @@ static void read_ext_intra_mode_info(VP10_COMMON *const cm, MODE_INFO *const mi = xd->mi[0]; MB_MODE_INFO *const mbmi = &mi->mbmi; FRAME_COUNTS *counts = xd->counts; + +#if !ALLOW_FILTER_INTRA_MODES + return; +#endif if (mbmi->mode == DC_PRED) { mbmi->ext_intra_mode_info.use_ext_intra_mode[0] = vpx_read(r, cm->fc->ext_intra_probs[0]); if (mbmi->ext_intra_mode_info.use_ext_intra_mode[0]) { - if (DR_ONLY ? 1 : vpx_read(r, DR_EXT_INTRA_PROB)) { - mbmi->ext_intra_mode_info.ext_intra_mode[0] = EXT_DR_PRED; - mbmi->ext_intra_mode_info.ext_intra_angle[0] = - read_uniform(r, EXT_INTRA_ANGLES); - } else { - mbmi->ext_intra_mode_info.ext_intra_mode[0] = - read_uniform(r, FILTER_INTRA_MODES); - } + mbmi->ext_intra_mode_info.ext_intra_mode[0] = + read_uniform(r, FILTER_INTRA_MODES); } if (counts) ++counts->ext_intra[0][mbmi->ext_intra_mode_info.use_ext_intra_mode[0]]; @@ -366,14 +364,8 @@ static void read_ext_intra_mode_info(VP10_COMMON *const cm, mbmi->ext_intra_mode_info.use_ext_intra_mode[1] = vpx_read(r, cm->fc->ext_intra_probs[1]); if (mbmi->ext_intra_mode_info.use_ext_intra_mode[1]) { - if (DR_ONLY ? 1 : vpx_read(r, DR_EXT_INTRA_PROB)) { - mbmi->ext_intra_mode_info.ext_intra_mode[1] = EXT_DR_PRED; - mbmi->ext_intra_mode_info.ext_intra_angle[1] = - read_uniform(r, EXT_INTRA_ANGLES); - } else { - mbmi->ext_intra_mode_info.ext_intra_mode[1] = - read_uniform(r, FILTER_INTRA_MODES); - } + mbmi->ext_intra_mode_info.ext_intra_mode[1] = + read_uniform(r, FILTER_INTRA_MODES); } if (counts) ++counts->ext_intra[1][mbmi->ext_intra_mode_info.use_ext_intra_mode[1]]; @@ -426,9 +418,20 @@ static void read_intra_frame_mode_info(VP10_COMMON *const cm, default: mbmi->mode = read_intra_mode(r, get_y_mode_probs(cm, mi, above_mi, left_mi, 0)); +#if CONFIG_EXT_INTRA + if (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED) + mbmi->angle_delta[0] = + read_uniform(r, 2 * MAX_ANGLE_DELTAS + 1) - MAX_ANGLE_DELTAS; +#endif // CONFIG_EXT_INTRA } mbmi->uv_mode = read_intra_mode_uv(cm, xd, r, mbmi->mode); +#if CONFIG_EXT_INTRA + if (mbmi->uv_mode != DC_PRED && mbmi->uv_mode != TM_PRED && + bsize >= BLOCK_8X8) + mbmi->angle_delta[1] = + read_uniform(r, 2 * MAX_ANGLE_DELTAS + 1) - MAX_ANGLE_DELTAS; +#endif mbmi->palette_mode_info.palette_size[0] = 0; mbmi->palette_mode_info.palette_size[1] = 0; @@ -591,8 +594,6 @@ static INLINE INTERP_FILTER read_switchable_interp_filter( cm->fc->switchable_interp_prob[ctx]); if (counts) ++counts->switchable_interp[ctx][type]; - // printf("%d/%d -> %d, %d\n", cm->current_video_frame, cm->show_frame, - // xd->mi[0]->mbmi.sb_type, xd->mi[0]->mbmi.interp_filter); return type; } @@ -626,9 +627,22 @@ static void read_intra_block_mode_info(VP10_COMMON *const cm, break; default: mbmi->mode = read_intra_mode_y(cm, xd, r, size_group_lookup[bsize]); +#if CONFIG_EXT_INTRA + mbmi->angle_delta[0] = 0; + if (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED) + mbmi->angle_delta[0] = + read_uniform(r, 2 * MAX_ANGLE_DELTAS + 1) - MAX_ANGLE_DELTAS; +#endif // CONFIG_EXT_INTRA } mbmi->uv_mode = read_intra_mode_uv(cm, xd, r, mbmi->mode); +#if CONFIG_EXT_INTRA + if (mbmi->uv_mode != DC_PRED && mbmi->uv_mode != TM_PRED && + bsize >= BLOCK_8X8) + mbmi->angle_delta[1] = + read_uniform(r, 2 * MAX_ANGLE_DELTAS + 1) - MAX_ANGLE_DELTAS; +#endif // CONFIG_EXT_INTRA + mbmi->palette_mode_info.palette_size[0] = 0; mbmi->palette_mode_info.palette_size[1] = 0; #if CONFIG_EXT_INTRA diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c index beb3414bf8c3748cc01281f422e726950df43439..a7b1f2400b530006e7981757d250bf0a150d3265 100644 --- a/vp10/encoder/bitstream.c +++ b/vp10/encoder/bitstream.c @@ -520,19 +520,15 @@ static void write_ref_frames(const VP10_COMMON *cm, const MACROBLOCKD *xd, static void write_ext_intra_mode_info(const VP10_COMMON *const cm, const MB_MODE_INFO *const mbmi, vpx_writer *w) { +#if !ALLOW_FILTER_INTRA_MODES + return; +#endif if (mbmi->mode == DC_PRED) { vpx_write(w, mbmi->ext_intra_mode_info.use_ext_intra_mode[0], cm->fc->ext_intra_probs[0]); if (mbmi->ext_intra_mode_info.use_ext_intra_mode[0]) { EXT_INTRA_MODE mode = mbmi->ext_intra_mode_info.ext_intra_mode[0]; - int dr_mode = mode > FILTER_TM_PRED; - if (!DR_ONLY) - vpx_write(w, dr_mode, DR_EXT_INTRA_PROB); - if (dr_mode) - write_uniform(w, EXT_INTRA_ANGLES, - mbmi->ext_intra_mode_info.ext_intra_angle[0]); - else - write_uniform(w, FILTER_INTRA_MODES, mode); + write_uniform(w, FILTER_INTRA_MODES, mode); } } if (mbmi->uv_mode == DC_PRED) { @@ -540,14 +536,7 @@ static void write_ext_intra_mode_info(const VP10_COMMON *const cm, cm->fc->ext_intra_probs[1]); if (mbmi->ext_intra_mode_info.use_ext_intra_mode[1]) { EXT_INTRA_MODE mode = mbmi->ext_intra_mode_info.ext_intra_mode[1]; - int dr_mode = mode > FILTER_TM_PRED; - if (!DR_ONLY) - vpx_write(w, dr_mode, DR_EXT_INTRA_PROB); - if (dr_mode) - write_uniform(w, EXT_INTRA_ANGLES, - mbmi->ext_intra_mode_info.ext_intra_angle[1]); - else - write_uniform(w, FILTER_INTRA_MODES, mode); + write_uniform(w, FILTER_INTRA_MODES, mode); } } } @@ -644,6 +633,12 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi, if (!is_inter) { if (bsize >= BLOCK_8X8) { write_intra_mode(w, mode, cm->fc->y_mode_prob[size_group_lookup[bsize]]); +#if CONFIG_EXT_INTRA + if (mode != DC_PRED && mode != TM_PRED) { + write_uniform(w, 2 * MAX_ANGLE_DELTAS + 1, + MAX_ANGLE_DELTAS + mbmi->angle_delta[0]); + } +#endif // CONFIG_EXT_INTRA } else { int idx, idy; const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize]; @@ -657,6 +652,11 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi, } write_intra_mode(w, mbmi->uv_mode, cm->fc->uv_mode_prob[mode]); #if CONFIG_EXT_INTRA + if (mbmi->uv_mode != DC_PRED && mbmi->uv_mode != TM_PRED && + bsize >= BLOCK_8X8) + write_uniform(w, 2 * MAX_ANGLE_DELTAS + 1, + MAX_ANGLE_DELTAS + mbmi->angle_delta[1]); + if (bsize >= BLOCK_8X8) write_ext_intra_mode_info(cm, mbmi, w); #endif // CONFIG_EXT_INTRA @@ -782,6 +782,11 @@ static void write_mb_modes_kf(const VP10_COMMON *cm, const MACROBLOCKD *xd, if (bsize >= BLOCK_8X8) { write_intra_mode(w, mbmi->mode, get_y_mode_probs(cm, mi, above_mi, left_mi, 0)); +#if CONFIG_EXT_INTRA + if (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED) + write_uniform(w, 2 * MAX_ANGLE_DELTAS + 1, + MAX_ANGLE_DELTAS + mbmi->angle_delta[0]); +#endif // CONFIG_EXT_INTRA } else { const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize]; const int num_4x4_h = num_4x4_blocks_high_lookup[bsize]; @@ -797,6 +802,12 @@ static void write_mb_modes_kf(const VP10_COMMON *cm, const MACROBLOCKD *xd, } write_intra_mode(w, mbmi->uv_mode, cm->fc->uv_mode_prob[mbmi->mode]); +#if CONFIG_EXT_INTRA + if (mbmi->uv_mode != DC_PRED && mbmi->uv_mode != TM_PRED && + bsize >= BLOCK_8X8) + write_uniform(w, 2 * MAX_ANGLE_DELTAS + 1, + MAX_ANGLE_DELTAS + mbmi->angle_delta[1]); +#endif // CONFIG_EXT_INTRA if (bsize >= BLOCK_8X8 && cm->allow_screen_content_tools && mbmi->mode == DC_PRED) diff --git a/vp10/encoder/rdopt.c b/vp10/encoder/rdopt.c index adcd5473a369efa316126d79bee01e8ab7e6aa51..3709d89cfb720a560b2655be4f492723a2f96a2c 100644 --- a/vp10/encoder/rdopt.c +++ b/vp10/encoder/rdopt.c @@ -1507,10 +1507,7 @@ static int rd_pick_ext_intra_sby(VP10_COMP *cpi, MACROBLOCK *x, MB_MODE_INFO *mbmi = &mic->mbmi; int this_rate, this_rate_tokenonly, s; int ext_intra_selected_flag = 0; - int i, step, delta, angle, best_angle, best_angle_dir; - int deltas[3] = {25, 5, 1}; - int branches[3] = {2, 2, 2}; - int64_t this_distortion, this_rd, best_angle_rd = INT64_MAX; + int64_t this_distortion, this_rd; EXT_INTRA_MODE mode; TX_SIZE best_tx_size = TX_4X4; EXT_INTRA_MODE_INFO ext_intra_mode_info; @@ -1522,142 +1519,173 @@ static int rd_pick_ext_intra_sby(VP10_COMP *cpi, MACROBLOCK *x, mbmi->ext_intra_mode_info.use_ext_intra_mode[0] = 1; mbmi->mode = DC_PRED; - if (!DR_ONLY) { - for (mode = 0; mode < FILTER_INTRA_MODES; ++mode) { - mbmi->ext_intra_mode_info.ext_intra_mode[0] = mode; - super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion, - &s, NULL, bsize, *best_rd); - if (this_rate_tokenonly == INT_MAX) - continue; + for (mode = 0; mode < FILTER_INTRA_MODES; ++mode) { + mbmi->ext_intra_mode_info.ext_intra_mode[0] = mode; + super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion, + &s, NULL, bsize, *best_rd); + if (this_rate_tokenonly == INT_MAX) + continue; - this_rate = this_rate_tokenonly + - vp10_cost_bit(cpi->common.fc->ext_intra_probs[0], 1) + - vp10_cost_bit(DR_EXT_INTRA_PROB, 0) + - write_uniform_cost(FILTER_INTRA_MODES, mode) + mode_cost; - this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion); + this_rate = this_rate_tokenonly + + vp10_cost_bit(cpi->common.fc->ext_intra_probs[0], 1) + + write_uniform_cost(FILTER_INTRA_MODES, mode) + mode_cost; + this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion); - if (this_rd < *best_rd) { - *best_rd = this_rd; - best_tx_size = mic->mbmi.tx_size; - ext_intra_mode_info = mbmi->ext_intra_mode_info; + if (this_rd < *best_rd) { + *best_rd = this_rd; + best_tx_size = mic->mbmi.tx_size; + ext_intra_mode_info = mbmi->ext_intra_mode_info; +#if CONFIG_EXT_TX + best_tx_type = mic->mbmi.tx_type; +#endif // CONFIG_EXT_TX + *rate = this_rate; + *rate_tokenonly = this_rate_tokenonly; + *distortion = this_distortion; + *skippable = s; + ext_intra_selected_flag = 1; + } + } + + if (ext_intra_selected_flag) { + mbmi->mode = DC_PRED; + mbmi->tx_size = best_tx_size; + mbmi->ext_intra_mode_info.use_ext_intra_mode[0] = + ext_intra_mode_info.use_ext_intra_mode[0]; + mbmi->ext_intra_mode_info.ext_intra_mode[0] = + ext_intra_mode_info.ext_intra_mode[0]; +#if CONFIG_EXT_TX + mbmi->tx_type = best_tx_type; +#endif // CONFIG_EXT_TX + return 1; + } else { + return 0; + } +} + +static int64_t rd_pick_intra_angle_sby(VP10_COMP *cpi, MACROBLOCK *x, + int *rate, int *rate_tokenonly, + int64_t *distortion, int *skippable, + BLOCK_SIZE bsize, int rate_overhead, + int64_t best_rd) { + MACROBLOCKD *const xd = &x->e_mbd; + MODE_INFO *const mic = xd->mi[0]; + MB_MODE_INFO *mbmi = &mic->mbmi; + int this_rate, this_rate_tokenonly, s; + int angle_delta, best_angle_delta = 0; + const double rd_adjust = 1.2; + int64_t this_distortion, this_rd, sse_dummy; + TX_SIZE best_tx_size = mic->mbmi.tx_size; #if CONFIG_EXT_TX - best_tx_type = mic->mbmi.tx_type; + TX_TYPE best_tx_type = mbmi->tx_type; +#endif // CONFIG_EXT_TX + + if (ANGLE_FAST_SEARCH) { + int deltas_level1[3] = {0, -2, 2}; + int deltas_level2[3][2] = { + {-1, 1}, {-3, -1}, {1, 3}, + }; + const int level1 = 3, level2 = 2; + int i, j, best_i = -1; + + for (i = 0; i < level1; ++i) { + mic->mbmi.angle_delta[0] = deltas_level1[i]; + super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion, + &s, NULL, bsize, + (i == 0 && best_rd < INT64_MAX) ? best_rd * rd_adjust : + best_rd); + if (this_rate_tokenonly == INT_MAX) { + if (i == 0) + break; + else + continue; + } + this_rate = this_rate_tokenonly + rate_overhead; + this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion); + if (i == 0 && best_rd < INT64_MAX && this_rd > best_rd * rd_adjust) + break; + if (this_rd < best_rd) { + best_i = i; + best_rd = this_rd; + best_angle_delta = mbmi->angle_delta[0]; + best_tx_size = mbmi->tx_size; +#if CONFIG_EXT_TX + best_tx_type = mbmi->tx_type; #endif // CONFIG_EXT_TX *rate = this_rate; *rate_tokenonly = this_rate_tokenonly; *distortion = this_distortion; *skippable = s; - ext_intra_selected_flag = 1; } } - } - mbmi->ext_intra_mode_info.ext_intra_mode[0] = EXT_DR_PRED; - if (ANGLE_FAST_SEARCH) { - best_angle = EXT_INTRA_ANGLES / 2; - for (step = 0; step < 3; ++step) { - delta = deltas[step]; - for (i = -branches[step]; i <= branches[step]; ++i) { - int64_t rd_thresh; - if (i == 0 && step != 0) - continue; - angle = best_angle + i * delta; - if (angle < 0) - angle = 0; - if (angle >= EXT_INTRA_ANGLES) - angle = EXT_INTRA_ANGLES - 1; - if (angle == best_angle && step != 0) - continue; - mbmi->ext_intra_mode_info.ext_intra_angle[0] = angle; - if (*best_rd == INT64_MAX) - rd_thresh = best_angle_rd; - else - rd_thresh = VPXMIN(best_angle_rd, *best_rd * RD_ADJUSTER); + if (best_i >= 0) { + for (j = 0; j < level2; ++j) { + mic->mbmi.angle_delta[0] = deltas_level2[best_i][j]; super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion, - &s, NULL, bsize, rd_thresh); + &s, NULL, bsize, best_rd); if (this_rate_tokenonly == INT_MAX) continue; - this_rate = this_rate_tokenonly + - vp10_cost_bit(cpi->common.fc->ext_intra_probs[0], 1) + - (DR_ONLY ? 0: vp10_cost_bit(DR_EXT_INTRA_PROB, 1)) + - write_uniform_cost(EXT_INTRA_ANGLES, angle) + mode_cost; + this_rate = this_rate_tokenonly + rate_overhead; this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion); - if (this_rd < *best_rd) { - *best_rd = this_rd; - best_tx_size = mic->mbmi.tx_size; - ext_intra_mode_info = mbmi->ext_intra_mode_info; + if (this_rd < best_rd) { + best_rd = this_rd; + best_angle_delta = mbmi->angle_delta[0]; + best_tx_size = mbmi->tx_size; #if CONFIG_EXT_TX - best_tx_type = mic->mbmi.tx_type; + best_tx_type = mbmi->tx_type; #endif // CONFIG_EXT_TX *rate = this_rate; *rate_tokenonly = this_rate_tokenonly; *distortion = this_distortion; *skippable = s; - ext_intra_selected_flag = 1; - } - if (this_rd < best_angle_rd) { - best_angle_rd = this_rd; - best_angle_dir = i; } } - - best_angle += best_angle_dir * delta; - if (best_angle < 0) - best_angle = 0; - if (best_angle >= EXT_INTRA_ANGLES) - best_angle = EXT_INTRA_ANGLES - 1; - if (*best_rd < best_angle_rd / RD_ADJUSTER) - break; } } else { - for (angle = 0; angle < EXT_INTRA_ANGLES; ++angle) { - mbmi->ext_intra_mode_info.ext_intra_angle[0] = angle; - if (prediction_angle_map(angle) == 90 || - prediction_angle_map(angle) == 180) - continue; + for (angle_delta = -MAX_ANGLE_DELTAS; angle_delta <= MAX_ANGLE_DELTAS; + ++angle_delta) { + mic->mbmi.angle_delta[0] = angle_delta; + super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion, - &s, NULL, bsize, *best_rd); + &s, NULL, bsize, best_rd); if (this_rate_tokenonly == INT_MAX) continue; - this_rate = this_rate_tokenonly + - vp10_cost_bit(cpi->common.fc->ext_intra_probs[0], 1) + - (DR_ONLY ? 0: vp10_cost_bit(DR_EXT_INTRA_PROB, 1)) + - write_uniform_cost(EXT_INTRA_ANGLES, angle) + mode_cost; + this_rate = this_rate_tokenonly + rate_overhead; this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion); - if (this_rd < *best_rd) { - *best_rd = this_rd; - best_tx_size = mic->mbmi.tx_size; - ext_intra_mode_info = mbmi->ext_intra_mode_info; + if (this_rd < best_rd) { + best_rd = this_rd; + best_angle_delta = mbmi->angle_delta[0]; + best_tx_size = mbmi->tx_size; #if CONFIG_EXT_TX - best_tx_type = mic->mbmi.tx_type; + best_tx_type = mbmi->tx_type; #endif // CONFIG_EXT_TX *rate = this_rate; *rate_tokenonly = this_rate_tokenonly; *distortion = this_distortion; *skippable = s; - ext_intra_selected_flag = 1; } } } - if (ext_intra_selected_flag) { - mbmi->mode = DC_PRED; - mbmi->tx_size = best_tx_size; - mbmi->ext_intra_mode_info.use_ext_intra_mode[0] = - ext_intra_mode_info.use_ext_intra_mode[0]; - mbmi->ext_intra_mode_info.ext_intra_mode[0] = - ext_intra_mode_info.ext_intra_mode[0]; - mbmi->ext_intra_mode_info.ext_intra_angle[0] = - ext_intra_mode_info.ext_intra_angle[0]; + mbmi->tx_size = best_tx_size; + mbmi->angle_delta[0] = best_angle_delta; #if CONFIG_EXT_TX - mbmi->tx_type = best_tx_type; + mbmi->tx_type = best_tx_type; #endif // CONFIG_EXT_TX - return 1; - } else { - return 0; + + if (*rate_tokenonly < INT_MAX) { + txfm_rd_in_plane(x, +#if CONFIG_VAR_TX + cpi, +#endif + &this_rate_tokenonly, &this_distortion, &s, + &sse_dummy, INT64_MAX, 0, bsize, mbmi->tx_size, + cpi->sf.use_fast_coef_costing); } + + return best_rd; } #endif // CONFIG_EXT_INTRA @@ -1676,6 +1704,7 @@ static int64_t rd_pick_intra_sby_mode(VP10_COMP *cpi, MACROBLOCK *x, TX_SIZE best_tx = TX_4X4; #if CONFIG_EXT_INTRA EXT_INTRA_MODE_INFO ext_intra_mode_info; + int is_directional_mode, rate_overhead, best_angle_delta = 0; #endif // CONFIG_EXT_INTRA #if CONFIG_EXT_TX TX_TYPE best_tx_type = DCT_DCT; @@ -1696,6 +1725,7 @@ static int64_t rd_pick_intra_sby_mode(VP10_COMP *cpi, MACROBLOCK *x, #if CONFIG_EXT_INTRA ext_intra_mode_info.use_ext_intra_mode[0] = 0; mic->mbmi.ext_intra_mode_info.use_ext_intra_mode[0] = 0; + mic->mbmi.angle_delta[0] = 0; #endif // CONFIG_EXT_INTRA memset(x->skip_txfm, SKIP_TXFM_NONE, sizeof(x->skip_txfm)); palette_mode_info.palette_size[0] = 0; @@ -1708,9 +1738,24 @@ static int64_t rd_pick_intra_sby_mode(VP10_COMP *cpi, MACROBLOCK *x, /* Y Search for intra prediction mode */ for (mode = DC_PRED; mode <= TM_PRED; ++mode) { mic->mbmi.mode = mode; - +#if CONFIG_EXT_INTRA + is_directional_mode = (mode != DC_PRED && mode != TM_PRED); + if (is_directional_mode) { + rate_overhead = bmode_costs[mode] + + write_uniform_cost(2 * MAX_ANGLE_DELTAS + 1, 0); + this_rate_tokenonly = INT_MAX; + this_rd = + rd_pick_intra_angle_sby(cpi, x, &this_rate, &this_rate_tokenonly, + &this_distortion, &s, bsize, rate_overhead, + best_rd); + } else { + mic->mbmi.angle_delta[0] = 0; + super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion, + &s, NULL, bsize, best_rd); + } +#endif // CONFIG_EXT_INTRA super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion, - &s, NULL, bsize, best_rd); + &s, NULL, bsize, best_rd); if (this_rate_tokenonly == INT_MAX) continue; @@ -1721,8 +1766,12 @@ static int64_t rd_pick_intra_sby_mode(VP10_COMP *cpi, MACROBLOCK *x, vp10_cost_bit(vp10_default_palette_y_mode_prob[bsize - BLOCK_8X8] [palette_ctx], 0); #if CONFIG_EXT_INTRA - if (mode == DC_PRED) + if (mode == DC_PRED && ALLOW_FILTER_INTRA_MODES) this_rate += vp10_cost_bit(cpi->common.fc->ext_intra_probs[0], 0); + if (is_directional_mode) + this_rate += write_uniform_cost(2 * MAX_ANGLE_DELTAS + 1, + MAX_ANGLE_DELTAS + + mic->mbmi.angle_delta[0]); #endif // CONFIG_EXT_INTRA this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion); @@ -1730,6 +1779,9 @@ static int64_t rd_pick_intra_sby_mode(VP10_COMP *cpi, MACROBLOCK *x, mode_selected = mode; best_rd = this_rd; best_tx = mic->mbmi.tx_size; +#if CONFIG_EXT_INTRA + best_angle_delta = mic->mbmi.angle_delta[0]; +#endif // CONFIG_EXT_INTRA #if CONFIG_EXT_TX best_tx_type = mic->mbmi.tx_type; #endif // CONFIG_EXT_TX @@ -1746,7 +1798,7 @@ static int64_t rd_pick_intra_sby_mode(VP10_COMP *cpi, MACROBLOCK *x, &best_tx, &mode_selected, &best_rd); #if CONFIG_EXT_INTRA - if (!palette_mode_info.palette_size[0] > 0) { + if (!palette_mode_info.palette_size[0] > 0 && ALLOW_FILTER_INTRA_MODES) { if (rd_pick_ext_intra_sby(cpi, x, rate, rate_tokenonly, distortion, skippable, bsize, bmode_costs[DC_PRED], &best_rd)) { @@ -1764,13 +1816,14 @@ static int64_t rd_pick_intra_sby_mode(VP10_COMP *cpi, MACROBLOCK *x, if (ext_intra_mode_info.use_ext_intra_mode[0]) { mic->mbmi.ext_intra_mode_info.ext_intra_mode[0] = ext_intra_mode_info.ext_intra_mode[0]; - mic->mbmi.ext_intra_mode_info.ext_intra_angle[0] = - ext_intra_mode_info.ext_intra_angle[0]; } #endif // CONFIG_EXT_INTRA mic->mbmi.mode = mode_selected; mic->mbmi.tx_size = best_tx; +#if CONFIG_EXT_INTRA + mic->mbmi.angle_delta[0] = best_angle_delta; +#endif // CONFIG_EXT_INTRA #if CONFIG_EXT_TX mic->mbmi.tx_type = best_tx_type; #endif // CONFIG_EXT_TX @@ -2468,141 +2521,143 @@ static int rd_pick_ext_intra_sbuv(VP10_COMP *cpi, MACROBLOCK *x, MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi; int ext_intra_selected_flag = 0; int this_rate_tokenonly, this_rate, s; - int64_t this_distortion, this_sse, this_rd, best_angle_rd = INT64_MAX; + int64_t this_distortion, this_sse, this_rd; EXT_INTRA_MODE mode; - int i, step, delta, angle, best_angle, best_angle_dir; - int deltas[3] = {25, 5, 1}; - int branches[3] = {2, 2, 2}; EXT_INTRA_MODE_INFO ext_intra_mode_info; vp10_zero(ext_intra_mode_info); mbmi->ext_intra_mode_info.use_ext_intra_mode[1] = 1; mbmi->uv_mode = DC_PRED; - if (!DR_ONLY) { - for (mode = 0; mode < FILTER_INTRA_MODES; ++mode) { - mbmi->ext_intra_mode_info.ext_intra_mode[1] = mode; - if (!super_block_uvrd(cpi, x, &this_rate_tokenonly, - &this_distortion, &s, &this_sse, bsize, *best_rd)) - continue; + for (mode = 0; mode < FILTER_INTRA_MODES; ++mode) { + mbmi->ext_intra_mode_info.ext_intra_mode[1] = mode; + if (!super_block_uvrd(cpi, x, &this_rate_tokenonly, + &this_distortion, &s, &this_sse, bsize, *best_rd)) + continue; - this_rate = this_rate_tokenonly + - vp10_cost_bit(cpi->common.fc->ext_intra_probs[1], 1) + - vp10_cost_bit(DR_EXT_INTRA_PROB, 0) + - cpi->intra_uv_mode_cost[mbmi->mode][mbmi->uv_mode] + - write_uniform_cost(FILTER_INTRA_MODES, mode); - this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion); - if (this_rd < *best_rd) { - *best_rd = this_rd; - *rate = this_rate; - *rate_tokenonly = this_rate_tokenonly; - *distortion = this_distortion; - *skippable = s; - ext_intra_mode_info = mbmi->ext_intra_mode_info; - ext_intra_selected_flag = 1; - if (!x->select_tx_size) - swap_block_ptr(x, ctx, 2, 0, 1, MAX_MB_PLANE); - } + this_rate = this_rate_tokenonly + + vp10_cost_bit(cpi->common.fc->ext_intra_probs[1], 1) + + cpi->intra_uv_mode_cost[mbmi->mode][mbmi->uv_mode] + + write_uniform_cost(FILTER_INTRA_MODES, mode); + this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion); + if (this_rd < *best_rd) { + *best_rd = this_rd; + *rate = this_rate; + *rate_tokenonly = this_rate_tokenonly; + *distortion = this_distortion; + *skippable = s; + ext_intra_mode_info = mbmi->ext_intra_mode_info; + ext_intra_selected_flag = 1; + if (!x->select_tx_size) + swap_block_ptr(x, ctx, 2, 0, 1, MAX_MB_PLANE); } } - mbmi->ext_intra_mode_info.ext_intra_mode[1] = EXT_DR_PRED; + + if (ext_intra_selected_flag) { + mbmi->uv_mode = DC_PRED; + mbmi->ext_intra_mode_info.use_ext_intra_mode[1] = + ext_intra_mode_info.use_ext_intra_mode[1]; + mbmi->ext_intra_mode_info.ext_intra_mode[1] = + ext_intra_mode_info.ext_intra_mode[1]; + return 1; + } else { + return 0; + } +} + +static int rd_pick_intra_angle_sbuv(VP10_COMP *cpi, MACROBLOCK *x, + PICK_MODE_CONTEXT *ctx, + int *rate, int *rate_tokenonly, + int64_t *distortion, int *skippable, + BLOCK_SIZE bsize, int rate_overhead, + int64_t best_rd) { + MACROBLOCKD *const xd = &x->e_mbd; + MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi; + int this_rate_tokenonly, this_rate, s; + int64_t this_distortion, this_sse, this_rd; + int angle_delta, best_angle_delta = 0; + const double rd_adjust = 1.2; + + (void)ctx; + *rate_tokenonly = INT_MAX; if (ANGLE_FAST_SEARCH) { - best_angle = EXT_INTRA_ANGLES / 2; - for (step = 0; step < 3; ++step) { - delta = deltas[step]; - for (i = -branches[step]; i <= branches[step]; ++i) { - int64_t rd_thresh; - if (i == 0 && step != 0) - continue; - angle = best_angle + i * delta; - if (angle < 0) - angle = 0; - if (angle >= EXT_INTRA_ANGLES) - angle = EXT_INTRA_ANGLES - 1; - if (angle == best_angle && step != 0) - continue; - mbmi->ext_intra_mode_info.ext_intra_angle[1] = angle; - if (*best_rd == INT64_MAX) - rd_thresh = best_angle_rd; + int deltas_level1[3] = {0, -2, 2}; + int deltas_level2[3][2] = { + {-1, 1}, {-3, -1}, {1, 3}, + }; + const int level1 = 3, level2 = 2; + int i, j, best_i = -1; + + for (i = 0; i < level1; ++i) { + mbmi->angle_delta[1] = deltas_level1[i]; + if (!super_block_uvrd(cpi, x, &this_rate_tokenonly, + &this_distortion, &s, &this_sse, bsize, + (i == 0 && best_rd < INT64_MAX) ? + best_rd * rd_adjust : best_rd)) { + if (i == 0) + break; else - rd_thresh = VPXMIN(best_angle_rd, *best_rd * RD_ADJUSTER); - if (!super_block_uvrd(cpi, x, &this_rate_tokenonly, &this_distortion, - &s, &this_sse, bsize, rd_thresh)) continue; - this_rate = this_rate_tokenonly + - vp10_cost_bit(cpi->common.fc->ext_intra_probs[1], 1) + - (DR_ONLY ? 0: vp10_cost_bit(DR_EXT_INTRA_PROB, 1)) + - cpi->intra_uv_mode_cost[mbmi->mode][mbmi->uv_mode] + - write_uniform_cost(EXT_INTRA_ANGLES, angle); + } + this_rate = this_rate_tokenonly + rate_overhead; + this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion); + if (i == 0 && best_rd < INT64_MAX && this_rd > best_rd * rd_adjust) + break; + if (this_rd < best_rd) { + best_i = i; + best_rd = this_rd; + best_angle_delta = mbmi->angle_delta[1]; + *rate = this_rate; + *rate_tokenonly = this_rate_tokenonly; + *distortion = this_distortion; + *skippable = s; + } + } + + if (best_i >= 0) { + for (j = 0; j < level2; ++j) { + mbmi->angle_delta[1] = deltas_level2[best_i][j]; + if (!super_block_uvrd(cpi, x, &this_rate_tokenonly, + &this_distortion, &s, &this_sse, bsize, best_rd)) + continue; + this_rate = this_rate_tokenonly + rate_overhead; this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion); - if (this_rd < *best_rd) { - *best_rd = this_rd; - *rate = this_rate; - *rate_tokenonly = this_rate_tokenonly; - *distortion = this_distortion; - *skippable = s; - ext_intra_mode_info = mbmi->ext_intra_mode_info; - ext_intra_selected_flag = 1; - if (!x->select_tx_size) - swap_block_ptr(x, ctx, 2, 0, 1, MAX_MB_PLANE); - } - if (this_rd < best_angle_rd) { - best_angle_rd = this_rd; - best_angle_dir = i; + if (this_rd < best_rd) { + best_rd = this_rd; + best_angle_delta = mbmi->angle_delta[1]; + *rate = this_rate; + *rate_tokenonly = this_rate_tokenonly; + *distortion = this_distortion; + *skippable = s; } } - best_angle += best_angle_dir * delta; - if (best_angle < 0) - best_angle = 0; - if (best_angle >= EXT_INTRA_ANGLES) - best_angle = EXT_INTRA_ANGLES - 1; - if (*best_rd < best_angle_rd / RD_ADJUSTER) - break; } } else { - for (angle = 0; angle < EXT_INTRA_ANGLES; ++angle) { - mbmi->ext_intra_mode_info.ext_intra_angle[1] = angle; - if (prediction_angle_map(angle) == 90 || - prediction_angle_map(angle) == 180) - continue; + for (angle_delta = -MAX_ANGLE_DELTAS; angle_delta <= MAX_ANGLE_DELTAS; + ++angle_delta) { + mbmi->angle_delta[1] = angle_delta; if (!super_block_uvrd(cpi, x, &this_rate_tokenonly, - &this_distortion, &s, &this_sse, bsize, *best_rd)) + &this_distortion, &s, &this_sse, bsize, best_rd)) continue; - - this_rate = this_rate_tokenonly + - vp10_cost_bit(cpi->common.fc->ext_intra_probs[1], 1) + - (DR_ONLY ? 0: vp10_cost_bit(DR_EXT_INTRA_PROB, 1)) + - cpi->intra_uv_mode_cost[mbmi->mode][mbmi->uv_mode] + - write_uniform_cost(EXT_INTRA_ANGLES, angle); + this_rate = this_rate_tokenonly + rate_overhead; this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion); - if (this_rd < *best_rd) { - *best_rd = this_rd; - *rate = this_rate; - *rate_tokenonly = this_rate_tokenonly; - *distortion = this_distortion; - *skippable = s; - ext_intra_mode_info = mbmi->ext_intra_mode_info; - ext_intra_selected_flag = 1; - if (!x->select_tx_size) - swap_block_ptr(x, ctx, 2, 0, 1, MAX_MB_PLANE); + if (this_rd < best_rd) { + best_rd = this_rd; + best_angle_delta = mbmi->angle_delta[1]; + *rate = this_rate; + *rate_tokenonly = this_rate_tokenonly; + *distortion = this_distortion; + *skippable = s; } } } - if (ext_intra_selected_flag) { - mbmi->uv_mode = DC_PRED; - mbmi->ext_intra_mode_info.use_ext_intra_mode[1] = - ext_intra_mode_info.use_ext_intra_mode[1]; - mbmi->ext_intra_mode_info.ext_intra_mode[1] = - ext_intra_mode_info.ext_intra_mode[1]; - mbmi->ext_intra_mode_info.ext_intra_angle[1] = - ext_intra_mode_info.ext_intra_angle[1]; - - return 1; - } else { - return 0; - } + mbmi->angle_delta[1] = best_angle_delta; + if (*rate_tokenonly != INT_MAX) + super_block_uvrd(cpi, x, &this_rate_tokenonly, + &this_distortion, &s, &this_sse, bsize, INT_MAX); + return *rate_tokenonly != INT_MAX; } #endif // CONFIG_EXT_INTRA @@ -2619,6 +2674,7 @@ static int64_t rd_pick_intra_sbuv_mode(VP10_COMP *cpi, MACROBLOCK *x, int this_rate_tokenonly, this_rate, s; int64_t this_distortion, this_sse; #if CONFIG_EXT_INTRA + int is_directional_mode, rate_overhead, best_angle_delta = 0; EXT_INTRA_MODE_INFO ext_intra_mode_info; ext_intra_mode_info.use_ext_intra_mode[1] = 0; @@ -2631,20 +2687,44 @@ static int64_t rd_pick_intra_sbuv_mode(VP10_COMP *cpi, MACROBLOCK *x, continue; mbmi->uv_mode = mode; - +#if CONFIG_EXT_INTRA + is_directional_mode = (mode != DC_PRED && mode != TM_PRED); + rate_overhead = cpi->intra_uv_mode_cost[mbmi->mode][mode] + + write_uniform_cost(2 * MAX_ANGLE_DELTAS + 1, 0); + mbmi->angle_delta[1] = 0; + if (mbmi->sb_type >= BLOCK_8X8 && is_directional_mode) { + if (!rd_pick_intra_angle_sbuv(cpi, x, ctx, &this_rate, + &this_rate_tokenonly, &this_distortion, &s, + bsize, rate_overhead, best_rd)) + continue; + } else { + if (!super_block_uvrd(cpi, x, &this_rate_tokenonly, + &this_distortion, &s, &this_sse, bsize, best_rd)) + continue; + } + this_rate = this_rate_tokenonly + + cpi->intra_uv_mode_cost[mbmi->mode][mode]; + if (mbmi->sb_type >= BLOCK_8X8 && is_directional_mode) + this_rate += write_uniform_cost(2 * MAX_ANGLE_DELTAS + 1, + MAX_ANGLE_DELTAS + + mbmi->angle_delta[1]); + if (mode == DC_PRED && 0) + this_rate += vp10_cost_bit(cpi->common.fc->ext_intra_probs[1], 0); +#else if (!super_block_uvrd(cpi, x, &this_rate_tokenonly, &this_distortion, &s, &this_sse, bsize, best_rd)) continue; this_rate = this_rate_tokenonly + cpi->intra_uv_mode_cost[xd->mi[0]->mbmi.mode][mode]; -#if CONFIG_EXT_INTRA - if (mode == DC_PRED) - this_rate += vp10_cost_bit(cpi->common.fc->ext_intra_probs[1], 0); #endif // CONFIG_EXT_INTRA + this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion); if (this_rd < best_rd) { mode_selected = mode; +#if CONFIG_EXT_INTRA + best_angle_delta = mbmi->angle_delta[1]; +#endif // CONFIG_EXT_INTRA best_rd = this_rd; *rate = this_rate; *rate_tokenonly = this_rate_tokenonly; @@ -2656,7 +2736,7 @@ static int64_t rd_pick_intra_sbuv_mode(VP10_COMP *cpi, MACROBLOCK *x, } #if CONFIG_EXT_INTRA - if (mbmi->sb_type >= BLOCK_8X8) { + if (mbmi->sb_type >= BLOCK_8X8 && ALLOW_FILTER_INTRA_MODES) { if (rd_pick_ext_intra_sbuv(cpi, x, ctx, rate, rate_tokenonly, distortion, skippable, bsize, &best_rd)) { mode_selected = mbmi->uv_mode; @@ -2669,6 +2749,7 @@ static int64_t rd_pick_intra_sbuv_mode(VP10_COMP *cpi, MACROBLOCK *x, if (ext_intra_mode_info.use_ext_intra_mode[1]) mbmi->ext_intra_mode_info.ext_intra_mode[1] = ext_intra_mode_info.ext_intra_mode[1]; + mbmi->angle_delta[1] = best_angle_delta; #endif // CONFIG_EXT_INTRA mbmi->uv_mode = mode_selected; return best_rd; @@ -4478,6 +4559,9 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, PREDICTION_MODE mode_uv[TX_SIZES]; #if CONFIG_EXT_INTRA EXT_INTRA_MODE_INFO ext_intra_mode_info_uv[TX_SIZES]; + int8_t uv_angle_delta[TX_SIZES]; + int is_directional_mode; + int rate_overhead, rate_dummy; #endif // CONFIG_EXT_INTRA const int intra_cost_penalty = vp10_get_intra_cost_penalty( cm->base_qindex, cm->y_dc_delta_q, cm->bit_depth); @@ -4762,17 +4846,31 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, TX_SIZE uv_tx; struct macroblockd_plane *const pd = &xd->plane[1]; memset(x->skip_txfm, 0, sizeof(x->skip_txfm)); - super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable, - NULL, bsize, best_rd); + #if CONFIG_EXT_INTRA + is_directional_mode = (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED); + if (is_directional_mode) { + rate_overhead = write_uniform_cost(2 * MAX_ANGLE_DELTAS + 1, 0) + + cpi->mbmode_cost[mbmi->mode]; + rate_y = INT_MAX; + this_rd = + rd_pick_intra_angle_sby(cpi, x, &rate_dummy, &rate_y, &distortion_y, + &skippable, bsize, rate_overhead, best_rd); + } else { + mbmi->angle_delta[0] = 0; + super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable, + NULL, bsize, best_rd); + } + // TODO(huisu): ext-intra is turned off in lossless mode for now to // avoid a unit test failure - if (mbmi->mode == DC_PRED && !xd->lossless[mbmi->segment_id]) { + if (mbmi->mode == DC_PRED && !xd->lossless[mbmi->segment_id] && + ALLOW_FILTER_INTRA_MODES) { MB_MODE_INFO mbmi_copy = *mbmi; - int rate_dummy; if (rate_y != INT_MAX) { - int this_rate = rate_y + cpi->mbmode_cost[mbmi->mode] + + int this_rate = rate_y + + cpi->mbmode_cost[mbmi->mode] + vp10_cost_bit(cm->fc->ext_intra_probs[0], 0); this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, distortion_y); } else { @@ -4784,7 +4882,11 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, cpi->mbmode_cost[mbmi->mode], &this_rd)) *mbmi = mbmi_copy; } +#else + super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable, + NULL, bsize, best_rd); #endif // CONFIG_EXT_INTRA + if (rate_y == INT_MAX) continue; uv_tx = get_uv_tx_size_impl(mbmi->tx_size, bsize, pd->subsampling_x, @@ -4795,6 +4897,7 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, &dist_uv[uv_tx], &skip_uv[uv_tx], &mode_uv[uv_tx]); #if CONFIG_EXT_INTRA ext_intra_mode_info_uv[uv_tx] = mbmi->ext_intra_mode_info; + uv_angle_delta[uv_tx] = mbmi->angle_delta[1]; #endif // CONFIG_EXT_INTRA } @@ -4803,32 +4906,29 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, skippable = skippable && skip_uv[uv_tx]; mbmi->uv_mode = mode_uv[uv_tx]; #if CONFIG_EXT_INTRA + mbmi->angle_delta[1] = uv_angle_delta[uv_tx]; mbmi->ext_intra_mode_info.use_ext_intra_mode[1] = ext_intra_mode_info_uv[uv_tx].use_ext_intra_mode[1]; if (ext_intra_mode_info_uv[uv_tx].use_ext_intra_mode[1]) { mbmi->ext_intra_mode_info.ext_intra_mode[1] = ext_intra_mode_info_uv[uv_tx].ext_intra_mode[1]; - mbmi->ext_intra_mode_info.ext_intra_angle[1] = - ext_intra_mode_info_uv[uv_tx].ext_intra_angle[1]; } #endif // CONFIG_EXT_INTRA rate2 = rate_y + cpi->mbmode_cost[mbmi->mode] + rate_uv_intra[uv_tx]; #if CONFIG_EXT_INTRA - if (mbmi->mode == DC_PRED) { + if (is_directional_mode) + rate2 += write_uniform_cost(2 * MAX_ANGLE_DELTAS + 1, + MAX_ANGLE_DELTAS + + mbmi->angle_delta[0]); + + if (mbmi->mode == DC_PRED && ALLOW_FILTER_INTRA_MODES) { rate2 += vp10_cost_bit(cm->fc->ext_intra_probs[0], mbmi->ext_intra_mode_info.use_ext_intra_mode[0]); if (mbmi->ext_intra_mode_info.use_ext_intra_mode[0]) { EXT_INTRA_MODE ext_intra_mode = mbmi->ext_intra_mode_info.ext_intra_mode[0]; - int angle = mbmi->ext_intra_mode_info.ext_intra_angle[0]; - if (!DR_ONLY) - rate2 += vp10_cost_bit(DR_EXT_INTRA_PROB, - ext_intra_mode > FILTER_TM_PRED); - if (ext_intra_mode > FILTER_TM_PRED) - rate2 += write_uniform_cost(EXT_INTRA_ANGLES, angle); - else - rate2 += write_uniform_cost(FILTER_INTRA_MODES, ext_intra_mode); + rate2 += write_uniform_cost(FILTER_INTRA_MODES, ext_intra_mode); } } #endif // CONFIG_EXT_INTRA