Commit be3559ba authored by hui su's avatar hui su

ext-intra experiment

Currently there are two parts in this experiment: extra directional intra
prediction modes and the filter intra modes migrated from the nextgen branch.

Several macros are defined in "blockd.h" to provide controls of the experiment
settings. Setting "DR_ONLY" as 1 (default is 0) means we only use directional
modes, and skip the filter-intra modes; "EXT_INTRA_ANGLES" (default is 128)
defines the number of different angles we want to support; setting
"ANGLE_FAST_SEARCH" as 1 (default is 1) means we use fast sub-optimal search
for the best prediction angle, instead of exhaustive search. The fast search
is about 6 times faster than the exhaustive search, while preserving about
60% of the coding gains.

With extra directional prediction modes (fast search), we observe the following
code gains (number in parentheses is for all-key-frame setting):
derflr +0.42%  (+1.79%)
hevclr +0.78%  (+2.19%)
hevcmr +1.20%  (+3.49%)
stdhd  +0.56%
Speed-wise, about 110% slower for key frames, and 30% slower overall.

The gains of filter intra modes mostly add up with the gains of directional
modes. The overall coding gain of this experiment:
derflr +0.94%
hevclr +1.46%
hevcmr +1.94%
stdhd  +1.58%

Change-Id: Ida9ad00cdb33aff422d06eb42b4f4e5f25df8a2a
parent 4101154d
......@@ -77,6 +77,15 @@ typedef struct {
uint8_t palette_first_color_idx[2];
} PALETTE_MODE_INFO;
#if CONFIG_EXT_INTRA
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
// This structure now relates to 8x8 block regions.
typedef struct {
// Common for both INTER and INTRA blocks
......@@ -106,6 +115,10 @@ typedef struct {
TX_TYPE tx_type;
#endif // CONFIG_EXT_TX
#if CONFIG_EXT_INTRA
EXT_INTRA_MODE_INFO ext_intra_mode_info;
#endif // CONFIG_EXT_INTRA
// TODO(slavarnway): Delete and use bmi[3].as_mv[] instead.
int_mv mv[2];
} MB_MODE_INFO;
......@@ -307,11 +320,72 @@ 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 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 const TX_TYPE filter_intra_mode_to_tx_type_lookup[FILTER_INTRA_MODES] = {
DCT_DCT, // FILTER_DC
ADST_DCT, // FILTER_V
DCT_ADST, // FILTER_H
DCT_DCT, // FILTER_D45
ADST_ADST, // FILTER_D135
ADST_DCT, // FILTER_D117
DCT_ADST, // FILTER_D153
DCT_ADST, // FILTER_D207
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,
const MACROBLOCKD *xd,
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) && 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)
#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];
}
}
}
#endif // CONFIG_EXT_INTRA
#if CONFIG_EXT_TX
#if USE_IDTX_FOR_32X32
......@@ -328,7 +402,6 @@ static INLINE TX_TYPE get_tx_type(PLANE_TYPE plane_type,
// UV Inter only
return (mbmi->tx_type == IDTX && tx_size == TX_32X32 ?
DCT_DCT : mbmi->tx_type);
// return mbmi->tx_type;
}
// Sub8x8-Inter/Intra OR UV-Intra
......
......@@ -955,6 +955,10 @@ static const struct segmentation_probs default_seg_probs = {
};
#endif
#if CONFIG_EXT_INTRA
static const vpx_prob default_ext_intra_probs[2] = {200, 200};
#endif // CONFIG_EXT_INTRA
static void init_mode_probs(FRAME_CONTEXT *fc) {
vp10_copy(fc->uv_mode_prob, default_uv_probs);
vp10_copy(fc->y_mode_prob, default_if_y_probs);
......@@ -978,6 +982,9 @@ static void init_mode_probs(FRAME_CONTEXT *fc) {
vp10_copy(fc->seg.tree_probs, default_seg_probs.tree_probs);
vp10_copy(fc->seg.pred_probs, default_seg_probs.pred_probs);
#endif
#if CONFIG_EXT_INTRA
vp10_copy(fc->ext_intra_probs, default_ext_intra_probs);
#endif // CONFIG_EXT_INTRA
}
const vpx_tree_index vp10_switchable_interp_tree
......@@ -1119,6 +1126,12 @@ void vp10_adapt_intra_frame_probs(VP10_COMMON *cm) {
vpx_tree_merge_probs(vp10_partition_tree, pre_fc->partition_prob[i],
counts->partition[i], fc->partition_prob[i]);
#endif
#if CONFIG_EXT_INTRA
for (i = 0; i < PLANE_TYPES; ++i) {
fc->ext_intra_probs[i] = mode_mv_merge_probs(
pre_fc->ext_intra_probs[i], counts->ext_intra[i]);
}
#endif // CONFIG_EXT_INTRA
}
static void set_default_lf_deltas(struct loopfilter *lf) {
......
......@@ -32,6 +32,10 @@ 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;
......@@ -72,6 +76,7 @@ typedef struct frame_contexts {
#endif
vpx_prob skip_probs[SKIP_CONTEXTS];
nmv_context nmvc;
int initialized;
#if CONFIG_EXT_TX
vpx_prob inter_ext_tx_prob[EXT_TX_SETS_INTER][EXT_TX_SIZES][TX_TYPES - 1];
vpx_prob intra_ext_tx_prob[EXT_TX_SETS_INTRA][EXT_TX_SIZES][INTRA_MODES]
......@@ -80,7 +85,9 @@ typedef struct frame_contexts {
#if CONFIG_MISC_FIXES
struct segmentation_probs seg;
#endif
int initialized;
#if CONFIG_EXT_INTRA
vpx_prob ext_intra_probs[PLANE_TYPES];
#endif // CONFIG_EXT_INTRA
} FRAME_CONTEXT;
typedef struct FRAME_COUNTS {
......@@ -112,6 +119,9 @@ typedef struct FRAME_COUNTS {
#if CONFIG_MISC_FIXES
struct seg_counts seg;
#endif
#if CONFIG_EXT_INTRA
unsigned int ext_intra[PLANE_TYPES][2];
#endif // CONFIG_EXT_INTRA
} FRAME_COUNTS;
extern const vpx_prob vp10_kf_y_mode_prob[INTRA_MODES][INTRA_MODES]
......
......@@ -156,6 +156,25 @@ typedef enum {
PALETTE_COLORS
} PALETTE_COLOR;
#if CONFIG_EXT_INTRA
typedef enum {
FILTER_DC_PRED,
FILTER_V_PRED,
FILTER_H_PRED,
FILTER_D45_PRED,
FILTER_D135_PRED,
FILTER_D117_PRED,
FILTER_D153_PRED,
FILTER_D207_PRED,
FILTER_D63_PRED,
FILTER_TM_PRED,
EXT_DR_PRED,
EXT_INTRA_MODES,
} EXT_INTRA_MODE;
#define FILTER_INTRA_MODES (FILTER_TM_PRED + 1)
#endif // CONFIG_EXT_INTRA
#define DC_PRED 0 // Average of above and left pixels
#define V_PRED 1 // Vertical
#define H_PRED 2 // Horizontal
......
This diff is collapsed.
......@@ -472,4 +472,10 @@ void vp10_accumulate_frame_counts(VP10_COMMON *cm, FRAME_COUNTS *counts,
cm->counts.seg.tree_mispred[i] += counts->seg.tree_mispred[i];
}
#endif
#if CONFIG_EXT_INTRA
for (i = 0; i < PLANE_TYPES; ++i)
for (j = 0; j < 2; j++)
cm->counts.ext_intra[i][j] += counts->ext_intra[i][j];
#endif // CONFIG_EXT_INTRA
}
......@@ -340,6 +340,47 @@ static void read_palette_mode_info(VP10_COMMON *const cm,
}
}
#if CONFIG_EXT_INTRA
static void read_ext_intra_mode_info(VP10_COMMON *const cm,
MACROBLOCKD *const xd, vpx_reader *r) {
MODE_INFO *const mi = xd->mi[0];
MB_MODE_INFO *const mbmi = &mi->mbmi;
FRAME_COUNTS *counts = xd->counts;
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);
}
}
if (counts)
++counts->ext_intra[0][mbmi->ext_intra_mode_info.use_ext_intra_mode[0]];
}
if (mbmi->uv_mode == DC_PRED) {
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);
}
}
if (counts)
++counts->ext_intra[1][mbmi->ext_intra_mode_info.use_ext_intra_mode[1]];
}
}
#endif // CONFIG_EXT_INTRA
static void read_intra_frame_mode_info(VP10_COMMON *const cm,
MACROBLOCKD *const xd,
int mi_row, int mi_col, vpx_reader *r) {
......@@ -413,6 +454,13 @@ static void read_intra_frame_mode_info(VP10_COMMON *const cm,
mbmi->tx_type = DCT_DCT;
}
#endif // CONFIG_EXT_TX
#if CONFIG_EXT_INTRA
mbmi->ext_intra_mode_info.use_ext_intra_mode[0] = 0;
mbmi->ext_intra_mode_info.use_ext_intra_mode[1] = 0;
if (bsize >= BLOCK_8X8)
read_ext_intra_mode_info(cm, xd, r);
#endif // CONFIG_EXT_INTRA
}
static int read_mv_component(vpx_reader *r,
......@@ -576,9 +624,14 @@ static void read_intra_block_mode_info(VP10_COMMON *const cm,
}
mbmi->uv_mode = read_intra_mode_uv(cm, xd, r, mbmi->mode);
mbmi->palette_mode_info.palette_size[0] = 0;
mbmi->palette_mode_info.palette_size[1] = 0;
#if CONFIG_EXT_INTRA
mbmi->ext_intra_mode_info.use_ext_intra_mode[0] = 0;
mbmi->ext_intra_mode_info.use_ext_intra_mode[1] = 0;
if (bsize >= BLOCK_8X8)
read_ext_intra_mode_info(cm, xd, r);
#endif // CONFIG_EXT_INTRA
}
static INLINE int is_mv_valid(const MV *mv) {
......
......@@ -511,6 +511,43 @@ static void write_ref_frames(const VP10_COMMON *cm, const MACROBLOCKD *xd,
}
}
#if CONFIG_EXT_INTRA
static void write_ext_intra_mode_info(const VP10_COMMON *const cm,
const MB_MODE_INFO *const mbmi,
vpx_writer *w) {
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);
}
}
if (mbmi->uv_mode == DC_PRED) {
vpx_write(w, mbmi->ext_intra_mode_info.use_ext_intra_mode[1],
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);
}
}
}
#endif // CONFIG_EXT_INTRA
static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi,
vpx_writer *w) {
VP10_COMMON *const cm = &cpi->common;
......@@ -592,6 +629,10 @@ 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 (bsize >= BLOCK_8X8)
write_ext_intra_mode_info(cm, mbmi, w);
#endif // CONFIG_EXT_INTRA
} else {
const int mode_ctx = mbmi_ext->mode_context[mbmi->ref_frame[0]];
const vpx_prob *const inter_probs = cm->fc->inter_mode_probs[mode_ctx];
......@@ -750,6 +791,11 @@ static void write_mb_modes_kf(const VP10_COMMON *cm, const MACROBLOCKD *xd,
&ext_tx_intra_encodings[eset][mbmi->tx_type]);
}
#endif // CONFIG_EXT_TX
#if CONFIG_EXT_INTRA
if (bsize >= BLOCK_8X8)
write_ext_intra_mode_info(cm, mbmi, w);
#endif // CONFIG_EXT_INTRA
}
static void write_modes_b(VP10_COMP *cpi, const TileInfo *const tile,
......@@ -1780,7 +1826,7 @@ static size_t write_compressed_header(VP10_COMP *cpi, uint8_t *data) {
&counts->mv);
#if CONFIG_EXT_TX
update_ext_tx_probs(cm, &header_bc);
#endif
#endif // CONFIG_EXT_TX
}
vpx_stop_encode(&header_bc);
......
......@@ -3312,6 +3312,16 @@ static void encode_superblock(VP10_COMP *cpi, ThreadData *td,
}
}
#endif // CONFIG_EXT_TX
#if CONFIG_EXT_INTRA
if (bsize >= BLOCK_8X8 && !is_inter_block(mbmi)) {
if (mbmi->mode == DC_PRED)
++td->counts->ext_intra[0]
[mbmi->ext_intra_mode_info.use_ext_intra_mode[0]];
if (mbmi->uv_mode == DC_PRED)
++td->counts->ext_intra[1]
[mbmi->ext_intra_mode_info.use_ext_intra_mode[1]];
}
#endif // CONFIG_EXT_INTRA
}
#if CONFIG_VAR_TX
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment