Merge "Extension of segmentation to 8 segments." into experimental
This commit is contained in:
Коммит
6579720e6a
|
@ -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]);
|
||||
// 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 (count2 > 0)
|
||||
cost += segcounts[2] * vp9_cost_zero(probs[2]) +
|
||||
segcounts[3] * vp9_cost_one(probs[2]);
|
||||
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]);
|
||||
}
|
||||
|
||||
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
|
||||
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]);
|
||||
}
|
||||
|
||||
// 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 (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++) {
|
||||
|
|
10
vpx/vp8cx.h
10
vpx/vp8cx.h
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче