Commit 31ee193a authored by Paul Wilkins's avatar Paul Wilkins

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
parent c77aff12
......@@ -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];
......
......@@ -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;
......
......@@ -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);
......
......@@ -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,
......
......@@ -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;
......
......@@ -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);
......
......@@ -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 &&
......
......@@ -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
......
......@@ -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++) {
......
......@@ -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 int rows; /**< number of rows */
unsigned int cols; /**< number of cols */
int delta_q[4]; /**< quantizer delta [-63, 63] off baseline for regions with id between 0 and 3*/
int delta_lf[4]; /**< loop filter strength delta [-63, 63] for regions with id between 0 and 3 */
unsigned int static_threshold[4];/**< threshold for region to be treated as static */
// TODO(paulwilkins): broken for VP9 which has 8 segments
// q and loop filter deltas for each segment
// (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;
/*!\brief vpx active region map
......
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