From 31ee193a9ccfccef65dad0fba3462b9f83db97fa Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Wed, 24 Apr 2013 13:04:45 +0100 Subject: Extension of segmentation to 8 segments. Also some further simplification following removal of top node code. There is an issue in regards to the shared file vp8cx.h in regard to the roi_map as this interface assumes that there are only 4 segments. I have left the value here as 4 for now meaning that the roi_map interface is broken for VP9. Note that this change would have been easier if I hadn't had to search for hard wire instances of the number 4 and <= 3. Change-Id: Ia8b6deea4be4dbd20deb1656e689dd43a5f190e8 --- vp9/common/vp9_blockd.h | 7 ++- vp9/common/vp9_loopfilter.h | 2 +- vp9/common/vp9_onyx.h | 8 ++- vp9/decoder/vp9_decodemv.c | 18 ++++++- vp9/decoder/vp9_decodframe.c | 2 +- vp9/encoder/vp9_bitstream.c | 35 ++++++++++-- vp9/encoder/vp9_encodeframe.c | 2 +- vp9/encoder/vp9_onyx_if.c | 29 ++++------ vp9/encoder/vp9_segmentation.c | 120 ++++++++++++++++------------------------- 9 files changed, 114 insertions(+), 109 deletions(-) (limited to 'vp9') diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h index 5b89aff88..6b4f607b1 100644 --- a/vp9/common/vp9_blockd.h +++ b/vp9/common/vp9_blockd.h @@ -23,7 +23,8 @@ // #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 DEFAULT_PRED_PROB_0 120 @@ -32,8 +33,6 @@ #define MBSKIP_CONTEXTS 3 -#define MAX_MB_SEGMENTS 4 - #define MAX_REF_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 */ // 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 signed char segment_feature_data[MAX_MB_SEGMENTS][SEG_LVL_MAX]; diff --git a/vp9/common/vp9_loopfilter.h b/vp9/common/vp9_loopfilter.h index 3b81146e2..81745e48a 100644 --- a/vp9/common/vp9_loopfilter.h +++ b/vp9/common/vp9_loopfilter.h @@ -36,7 +36,7 @@ typedef struct { lim[MAX_LOOP_FILTER + 1][SIMD_WIDTH]); DECLARE_ALIGNED(SIMD_WIDTH, unsigned char, 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]; } loop_filter_info_n; diff --git a/vp9/common/vp9_onyx.h b/vp9/common/vp9_onyx.h index 422f3885f..b85b88968 100644 --- a/vp9/common/vp9_onyx.h +++ b/vp9/common/vp9_onyx.h @@ -21,6 +21,9 @@ extern "C" #include "vpx/vp8cx.h" #include "vpx_scale/yv12config.h" #include "vp9/common/vp9_ppflags.h" + +#define MAX_MB_SEGMENTS 8 + typedef int *VP9_PTR; /* Create/destroy static data structures. */ @@ -225,8 +228,9 @@ extern "C" 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 threshold[4]); + int delta_q[MAX_MB_SEGMENTS], + int delta_lf[MAX_MB_SEGMENTS], + unsigned int threshold[MAX_MB_SEGMENTS]); int vp9_set_active_map(VP9_PTR comp, unsigned char *map, unsigned int rows, unsigned int cols); diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c index 801e41a43..5352a0839 100644 --- a/vp9/decoder/vp9_decodemv.c +++ b/vp9/decoder/vp9_decodemv.c @@ -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) { const vp9_prob *const p = xd->mb_segment_tree_probs; - return vp9_read(r, p[0]) ? 2 + vp9_read(r, p[2]) - : vp9_read(r, p[1]); + int ret_val; + + 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, diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c index 2bd200ef7..864eb82fd 100644 --- a/vp9/decoder/vp9_decodframe.c +++ b/vp9/decoder/vp9_decodframe.c @@ -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); #endif 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) : MAX_PROB; diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 33db0de7d..e80c9ccb7 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -537,24 +537,49 @@ static void write_mb_segid(vp9_writer *bc, case 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[2]); break; case 1: 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; case 2: - vp9_write(bc, 1, xd->mb_segment_tree_probs[0]); - vp9_write(bc, 0, xd->mb_segment_tree_probs[2]); + 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[3]); break; 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[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; // TRAP.. This should not happen default: 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[2]); break; } } @@ -1977,7 +2002,7 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest, vp9_choose_segmap_coding_method(cpi); // Send the tree probabilities used to decode unpredicted // 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]; if (prob != 255) { vp9_write_bit(&header_bc, 1); diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 0837931e5..b1b28c785 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -594,7 +594,7 @@ static void set_offsets(VP9_COMP *cpi, mbmi->segment_id = find_seg_id(cm->last_frame_seg_map, bsize, 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); if (xd->segmentation_enabled && cpi->seg0_cnt > 0 && diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index 03a8388ef..c2c587e10 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -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, - unsigned int cols, int delta_q[4], int delta_lf[4], - unsigned int threshold[4]) { + unsigned int cols, int delta_q[MAX_MB_SEGMENTS], + int delta_lf[MAX_MB_SEGMENTS], + unsigned int threshold[MAX_MB_SEGMENTS]) { VP9_COMP *cpi = (VP9_COMP *) comp; signed char feature_data[SEG_LVL_MAX][MAX_MB_SEGMENTS]; 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. vp9_enable_segmentation((VP9_PTR)cpi); - // Set up the quant segment data - feature_data[SEG_LVL_ALT_Q][0] = delta_q[0]; - feature_data[SEG_LVL_ALT_Q][1] = delta_q[1]; - feature_data[SEG_LVL_ALT_Q][2] = delta_q[2]; - feature_data[SEG_LVL_ALT_Q][3] = delta_q[3]; - - // 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]; + // Set up the quan, LF and breakout threshold segment data + for (i = 0; i < MAX_MB_SEGMENTS; i++) { + feature_data[SEG_LVL_ALT_Q][i] = delta_q[i]; + feature_data[SEG_LVL_ALT_LF][i] = delta_lf[i]; + cpi->segment_encode_breakout[i] = threshold[i]; + } // 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]) vp9_enable_segfeature(xd, i, SEG_LVL_ALT_Q); else diff --git a/vp9/encoder/vp9_segmentation.c b/vp9/encoder/vp9_segmentation.c index 1d3e8529d..56484e693 100644 --- a/vp9/encoder/vp9_segmentation.c +++ b/vp9/encoder/vp9_segmentation.c @@ -63,16 +63,18 @@ void vp9_set_segment_data(VP9_PTR ptr, static void calc_segtree_probs(MACROBLOCKD *xd, int *segcounts, 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 - segment_tree_probs[0] = get_binary_prob(count1, count2); - segment_tree_probs[1] = get_prob(segcounts[0], count1); - segment_tree_probs[2] = get_prob(segcounts[2], count2); + segment_tree_probs[0] = + get_binary_prob(segcounts[0] + segcounts[1] + segcounts[2] + segcounts[3], + 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 @@ -83,68 +85,38 @@ static int cost_segmap(MACROBLOCKD *xd, int count1, count2; // Cost the top node of the tree - count1 = segcounts[0] + segcounts[1]; - count2 = segcounts[2] + segcounts[3]; + count1 = segcounts[0] + segcounts[1] + segcounts[2] + segcounts[3]; + count2 = segcounts[3] + segcounts[4] + segcounts[5] + segcounts[6]; cost = count1 * vp9_cost_zero(probs[0]) + count2 * vp9_cost_one(probs[0]); - // Now add the cost of each individual segment branch - if (count1 > 0) - cost += segcounts[0] * vp9_cost_zero(probs[1]) + - segcounts[1] * vp9_cost_one(probs[1]); - - if (count2 > 0) - cost += segcounts[2] * vp9_cost_zero(probs[2]) + - segcounts[3] * vp9_cost_one(probs[2]); - - return cost; -} - -// Based on set of segment counts calculate a probability tree -static void calc_segtree_probs_pred(MACROBLOCKD *xd, - int (*segcounts)[MAX_MB_SEGMENTS], - vp9_prob *segment_tree_probs) { - int count[4]; - - 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]); -} + // Cost subsequent levels + if (count1 > 0) { + count1 = segcounts[0] + segcounts[1]; + count2 = segcounts[2] + segcounts[3]; + cost += count1 * vp9_cost_zero(probs[1]) + + count2 * vp9_cost_one(probs[1]); + + if (count1 > 0) + cost += segcounts[0] * vp9_cost_zero(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]); + } -// 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]); - } + 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]); + + if (count1 > 0) + cost += segcounts[4] * vp9_cost_zero(probs[5]) + + segcounts[5] * vp9_cost_one(probs[5]); + if (count2 > 0) + cost += segcounts[6] * vp9_cost_zero(probs[6]) + + segcounts[7] * vp9_cost_one(probs[6]); } return cost; @@ -154,7 +126,7 @@ static void count_segs(VP9_COMP *cpi, MODE_INFO *mi, int *no_pred_segcounts, 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) { VP9_COMMON *const cm = &cpi->common; MACROBLOCKD *const xd = &cpi->mb.e_mbd; @@ -184,7 +156,7 @@ static void count_segs(VP9_COMP *cpi, if (!seg_predicted) // 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 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 t_pred_tree[MB_FEATURE_TREE_PROBS]; + vp9_prob no_pred_tree[MB_SEG_TREE_PROBS]; + vp9_prob t_pred_tree[MB_SEG_TREE_PROBS]; vp9_prob t_nopred_prob[PREDICTION_PROBS]; 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) { // Work out probability tree for coding those segments not // predicted using the temporal method and the cost. - calc_segtree_probs_pred(xd, t_unpred_seg_counts, t_pred_tree); - t_pred_cost = cost_segmap_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(xd, t_unpred_seg_counts, t_pred_tree); // Add in the cost of the signalling for each prediction context for (i = 0; i < PREDICTION_PROBS; i++) { -- cgit v1.2.3