Merge "Extension of segmentation to 8 segments." into experimental

This commit is contained in:
Paul Wilkins 2013-04-24 09:44:48 -07:00 committed by Gerrit Code Review
commit 6579720e6a
10 changed files with 119 additions and 110 deletions

View File

@ -23,7 +23,8 @@
// #define MODE_STATS // #define MODE_STATS
#define MB_FEATURE_TREE_PROBS 3 #define MAX_MB_SEGMENTS 8
#define MB_SEG_TREE_PROBS (MAX_MB_SEGMENTS-1)
#define PREDICTION_PROBS 3 #define PREDICTION_PROBS 3
#define DEFAULT_PRED_PROB_0 120 #define DEFAULT_PRED_PROB_0 120
@ -32,8 +33,6 @@
#define MBSKIP_CONTEXTS 3 #define MBSKIP_CONTEXTS 3
#define MAX_MB_SEGMENTS 4
#define MAX_REF_LF_DELTAS 4 #define MAX_REF_LF_DELTAS 4
#define MAX_MODE_LF_DELTAS 4 #define MAX_MODE_LF_DELTAS 4
@ -398,7 +397,7 @@ typedef struct macroblockd {
/* are enabled and when enabled the proabilities used to decode the per MB flags in MB_MODE_INFO */ /* are enabled and when enabled the proabilities used to decode the per MB flags in MB_MODE_INFO */
// Probability Tree used to code Segment number // Probability Tree used to code Segment number
vp9_prob mb_segment_tree_probs[MB_FEATURE_TREE_PROBS]; vp9_prob mb_segment_tree_probs[MB_SEG_TREE_PROBS];
// Segment features // Segment features
signed char segment_feature_data[MAX_MB_SEGMENTS][SEG_LVL_MAX]; signed char segment_feature_data[MAX_MB_SEGMENTS][SEG_LVL_MAX];

View File

@ -36,7 +36,7 @@ typedef struct {
lim[MAX_LOOP_FILTER + 1][SIMD_WIDTH]); lim[MAX_LOOP_FILTER + 1][SIMD_WIDTH]);
DECLARE_ALIGNED(SIMD_WIDTH, unsigned char, DECLARE_ALIGNED(SIMD_WIDTH, unsigned char,
hev_thr[4][SIMD_WIDTH]); hev_thr[4][SIMD_WIDTH]);
unsigned char lvl[4][4][4]; unsigned char lvl[MAX_MB_SEGMENTS][4][4];
unsigned char mode_lf_lut[MB_MODE_COUNT]; unsigned char mode_lf_lut[MB_MODE_COUNT];
} loop_filter_info_n; } loop_filter_info_n;

View File

@ -21,6 +21,9 @@ extern "C"
#include "vpx/vp8cx.h" #include "vpx/vp8cx.h"
#include "vpx_scale/yv12config.h" #include "vpx_scale/yv12config.h"
#include "vp9/common/vp9_ppflags.h" #include "vp9/common/vp9_ppflags.h"
#define MAX_MB_SEGMENTS 8
typedef int *VP9_PTR; typedef int *VP9_PTR;
/* Create/destroy static data structures. */ /* Create/destroy static data structures. */
@ -225,8 +228,9 @@ extern "C"
int vp9_set_roimap(VP9_PTR comp, unsigned char *map, int vp9_set_roimap(VP9_PTR comp, unsigned char *map,
unsigned int rows, unsigned int cols, unsigned int rows, unsigned int cols,
int delta_q[4], int delta_lf[4], int delta_q[MAX_MB_SEGMENTS],
unsigned int threshold[4]); int delta_lf[MAX_MB_SEGMENTS],
unsigned int threshold[MAX_MB_SEGMENTS]);
int vp9_set_active_map(VP9_PTR comp, unsigned char *map, int vp9_set_active_map(VP9_PTR comp, unsigned char *map,
unsigned int rows, unsigned int cols); unsigned int rows, unsigned int cols);

View File

@ -75,8 +75,22 @@ static MB_PREDICTION_MODE read_uv_mode(vp9_reader *r, const vp9_prob *p) {
static int read_mb_segid(vp9_reader *r, MACROBLOCKD *xd) { static int read_mb_segid(vp9_reader *r, MACROBLOCKD *xd) {
const vp9_prob *const p = xd->mb_segment_tree_probs; const vp9_prob *const p = xd->mb_segment_tree_probs;
return vp9_read(r, p[0]) ? 2 + vp9_read(r, p[2]) int ret_val;
: vp9_read(r, p[1]);
if (vp9_read(r, p[0])) {
if (vp9_read(r, p[4])) {
ret_val = 6 + vp9_read(r, p[6]);
} else {
ret_val = 4 + vp9_read(r, p[5]);
}
} else {
if (vp9_read(r, p[1])) {
ret_val = 2 + vp9_read(r, p[3]);
} else {
ret_val = vp9_read(r, p[2]);
}
}
return ret_val;
} }
static void set_segment_id(VP9_COMMON *cm, MB_MODE_INFO *mbmi, static void set_segment_id(VP9_COMMON *cm, MB_MODE_INFO *mbmi,

View File

@ -1107,7 +1107,7 @@ static void setup_segmentation(VP9_COMMON *pc, MACROBLOCKD *xd, vp9_reader *r) {
xd->allow_implicit_segment_update = vp9_read_bit(r); xd->allow_implicit_segment_update = vp9_read_bit(r);
#endif #endif
if (xd->update_mb_segmentation_map) { if (xd->update_mb_segmentation_map) {
for (i = 0; i < MB_FEATURE_TREE_PROBS; i++) for (i = 0; i < MB_SEG_TREE_PROBS; i++)
xd->mb_segment_tree_probs[i] = vp9_read_bit(r) ? vp9_read_prob(r) xd->mb_segment_tree_probs[i] = vp9_read_bit(r) ? vp9_read_prob(r)
: MAX_PROB; : MAX_PROB;

View File

@ -537,24 +537,49 @@ static void write_mb_segid(vp9_writer *bc,
case 0: case 0:
vp9_write(bc, 0, xd->mb_segment_tree_probs[0]); vp9_write(bc, 0, xd->mb_segment_tree_probs[0]);
vp9_write(bc, 0, xd->mb_segment_tree_probs[1]); vp9_write(bc, 0, xd->mb_segment_tree_probs[1]);
vp9_write(bc, 0, xd->mb_segment_tree_probs[2]);
break; break;
case 1: case 1:
vp9_write(bc, 0, xd->mb_segment_tree_probs[0]); vp9_write(bc, 0, xd->mb_segment_tree_probs[0]);
vp9_write(bc, 1, xd->mb_segment_tree_probs[1]); vp9_write(bc, 0, xd->mb_segment_tree_probs[1]);
vp9_write(bc, 1, xd->mb_segment_tree_probs[2]);
break; break;
case 2: case 2:
vp9_write(bc, 1, xd->mb_segment_tree_probs[0]); vp9_write(bc, 0, xd->mb_segment_tree_probs[0]);
vp9_write(bc, 0, xd->mb_segment_tree_probs[2]); vp9_write(bc, 1, xd->mb_segment_tree_probs[1]);
vp9_write(bc, 0, xd->mb_segment_tree_probs[3]);
break; break;
case 3: case 3:
vp9_write(bc, 0, xd->mb_segment_tree_probs[0]);
vp9_write(bc, 1, xd->mb_segment_tree_probs[1]);
vp9_write(bc, 1, xd->mb_segment_tree_probs[3]);
break;
case 4:
vp9_write(bc, 1, xd->mb_segment_tree_probs[0]); vp9_write(bc, 1, xd->mb_segment_tree_probs[0]);
vp9_write(bc, 1, xd->mb_segment_tree_probs[2]); vp9_write(bc, 0, xd->mb_segment_tree_probs[4]);
vp9_write(bc, 0, xd->mb_segment_tree_probs[5]);
break;
case 5:
vp9_write(bc, 1, xd->mb_segment_tree_probs[0]);
vp9_write(bc, 0, xd->mb_segment_tree_probs[4]);
vp9_write(bc, 1, xd->mb_segment_tree_probs[5]);
break;
case 6:
vp9_write(bc, 1, xd->mb_segment_tree_probs[0]);
vp9_write(bc, 1, xd->mb_segment_tree_probs[4]);
vp9_write(bc, 0, xd->mb_segment_tree_probs[6]);
break;
case 7:
vp9_write(bc, 1, xd->mb_segment_tree_probs[0]);
vp9_write(bc, 1, xd->mb_segment_tree_probs[4]);
vp9_write(bc, 1, xd->mb_segment_tree_probs[6]);
break; break;
// TRAP.. This should not happen // TRAP.. This should not happen
default: default:
vp9_write(bc, 0, xd->mb_segment_tree_probs[0]); vp9_write(bc, 0, xd->mb_segment_tree_probs[0]);
vp9_write(bc, 0, xd->mb_segment_tree_probs[1]); vp9_write(bc, 0, xd->mb_segment_tree_probs[1]);
vp9_write(bc, 0, xd->mb_segment_tree_probs[2]);
break; break;
} }
} }
@ -1977,7 +2002,7 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
vp9_choose_segmap_coding_method(cpi); vp9_choose_segmap_coding_method(cpi);
// Send the tree probabilities used to decode unpredicted // Send the tree probabilities used to decode unpredicted
// macro-block segments // macro-block segments
for (i = 0; i < MB_FEATURE_TREE_PROBS; i++) { for (i = 0; i < MB_SEG_TREE_PROBS; i++) {
const int prob = xd->mb_segment_tree_probs[i]; const int prob = xd->mb_segment_tree_probs[i];
if (prob != 255) { if (prob != 255) {
vp9_write_bit(&header_bc, 1); vp9_write_bit(&header_bc, 1);

View File

@ -594,7 +594,7 @@ static void set_offsets(VP9_COMP *cpi,
mbmi->segment_id = find_seg_id(cm->last_frame_seg_map, bsize, mbmi->segment_id = find_seg_id(cm->last_frame_seg_map, bsize,
mb_row, cm->mb_rows, mb_col, cm->mb_cols); mb_row, cm->mb_rows, mb_col, cm->mb_cols);
} }
assert(mbmi->segment_id <= 3); assert(mbmi->segment_id <= (MAX_MB_SEGMENTS-1));
vp9_mb_init_quantizer(cpi, x); vp9_mb_init_quantizer(cpi, x);
if (xd->segmentation_enabled && cpi->seg0_cnt > 0 && if (xd->segmentation_enabled && cpi->seg0_cnt > 0 &&

View File

@ -4204,8 +4204,9 @@ int vp9_get_preview_raw_frame(VP9_PTR comp, YV12_BUFFER_CONFIG *dest,
} }
int vp9_set_roimap(VP9_PTR comp, unsigned char *map, unsigned int rows, int vp9_set_roimap(VP9_PTR comp, unsigned char *map, unsigned int rows,
unsigned int cols, int delta_q[4], int delta_lf[4], unsigned int cols, int delta_q[MAX_MB_SEGMENTS],
unsigned int threshold[4]) { int delta_lf[MAX_MB_SEGMENTS],
unsigned int threshold[MAX_MB_SEGMENTS]) {
VP9_COMP *cpi = (VP9_COMP *) comp; VP9_COMP *cpi = (VP9_COMP *) comp;
signed char feature_data[SEG_LVL_MAX][MAX_MB_SEGMENTS]; signed char feature_data[SEG_LVL_MAX][MAX_MB_SEGMENTS];
MACROBLOCKD *xd = &cpi->mb.e_mbd; MACROBLOCKD *xd = &cpi->mb.e_mbd;
@ -4225,25 +4226,15 @@ int vp9_set_roimap(VP9_PTR comp, unsigned char *map, unsigned int rows,
// Activate segmentation. // Activate segmentation.
vp9_enable_segmentation((VP9_PTR)cpi); vp9_enable_segmentation((VP9_PTR)cpi);
// Set up the quant segment data // Set up the quan, LF and breakout threshold segment data
feature_data[SEG_LVL_ALT_Q][0] = delta_q[0]; for (i = 0; i < MAX_MB_SEGMENTS; i++) {
feature_data[SEG_LVL_ALT_Q][1] = delta_q[1]; feature_data[SEG_LVL_ALT_Q][i] = delta_q[i];
feature_data[SEG_LVL_ALT_Q][2] = delta_q[2]; feature_data[SEG_LVL_ALT_LF][i] = delta_lf[i];
feature_data[SEG_LVL_ALT_Q][3] = delta_q[3]; cpi->segment_encode_breakout[i] = threshold[i];
}
// Set up the loop segment data s
feature_data[SEG_LVL_ALT_LF][0] = delta_lf[0];
feature_data[SEG_LVL_ALT_LF][1] = delta_lf[1];
feature_data[SEG_LVL_ALT_LF][2] = delta_lf[2];
feature_data[SEG_LVL_ALT_LF][3] = delta_lf[3];
cpi->segment_encode_breakout[0] = threshold[0];
cpi->segment_encode_breakout[1] = threshold[1];
cpi->segment_encode_breakout[2] = threshold[2];
cpi->segment_encode_breakout[3] = threshold[3];
// Enable the loop and quant changes in the feature mask // Enable the loop and quant changes in the feature mask
for (i = 0; i < 4; i++) { for (i = 0; i < MAX_MB_SEGMENTS; i++) {
if (delta_q[i]) if (delta_q[i])
vp9_enable_segfeature(xd, i, SEG_LVL_ALT_Q); vp9_enable_segfeature(xd, i, SEG_LVL_ALT_Q);
else else

View File

@ -63,16 +63,18 @@ void vp9_set_segment_data(VP9_PTR ptr,
static void calc_segtree_probs(MACROBLOCKD *xd, static void calc_segtree_probs(MACROBLOCKD *xd,
int *segcounts, int *segcounts,
vp9_prob *segment_tree_probs) { vp9_prob *segment_tree_probs) {
int count1, count2;
// Total count for all segments
count1 = segcounts[0] + segcounts[1];
count2 = segcounts[2] + segcounts[3];
// Work out probabilities of each segment // Work out probabilities of each segment
segment_tree_probs[0] = get_binary_prob(count1, count2); segment_tree_probs[0] =
segment_tree_probs[1] = get_prob(segcounts[0], count1); get_binary_prob(segcounts[0] + segcounts[1] + segcounts[2] + segcounts[3],
segment_tree_probs[2] = get_prob(segcounts[2], count2); segcounts[4] + segcounts[5] + segcounts[6] + segcounts[7]);
segment_tree_probs[1] =
get_binary_prob(segcounts[0] + segcounts[1], segcounts[2] + segcounts[3]);
segment_tree_probs[2] = get_binary_prob(segcounts[0], segcounts[1]);
segment_tree_probs[3] = get_binary_prob(segcounts[2], segcounts[3]);
segment_tree_probs[4] =
get_binary_prob(segcounts[4] + segcounts[5], segcounts[6] + segcounts[7]);
segment_tree_probs[5] = get_binary_prob(segcounts[4], segcounts[5]);
segment_tree_probs[6] = get_binary_prob(segcounts[6], segcounts[7]);
} }
// Based on set of segment counts and probabilities calculate a cost estimate // Based on set of segment counts and probabilities calculate a cost estimate
@ -83,68 +85,38 @@ static int cost_segmap(MACROBLOCKD *xd,
int count1, count2; int count1, count2;
// Cost the top node of the tree // Cost the top node of the tree
count1 = segcounts[0] + segcounts[1]; count1 = segcounts[0] + segcounts[1] + segcounts[2] + segcounts[3];
count2 = segcounts[2] + segcounts[3]; count2 = segcounts[3] + segcounts[4] + segcounts[5] + segcounts[6];
cost = count1 * vp9_cost_zero(probs[0]) + cost = count1 * vp9_cost_zero(probs[0]) +
count2 * vp9_cost_one(probs[0]); count2 * vp9_cost_one(probs[0]);
// Now add the cost of each individual segment branch // Cost subsequent levels
if (count1 > 0) if (count1 > 0) {
cost += segcounts[0] * vp9_cost_zero(probs[1]) + count1 = segcounts[0] + segcounts[1];
segcounts[1] * vp9_cost_one(probs[1]); count2 = segcounts[2] + segcounts[3];
cost += count1 * vp9_cost_zero(probs[1]) +
count2 * vp9_cost_one(probs[1]);
if (count2 > 0) if (count1 > 0)
cost += segcounts[2] * vp9_cost_zero(probs[2]) + cost += segcounts[0] * vp9_cost_zero(probs[2]) +
segcounts[3] * vp9_cost_one(probs[2]); segcounts[1] * vp9_cost_one(probs[2]);
if (count2 > 0)
cost += segcounts[2] * vp9_cost_zero(probs[3]) +
segcounts[3] * vp9_cost_one(probs[3]);
}
return cost; if (count2 > 0) {
} count1 = segcounts[4] + segcounts[5];
count2 = segcounts[6] + segcounts[7];
cost += count1 * vp9_cost_zero(probs[4]) +
count2 * vp9_cost_one(probs[4]);
// Based on set of segment counts calculate a probability tree if (count1 > 0)
static void calc_segtree_probs_pred(MACROBLOCKD *xd, cost += segcounts[4] * vp9_cost_zero(probs[5]) +
int (*segcounts)[MAX_MB_SEGMENTS], segcounts[5] * vp9_cost_one(probs[5]);
vp9_prob *segment_tree_probs) { if (count2 > 0)
int count[4]; cost += segcounts[6] * vp9_cost_zero(probs[6]) +
segcounts[7] * vp9_cost_one(probs[6]);
assert(!segcounts[0][0] && !segcounts[1][1] &&
!segcounts[2][2] && !segcounts[3][3]);
// Total count for all segments
count[0] = segcounts[3][0] + segcounts[1][0] + segcounts[2][0];
count[1] = segcounts[2][1] + segcounts[0][1] + segcounts[3][1];
count[2] = segcounts[0][2] + segcounts[3][2] + segcounts[1][2];
count[3] = segcounts[1][3] + segcounts[2][3] + segcounts[0][3];
// Work out probabilities of each segment
segment_tree_probs[0] = get_binary_prob(count[0] + count[1],
count[2] + count[3]);
segment_tree_probs[1] = get_binary_prob(count[0], count[1]);
segment_tree_probs[2] = get_binary_prob(count[2], count[3]);
}
// Based on set of segment counts and probabilities calculate a cost estimate
static int cost_segmap_pred(MACROBLOCKD *xd,
int (*segcounts)[MAX_MB_SEGMENTS],
vp9_prob *probs) {
int pred_seg, cost = 0;
for (pred_seg = 0; pred_seg < MAX_MB_SEGMENTS; pred_seg++) {
int count1, count2;
// Cost the top node of the tree
count1 = segcounts[pred_seg][0] + segcounts[pred_seg][1];
count2 = segcounts[pred_seg][2] + segcounts[pred_seg][3];
cost += count1 * vp9_cost_zero(probs[0]) +
count2 * vp9_cost_one(probs[0]);
// Now add the cost of each individual segment branch
if (pred_seg >= 2 && count1) {
cost += segcounts[pred_seg][0] * vp9_cost_zero(probs[1]) +
segcounts[pred_seg][1] * vp9_cost_one(probs[1]);
} else if (pred_seg < 2 && count2 > 0) {
cost += segcounts[pred_seg][2] * vp9_cost_zero(probs[2]) +
segcounts[pred_seg][3] * vp9_cost_one(probs[2]);
}
} }
return cost; return cost;
@ -154,7 +126,7 @@ static void count_segs(VP9_COMP *cpi,
MODE_INFO *mi, MODE_INFO *mi,
int *no_pred_segcounts, int *no_pred_segcounts,
int (*temporal_predictor_count)[2], int (*temporal_predictor_count)[2],
int (*t_unpred_seg_counts)[MAX_MB_SEGMENTS], int *t_unpred_seg_counts,
int bw, int bh, int mb_row, int mb_col) { int bw, int bh, int mb_row, int mb_col) {
VP9_COMMON *const cm = &cpi->common; VP9_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &cpi->mb.e_mbd; MACROBLOCKD *const xd = &cpi->mb.e_mbd;
@ -184,7 +156,7 @@ static void count_segs(VP9_COMP *cpi,
if (!seg_predicted) if (!seg_predicted)
// Update the "unpredicted" segment count // Update the "unpredicted" segment count
t_unpred_seg_counts[pred_seg_id][segment_id]++; t_unpred_seg_counts[segment_id]++;
} }
} }
@ -200,10 +172,10 @@ void vp9_choose_segmap_coding_method(VP9_COMP *cpi) {
int temporal_predictor_count[PREDICTION_PROBS][2]; int temporal_predictor_count[PREDICTION_PROBS][2];
int no_pred_segcounts[MAX_MB_SEGMENTS]; int no_pred_segcounts[MAX_MB_SEGMENTS];
int t_unpred_seg_counts[MAX_MB_SEGMENTS][MAX_MB_SEGMENTS]; int t_unpred_seg_counts[MAX_MB_SEGMENTS];
vp9_prob no_pred_tree[MB_FEATURE_TREE_PROBS]; vp9_prob no_pred_tree[MB_SEG_TREE_PROBS];
vp9_prob t_pred_tree[MB_FEATURE_TREE_PROBS]; vp9_prob t_pred_tree[MB_SEG_TREE_PROBS];
vp9_prob t_nopred_prob[PREDICTION_PROBS]; vp9_prob t_nopred_prob[PREDICTION_PROBS];
const int mis = cm->mode_info_stride; const int mis = cm->mode_info_stride;
@ -318,8 +290,8 @@ void vp9_choose_segmap_coding_method(VP9_COMP *cpi) {
if (cm->frame_type != KEY_FRAME) { if (cm->frame_type != KEY_FRAME) {
// Work out probability tree for coding those segments not // Work out probability tree for coding those segments not
// predicted using the temporal method and the cost. // predicted using the temporal method and the cost.
calc_segtree_probs_pred(xd, t_unpred_seg_counts, t_pred_tree); calc_segtree_probs(xd, t_unpred_seg_counts, t_pred_tree);
t_pred_cost = cost_segmap_pred(xd, t_unpred_seg_counts, t_pred_tree); t_pred_cost = cost_segmap(xd, t_unpred_seg_counts, t_pred_tree);
// Add in the cost of the signalling for each prediction context // Add in the cost of the signalling for each prediction context
for (i = 0; i < PREDICTION_PROBS; i++) { for (i = 0; i < PREDICTION_PROBS; i++) {

View File

@ -215,9 +215,13 @@ typedef struct vpx_roi_map {
unsigned char *roi_map; /**< specify an id between 0 and 3 for each 16x16 region within a frame */ unsigned char *roi_map; /**< specify an id between 0 and 3 for each 16x16 region within a frame */
unsigned int rows; /**< number of rows */ unsigned int rows; /**< number of rows */
unsigned int cols; /**< number of cols */ unsigned int cols; /**< number of cols */
int delta_q[4]; /**< quantizer delta [-63, 63] off baseline for regions with id between 0 and 3*/ // TODO(paulwilkins): broken for VP9 which has 8 segments
int delta_lf[4]; /**< loop filter strength delta [-63, 63] for regions with id between 0 and 3 */ // q and loop filter deltas for each segment
unsigned int static_threshold[4];/**< threshold for region to be treated as static */ // (see MAX_MB_SEGMENTS)
int delta_q[4];
int delta_lf[4];
// Static breakout threshold for each segment
unsigned int static_threshold[4];
} vpx_roi_map_t; } vpx_roi_map_t;
/*!\brief vpx active region map /*!\brief vpx active region map