Merge "vp10: make segmentation probs use generic probability model."
This commit is contained in:
commit
24517b9635
@ -746,6 +746,14 @@ static const vpx_prob default_switchable_interp_prob[SWITCHABLE_FILTER_CONTEXTS]
|
||||
{ 149, 144, },
|
||||
};
|
||||
|
||||
#if CONFIG_MISC_FIXES
|
||||
// FIXME(someone) need real defaults here
|
||||
static const struct segmentation_probs default_seg_probs = {
|
||||
{ 128, 128, 128, 128, 128, 128, 128 },
|
||||
{ 128, 128, 128 },
|
||||
};
|
||||
#endif
|
||||
|
||||
static void init_mode_probs(FRAME_CONTEXT *fc) {
|
||||
vp10_copy(fc->uv_mode_prob, default_if_uv_probs);
|
||||
vp10_copy(fc->y_mode_prob, default_if_y_probs);
|
||||
@ -758,6 +766,10 @@ static void init_mode_probs(FRAME_CONTEXT *fc) {
|
||||
fc->tx_probs = default_tx_probs;
|
||||
vp10_copy(fc->skip_probs, default_skip_probs);
|
||||
vp10_copy(fc->inter_mode_probs, default_inter_mode_probs);
|
||||
#if CONFIG_MISC_FIXES
|
||||
vp10_copy(fc->seg.tree_probs, default_seg_probs.tree_probs);
|
||||
vp10_copy(fc->seg.pred_probs, default_seg_probs.pred_probs);
|
||||
#endif
|
||||
}
|
||||
|
||||
const vpx_tree_index vp10_switchable_interp_tree
|
||||
@ -844,6 +856,20 @@ void vp10_adapt_intra_frame_probs(VP10_COMMON *cm) {
|
||||
for (i = 0; i < SKIP_CONTEXTS; ++i)
|
||||
fc->skip_probs[i] = mode_mv_merge_probs(
|
||||
pre_fc->skip_probs[i], counts->skip[i]);
|
||||
|
||||
#if CONFIG_MISC_FIXES
|
||||
if (cm->seg.temporal_update) {
|
||||
for (i = 0; i < INTRA_INTER_CONTEXTS; i++)
|
||||
fc->seg.pred_probs[i] = mode_mv_merge_probs(pre_fc->seg.pred_probs[i],
|
||||
counts->seg.pred[i]);
|
||||
|
||||
vpx_tree_merge_probs(vp10_segment_tree, pre_fc->seg.tree_probs,
|
||||
counts->seg.tree_mispred, fc->seg.tree_probs);
|
||||
} else {
|
||||
vpx_tree_merge_probs(vp10_segment_tree, pre_fc->seg.tree_probs,
|
||||
counts->seg.tree_total, fc->seg.tree_probs);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void set_default_lf_deltas(struct loopfilter *lf) {
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "vp10/common/entropy.h"
|
||||
#include "vp10/common/entropymv.h"
|
||||
#include "vp10/common/filter.h"
|
||||
#include "vp10/common/seg_common.h"
|
||||
#include "vpx_dsp/vpx_filter.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -47,6 +48,12 @@ struct tx_counts {
|
||||
unsigned int tx_totals[TX_SIZES];
|
||||
};
|
||||
|
||||
struct seg_counts {
|
||||
unsigned int tree_total[MAX_SEGMENTS];
|
||||
unsigned int tree_mispred[MAX_SEGMENTS];
|
||||
unsigned int pred[PREDICTION_PROBS][2];
|
||||
};
|
||||
|
||||
typedef struct frame_contexts {
|
||||
vpx_prob y_mode_prob[BLOCK_SIZE_GROUPS][INTRA_MODES - 1];
|
||||
vpx_prob uv_mode_prob[INTRA_MODES][INTRA_MODES - 1];
|
||||
@ -62,6 +69,9 @@ typedef struct frame_contexts {
|
||||
struct tx_probs tx_probs;
|
||||
vpx_prob skip_probs[SKIP_CONTEXTS];
|
||||
nmv_context nmvc;
|
||||
#if CONFIG_MISC_FIXES
|
||||
struct segmentation_probs seg;
|
||||
#endif
|
||||
int initialized;
|
||||
} FRAME_CONTEXT;
|
||||
|
||||
@ -82,6 +92,9 @@ typedef struct FRAME_COUNTS {
|
||||
struct tx_counts tx;
|
||||
unsigned int skip[SKIP_CONTEXTS][2];
|
||||
nmv_context_counts mv;
|
||||
#if CONFIG_MISC_FIXES
|
||||
struct seg_counts seg;
|
||||
#endif
|
||||
} FRAME_COUNTS;
|
||||
|
||||
extern const vpx_prob vp10_kf_uv_mode_prob[INTRA_MODES][INTRA_MODES - 1];
|
||||
|
@ -254,6 +254,9 @@ typedef struct VP10Common {
|
||||
|
||||
struct loopfilter lf;
|
||||
struct segmentation seg;
|
||||
#if !CONFIG_MISC_FIXES
|
||||
struct segmentation_probs segp;
|
||||
#endif
|
||||
|
||||
int frame_parallel_decode; // frame-based threading.
|
||||
|
||||
|
@ -48,9 +48,9 @@ static INLINE int vp10_get_pred_context_seg_id(const MACROBLOCKD *xd) {
|
||||
return above_sip + left_sip;
|
||||
}
|
||||
|
||||
static INLINE vpx_prob vp10_get_pred_prob_seg_id(const struct segmentation *seg,
|
||||
const MACROBLOCKD *xd) {
|
||||
return seg->pred_probs[vp10_get_pred_context_seg_id(xd)];
|
||||
static INLINE vpx_prob vp10_get_pred_prob_seg_id(
|
||||
const struct segmentation_probs *segp, const MACROBLOCKD *xd) {
|
||||
return segp->pred_probs[vp10_get_pred_context_seg_id(xd)];
|
||||
}
|
||||
|
||||
static INLINE int vp10_get_skip_context(const MACROBLOCKD *xd) {
|
||||
|
@ -42,13 +42,15 @@ struct segmentation {
|
||||
uint8_t abs_delta;
|
||||
uint8_t temporal_update;
|
||||
|
||||
vpx_prob tree_probs[SEG_TREE_PROBS];
|
||||
vpx_prob pred_probs[PREDICTION_PROBS];
|
||||
|
||||
int16_t feature_data[MAX_SEGMENTS][SEG_LVL_MAX];
|
||||
unsigned int feature_mask[MAX_SEGMENTS];
|
||||
};
|
||||
|
||||
struct segmentation_probs {
|
||||
vpx_prob tree_probs[SEG_TREE_PROBS];
|
||||
vpx_prob pred_probs[PREDICTION_PROBS];
|
||||
};
|
||||
|
||||
static INLINE int segfeature_active(const struct segmentation *seg,
|
||||
int segment_id,
|
||||
SEG_LVL_FEATURES feature_id) {
|
||||
|
@ -434,4 +434,15 @@ void vp10_accumulate_frame_counts(VP10_COMMON *cm, FRAME_COUNTS *counts,
|
||||
for (i = 0; i < MV_FP_SIZE; i++)
|
||||
comps->fp[i] += comps_t->fp[i];
|
||||
}
|
||||
|
||||
#if CONFIG_MISC_FIXES
|
||||
for (i = 0; i < PREDICTION_PROBS; i++)
|
||||
for (j = 0; j < 2; j++)
|
||||
cm->counts.seg.pred[i][j] += counts->seg.pred[i][j];
|
||||
|
||||
for (i = 0; i < MAX_SEGMENTS; i++) {
|
||||
cm->counts.seg.tree_total[i] += counts->seg.tree_total[i];
|
||||
cm->counts.seg.tree_mispred[i] += counts->seg.tree_mispred[i];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -1047,6 +1047,9 @@ static void read_coef_probs(FRAME_CONTEXT *fc, TX_MODE tx_mode,
|
||||
static void setup_segmentation(VP10_COMMON *const cm,
|
||||
struct vpx_read_bit_buffer *rb) {
|
||||
struct segmentation *const seg = &cm->seg;
|
||||
#if !CONFIG_MISC_FIXES
|
||||
struct segmentation_probs *const segp = &cm->segp;
|
||||
#endif
|
||||
int i, j;
|
||||
|
||||
seg->update_map = 0;
|
||||
@ -1063,23 +1066,26 @@ static void setup_segmentation(VP10_COMMON *const cm,
|
||||
seg->update_map = vpx_rb_read_bit(rb);
|
||||
}
|
||||
if (seg->update_map) {
|
||||
#if !CONFIG_MISC_FIXES
|
||||
for (i = 0; i < SEG_TREE_PROBS; i++)
|
||||
seg->tree_probs[i] = vpx_rb_read_bit(rb) ? vpx_rb_read_literal(rb, 8)
|
||||
: MAX_PROB;
|
||||
|
||||
segp->tree_probs[i] = vpx_rb_read_bit(rb) ? vpx_rb_read_literal(rb, 8)
|
||||
: MAX_PROB;
|
||||
#endif
|
||||
if (frame_is_intra_only(cm) || cm->error_resilient_mode) {
|
||||
seg->temporal_update = 0;
|
||||
} else {
|
||||
seg->temporal_update = vpx_rb_read_bit(rb);
|
||||
}
|
||||
#if !CONFIG_MISC_FIXES
|
||||
if (seg->temporal_update) {
|
||||
for (i = 0; i < PREDICTION_PROBS; i++)
|
||||
seg->pred_probs[i] = vpx_rb_read_bit(rb) ? vpx_rb_read_literal(rb, 8)
|
||||
: MAX_PROB;
|
||||
segp->pred_probs[i] = vpx_rb_read_bit(rb) ? vpx_rb_read_literal(rb, 8)
|
||||
: MAX_PROB;
|
||||
} else {
|
||||
for (i = 0; i < PREDICTION_PROBS; i++)
|
||||
seg->pred_probs[i] = MAX_PROB;
|
||||
segp->pred_probs[i] = MAX_PROB;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Segmentation data update
|
||||
@ -2131,6 +2137,17 @@ static int read_compressed_header(VP10Decoder *pbi, const uint8_t *data,
|
||||
for (k = 0; k < SKIP_CONTEXTS; ++k)
|
||||
vp10_diff_update_prob(&r, &fc->skip_probs[k]);
|
||||
|
||||
#if CONFIG_MISC_FIXES
|
||||
if (cm->seg.enabled) {
|
||||
if (cm->seg.temporal_update) {
|
||||
for (k = 0; k < PREDICTION_PROBS; k++)
|
||||
vp10_diff_update_prob(&r, &cm->fc->seg.pred_probs[k]);
|
||||
}
|
||||
for (k = 0; k < MAX_SEGMENTS - 1; k++)
|
||||
vp10_diff_update_prob(&r, &cm->fc->seg.tree_probs[k]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!frame_is_intra_only(cm)) {
|
||||
nmv_context *const nmvc = &fc->nmvc;
|
||||
int i, j;
|
||||
|
@ -73,8 +73,9 @@ static PREDICTION_MODE read_inter_mode(VP10_COMMON *cm, MACROBLOCKD *xd,
|
||||
return NEARESTMV + mode;
|
||||
}
|
||||
|
||||
static int read_segment_id(vpx_reader *r, const struct segmentation *seg) {
|
||||
return vpx_read_tree(r, vp10_segment_tree, seg->tree_probs);
|
||||
static int read_segment_id(vpx_reader *r,
|
||||
const struct segmentation_probs *segp) {
|
||||
return vpx_read_tree(r, vp10_segment_tree, segp->tree_probs);
|
||||
}
|
||||
|
||||
static TX_SIZE read_selected_tx_size(VP10_COMMON *cm, MACROBLOCKD *xd,
|
||||
@ -129,18 +130,32 @@ static void set_segment_id(VP10_COMMON *cm, int mi_offset,
|
||||
cm->current_frame_seg_map[mi_offset + y * cm->mi_cols + x] = segment_id;
|
||||
}
|
||||
|
||||
static int read_intra_segment_id(VP10_COMMON *const cm, int mi_offset,
|
||||
int x_mis, int y_mis,
|
||||
static int read_intra_segment_id(VP10_COMMON *const cm, MACROBLOCKD *const xd,
|
||||
int mi_offset, int x_mis, int y_mis,
|
||||
vpx_reader *r) {
|
||||
struct segmentation *const seg = &cm->seg;
|
||||
#if CONFIG_MISC_FIXES
|
||||
FRAME_COUNTS *counts = xd->counts;
|
||||
struct segmentation_probs *const segp = &cm->fc->seg;
|
||||
#else
|
||||
struct segmentation_probs *const segp = &cm->segp;
|
||||
#endif
|
||||
int segment_id;
|
||||
|
||||
#if !CONFIG_MISC_FIXES
|
||||
(void) xd;
|
||||
#endif
|
||||
|
||||
if (!seg->enabled)
|
||||
return 0; // Default for disabled segmentation
|
||||
|
||||
assert(seg->update_map && !seg->temporal_update);
|
||||
|
||||
segment_id = read_segment_id(r, seg);
|
||||
segment_id = read_segment_id(r, segp);
|
||||
#if CONFIG_MISC_FIXES
|
||||
if (counts)
|
||||
++counts->seg.tree_total[segment_id];
|
||||
#endif
|
||||
set_segment_id(cm, mi_offset, x_mis, y_mis, segment_id);
|
||||
return segment_id;
|
||||
}
|
||||
@ -160,6 +175,12 @@ static void copy_segment_id(const VP10_COMMON *cm,
|
||||
static int read_inter_segment_id(VP10_COMMON *const cm, MACROBLOCKD *const xd,
|
||||
int mi_row, int mi_col, vpx_reader *r) {
|
||||
struct segmentation *const seg = &cm->seg;
|
||||
#if CONFIG_MISC_FIXES
|
||||
FRAME_COUNTS *counts = xd->counts;
|
||||
struct segmentation_probs *const segp = &cm->fc->seg;
|
||||
#else
|
||||
struct segmentation_probs *const segp = &cm->segp;
|
||||
#endif
|
||||
MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
|
||||
int predicted_segment_id, segment_id;
|
||||
const int mi_offset = mi_row * cm->mi_cols + mi_col;
|
||||
@ -184,12 +205,28 @@ static int read_inter_segment_id(VP10_COMMON *const cm, MACROBLOCKD *const xd,
|
||||
}
|
||||
|
||||
if (seg->temporal_update) {
|
||||
const vpx_prob pred_prob = vp10_get_pred_prob_seg_id(seg, xd);
|
||||
const int ctx = vp10_get_pred_context_seg_id(xd);
|
||||
const vpx_prob pred_prob = segp->pred_probs[ctx];
|
||||
mbmi->seg_id_predicted = vpx_read(r, pred_prob);
|
||||
segment_id = mbmi->seg_id_predicted ? predicted_segment_id
|
||||
: read_segment_id(r, seg);
|
||||
#if CONFIG_MISC_FIXES
|
||||
if (counts)
|
||||
++counts->seg.pred[ctx][mbmi->seg_id_predicted];
|
||||
#endif
|
||||
if (mbmi->seg_id_predicted) {
|
||||
segment_id = predicted_segment_id;
|
||||
} else {
|
||||
segment_id = read_segment_id(r, segp);
|
||||
#if CONFIG_MISC_FIXES
|
||||
if (counts)
|
||||
++counts->seg.tree_mispred[segment_id];
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
segment_id = read_segment_id(r, seg);
|
||||
segment_id = read_segment_id(r, segp);
|
||||
#if CONFIG_MISC_FIXES
|
||||
if (counts)
|
||||
++counts->seg.tree_total[segment_id];
|
||||
#endif
|
||||
}
|
||||
set_segment_id(cm, mi_offset, x_mis, y_mis, segment_id);
|
||||
return segment_id;
|
||||
@ -258,7 +295,7 @@ static void read_intra_frame_mode_info(VP10_COMMON *const cm,
|
||||
const int x_mis = VPXMIN(cm->mi_cols - mi_col, bw);
|
||||
const int y_mis = VPXMIN(cm->mi_rows - mi_row, bh);
|
||||
|
||||
mbmi->segment_id = read_intra_segment_id(cm, mi_offset, x_mis, y_mis, r);
|
||||
mbmi->segment_id = read_intra_segment_id(cm, xd, mi_offset, x_mis, y_mis, r);
|
||||
mbmi->skip = read_skip(cm, xd, mbmi->segment_id, r);
|
||||
mbmi->tx_size = read_tx_size(cm, xd, 1, r);
|
||||
mbmi->ref_frame[0] = INTRA_FRAME;
|
||||
|
@ -251,9 +251,10 @@ static void pack_mb_tokens(vpx_writer *w,
|
||||
}
|
||||
|
||||
static void write_segment_id(vpx_writer *w, const struct segmentation *seg,
|
||||
const struct segmentation_probs *segp,
|
||||
int segment_id) {
|
||||
if (seg->enabled && seg->update_map)
|
||||
vp10_write_tree(w, vp10_segment_tree, seg->tree_probs, segment_id, 3, 0);
|
||||
vp10_write_tree(w, vp10_segment_tree, segp->tree_probs, segment_id, 3, 0);
|
||||
}
|
||||
|
||||
// This function encodes the reference frame
|
||||
@ -299,6 +300,11 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi,
|
||||
const MACROBLOCK *const x = &cpi->td.mb;
|
||||
const MACROBLOCKD *const xd = &x->e_mbd;
|
||||
const struct segmentation *const seg = &cm->seg;
|
||||
#if CONFIG_MISC_FIXES
|
||||
const struct segmentation_probs *const segp = &cm->fc->seg;
|
||||
#else
|
||||
const struct segmentation_probs *const segp = &cm->segp;
|
||||
#endif
|
||||
const MB_MODE_INFO *const mbmi = &mi->mbmi;
|
||||
const MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
|
||||
const PREDICTION_MODE mode = mbmi->mode;
|
||||
@ -312,12 +318,12 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi,
|
||||
if (seg->update_map) {
|
||||
if (seg->temporal_update) {
|
||||
const int pred_flag = mbmi->seg_id_predicted;
|
||||
vpx_prob pred_prob = vp10_get_pred_prob_seg_id(seg, xd);
|
||||
vpx_prob pred_prob = vp10_get_pred_prob_seg_id(segp, xd);
|
||||
vpx_write(w, pred_flag, pred_prob);
|
||||
if (!pred_flag)
|
||||
write_segment_id(w, seg, segment_id);
|
||||
write_segment_id(w, seg, segp, segment_id);
|
||||
} else {
|
||||
write_segment_id(w, seg, segment_id);
|
||||
write_segment_id(w, seg, segp, segment_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -429,6 +435,11 @@ static void write_palette_mode_info(const VP10_COMMON *cm,
|
||||
static void write_mb_modes_kf(const VP10_COMMON *cm, const MACROBLOCKD *xd,
|
||||
MODE_INFO **mi_8x8, vpx_writer *w) {
|
||||
const struct segmentation *const seg = &cm->seg;
|
||||
#if CONFIG_MISC_FIXES
|
||||
const struct segmentation_probs *const segp = &cm->fc->seg;
|
||||
#else
|
||||
const struct segmentation_probs *const segp = &cm->segp;
|
||||
#endif
|
||||
const MODE_INFO *const mi = mi_8x8[0];
|
||||
const MODE_INFO *const above_mi = xd->above_mi;
|
||||
const MODE_INFO *const left_mi = xd->left_mi;
|
||||
@ -436,7 +447,7 @@ static void write_mb_modes_kf(const VP10_COMMON *cm, const MACROBLOCKD *xd,
|
||||
const BLOCK_SIZE bsize = mbmi->sb_type;
|
||||
|
||||
if (seg->update_map)
|
||||
write_segment_id(w, seg, mbmi->segment_id);
|
||||
write_segment_id(w, seg, segp, mbmi->segment_id);
|
||||
|
||||
write_skip(cm, xd, mbmi->segment_id, mi, w);
|
||||
|
||||
@ -859,6 +870,9 @@ static void encode_segmentation(VP10_COMMON *cm, MACROBLOCKD *xd,
|
||||
int i, j;
|
||||
|
||||
const struct segmentation *seg = &cm->seg;
|
||||
#if !CONFIG_MISC_FIXES
|
||||
const struct segmentation_probs *segp = &cm->segp;
|
||||
#endif
|
||||
|
||||
vpx_wb_write_bit(wb, seg->enabled);
|
||||
if (!seg->enabled)
|
||||
@ -873,14 +887,16 @@ static void encode_segmentation(VP10_COMMON *cm, MACROBLOCKD *xd,
|
||||
if (seg->update_map) {
|
||||
// Select the coding strategy (temporal or spatial)
|
||||
vp10_choose_segmap_coding_method(cm, xd);
|
||||
#if !CONFIG_MISC_FIXES
|
||||
// Write out probabilities used to decode unpredicted macro-block segments
|
||||
for (i = 0; i < SEG_TREE_PROBS; i++) {
|
||||
const int prob = seg->tree_probs[i];
|
||||
const int prob = segp->tree_probs[i];
|
||||
const int update = prob != MAX_PROB;
|
||||
vpx_wb_write_bit(wb, update);
|
||||
if (update)
|
||||
vpx_wb_write_literal(wb, prob, 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Write out the chosen coding method.
|
||||
if (!frame_is_intra_only(cm) && !cm->error_resilient_mode) {
|
||||
@ -888,15 +904,18 @@ static void encode_segmentation(VP10_COMMON *cm, MACROBLOCKD *xd,
|
||||
} else {
|
||||
assert(seg->temporal_update == 0);
|
||||
}
|
||||
|
||||
#if !CONFIG_MISC_FIXES
|
||||
if (seg->temporal_update) {
|
||||
for (i = 0; i < PREDICTION_PROBS; i++) {
|
||||
const int prob = seg->pred_probs[i];
|
||||
const int prob = segp->pred_probs[i];
|
||||
const int update = prob != MAX_PROB;
|
||||
vpx_wb_write_bit(wb, update);
|
||||
if (update)
|
||||
vpx_wb_write_literal(wb, prob, 8);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Segmentation data
|
||||
@ -925,6 +944,27 @@ static void encode_segmentation(VP10_COMMON *cm, MACROBLOCKD *xd,
|
||||
}
|
||||
|
||||
#if CONFIG_MISC_FIXES
|
||||
static void update_seg_probs(VP10_COMP *cpi, vpx_writer *w) {
|
||||
VP10_COMMON *cm = &cpi->common;
|
||||
|
||||
if (!cpi->common.seg.enabled)
|
||||
return;
|
||||
|
||||
if (cpi->common.seg.temporal_update) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PREDICTION_PROBS; i++)
|
||||
vp10_cond_prob_diff_update(w, &cm->fc->seg.pred_probs[i],
|
||||
cm->counts.seg.pred[i]);
|
||||
|
||||
prob_diff_update(vp10_segment_tree, cm->fc->seg.tree_probs,
|
||||
cm->counts.seg.tree_mispred, MAX_SEGMENTS, w);
|
||||
} else {
|
||||
prob_diff_update(vp10_segment_tree, cm->fc->seg.tree_probs,
|
||||
cm->counts.seg.tree_total, MAX_SEGMENTS, w);
|
||||
}
|
||||
}
|
||||
|
||||
static void write_txfm_mode(TX_MODE mode, struct vpx_write_bit_buffer *wb) {
|
||||
vpx_wb_write_bit(wb, mode == TX_MODE_SELECT);
|
||||
if (mode != TX_MODE_SELECT)
|
||||
@ -1323,6 +1363,9 @@ static size_t write_compressed_header(VP10_COMP *cpi, uint8_t *data) {
|
||||
#endif
|
||||
update_coef_probs(cpi, &header_bc);
|
||||
update_skip_probs(cm, &header_bc, counts);
|
||||
#if CONFIG_MISC_FIXES
|
||||
update_seg_probs(cpi, &header_bc);
|
||||
#endif
|
||||
|
||||
if (!frame_is_intra_only(cm)) {
|
||||
int i;
|
||||
|
@ -418,7 +418,9 @@ static void save_coding_context(VP10_COMP *cpi) {
|
||||
memcpy(cc->nmvcosts_hp[1], cpi->nmvcosts_hp[1],
|
||||
MV_VALS * sizeof(*cpi->nmvcosts_hp[1]));
|
||||
|
||||
vp10_copy(cc->segment_pred_probs, cm->seg.pred_probs);
|
||||
#if !CONFIG_MISC_FIXES
|
||||
vp10_copy(cc->segment_pred_probs, cm->segp.pred_probs);
|
||||
#endif
|
||||
|
||||
memcpy(cpi->coding_context.last_frame_seg_map_copy,
|
||||
cm->last_frame_seg_map, (cm->mi_rows * cm->mi_cols));
|
||||
@ -444,7 +446,9 @@ static void restore_coding_context(VP10_COMP *cpi) {
|
||||
memcpy(cpi->nmvcosts_hp[1], cc->nmvcosts_hp[1],
|
||||
MV_VALS * sizeof(*cc->nmvcosts_hp[1]));
|
||||
|
||||
vp10_copy(cm->seg.pred_probs, cc->segment_pred_probs);
|
||||
#if !CONFIG_MISC_FIXES
|
||||
vp10_copy(cm->segp.pred_probs, cc->segment_pred_probs);
|
||||
#endif
|
||||
|
||||
memcpy(cm->last_frame_seg_map,
|
||||
cpi->coding_context.last_frame_seg_map_copy,
|
||||
@ -1440,7 +1444,7 @@ void vp10_change_config(struct VP10_COMP *cpi, const VP10EncoderConfig *oxcf) {
|
||||
}
|
||||
}
|
||||
|
||||
vp10_reset_segment_features(&cm->seg);
|
||||
vp10_reset_segment_features(cm);
|
||||
vp10_set_high_precision_mv(cpi, 0);
|
||||
|
||||
{
|
||||
@ -3561,7 +3565,7 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi,
|
||||
// Set various flags etc to special state if it is a key frame.
|
||||
if (frame_is_intra_only(cm)) {
|
||||
// Reset the loop filter deltas and segmentation map.
|
||||
vp10_reset_segment_features(&cm->seg);
|
||||
vp10_reset_segment_features(cm);
|
||||
|
||||
// If segmentation is enabled force a map update for key frames.
|
||||
if (seg->enabled) {
|
||||
|
@ -55,7 +55,9 @@ typedef struct {
|
||||
int nmvcosts[2][MV_VALS];
|
||||
int nmvcosts_hp[2][MV_VALS];
|
||||
|
||||
#if !CONFIG_MISC_FIXES
|
||||
vpx_prob segment_pred_probs[PREDICTION_PROBS];
|
||||
#endif
|
||||
|
||||
unsigned char *last_frame_seg_map_copy;
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "vp10/encoder/cost.h"
|
||||
#include "vp10/encoder/segmentation.h"
|
||||
#include "vp10/encoder/subexp.h"
|
||||
|
||||
void vp10_enable_segmentation(struct segmentation *seg) {
|
||||
seg->enabled = 1;
|
||||
@ -49,24 +50,40 @@ void vp10_clear_segdata(struct segmentation *seg, int segment_id,
|
||||
}
|
||||
|
||||
// Based on set of segment counts calculate a probability tree
|
||||
static void calc_segtree_probs(int *segcounts, vpx_prob *segment_tree_probs) {
|
||||
static void calc_segtree_probs(unsigned *segcounts,
|
||||
vpx_prob *segment_tree_probs, const vpx_prob *cur_tree_probs) {
|
||||
// Work out probabilities of each segment
|
||||
const int c01 = segcounts[0] + segcounts[1];
|
||||
const int c23 = segcounts[2] + segcounts[3];
|
||||
const int c45 = segcounts[4] + segcounts[5];
|
||||
const int c67 = segcounts[6] + segcounts[7];
|
||||
const unsigned cc[4] = {
|
||||
segcounts[0] + segcounts[1], segcounts[2] + segcounts[3],
|
||||
segcounts[4] + segcounts[5], segcounts[6] + segcounts[7]
|
||||
};
|
||||
const unsigned ccc[2] = { cc[0] + cc[1], cc[2] + cc[3] };
|
||||
#if CONFIG_MISC_FIXES
|
||||
int i;
|
||||
#endif
|
||||
|
||||
segment_tree_probs[0] = get_binary_prob(c01 + c23, c45 + c67);
|
||||
segment_tree_probs[1] = get_binary_prob(c01, c23);
|
||||
segment_tree_probs[2] = get_binary_prob(c45, c67);
|
||||
segment_tree_probs[0] = get_binary_prob(ccc[0], ccc[1]);
|
||||
segment_tree_probs[1] = get_binary_prob(cc[0], cc[1]);
|
||||
segment_tree_probs[2] = get_binary_prob(cc[2], cc[3]);
|
||||
segment_tree_probs[3] = get_binary_prob(segcounts[0], segcounts[1]);
|
||||
segment_tree_probs[4] = get_binary_prob(segcounts[2], segcounts[3]);
|
||||
segment_tree_probs[5] = get_binary_prob(segcounts[4], segcounts[5]);
|
||||
segment_tree_probs[6] = get_binary_prob(segcounts[6], segcounts[7]);
|
||||
|
||||
#if CONFIG_MISC_FIXES
|
||||
for (i = 0; i < 7; i++) {
|
||||
const unsigned *ct = i == 0 ? ccc : i < 3 ? cc + (i & 2)
|
||||
: segcounts + (i - 3) * 2;
|
||||
vp10_prob_diff_update_savings_search(ct,
|
||||
cur_tree_probs[i], &segment_tree_probs[i], DIFF_UPDATE_PROB);
|
||||
}
|
||||
#else
|
||||
(void) cur_tree_probs;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Based on set of segment counts and probabilities calculate a cost estimate
|
||||
static int cost_segmap(int *segcounts, vpx_prob *probs) {
|
||||
static int cost_segmap(unsigned *segcounts, vpx_prob *probs) {
|
||||
const int c01 = segcounts[0] + segcounts[1];
|
||||
const int c23 = segcounts[2] + segcounts[3];
|
||||
const int c45 = segcounts[4] + segcounts[5];
|
||||
@ -108,9 +125,9 @@ static int cost_segmap(int *segcounts, vpx_prob *probs) {
|
||||
|
||||
static void count_segs(const VP10_COMMON *cm, MACROBLOCKD *xd,
|
||||
const TileInfo *tile, MODE_INFO **mi,
|
||||
int *no_pred_segcounts,
|
||||
int (*temporal_predictor_count)[2],
|
||||
int *t_unpred_seg_counts,
|
||||
unsigned *no_pred_segcounts,
|
||||
unsigned (*temporal_predictor_count)[2],
|
||||
unsigned *t_unpred_seg_counts,
|
||||
int bw, int bh, int mi_row, int mi_col) {
|
||||
int segment_id;
|
||||
|
||||
@ -147,9 +164,9 @@ static void count_segs(const VP10_COMMON *cm, MACROBLOCKD *xd,
|
||||
|
||||
static void count_segs_sb(const VP10_COMMON *cm, MACROBLOCKD *xd,
|
||||
const TileInfo *tile, MODE_INFO **mi,
|
||||
int *no_pred_segcounts,
|
||||
int (*temporal_predictor_count)[2],
|
||||
int *t_unpred_seg_counts,
|
||||
unsigned *no_pred_segcounts,
|
||||
unsigned (*temporal_predictor_count)[2],
|
||||
unsigned *t_unpred_seg_counts,
|
||||
int mi_row, int mi_col,
|
||||
BLOCK_SIZE bsize) {
|
||||
const int mis = cm->mi_stride;
|
||||
@ -197,24 +214,39 @@ static void count_segs_sb(const VP10_COMMON *cm, MACROBLOCKD *xd,
|
||||
|
||||
void vp10_choose_segmap_coding_method(VP10_COMMON *cm, MACROBLOCKD *xd) {
|
||||
struct segmentation *seg = &cm->seg;
|
||||
#if CONFIG_MISC_FIXES
|
||||
struct segmentation_probs *segp = &cm->fc->seg;
|
||||
#else
|
||||
struct segmentation_probs *segp = &cm->segp;
|
||||
#endif
|
||||
|
||||
int no_pred_cost;
|
||||
int t_pred_cost = INT_MAX;
|
||||
|
||||
int i, tile_col, mi_row, mi_col;
|
||||
|
||||
int temporal_predictor_count[PREDICTION_PROBS][2] = { { 0 } };
|
||||
int no_pred_segcounts[MAX_SEGMENTS] = { 0 };
|
||||
int t_unpred_seg_counts[MAX_SEGMENTS] = { 0 };
|
||||
#if CONFIG_MISC_FIXES
|
||||
unsigned (*temporal_predictor_count)[2] = cm->counts.seg.pred;
|
||||
unsigned *no_pred_segcounts = cm->counts.seg.tree_total;
|
||||
unsigned *t_unpred_seg_counts = cm->counts.seg.tree_mispred;
|
||||
#else
|
||||
unsigned temporal_predictor_count[PREDICTION_PROBS][2] = { { 0 } };
|
||||
unsigned no_pred_segcounts[MAX_SEGMENTS] = { 0 };
|
||||
unsigned t_unpred_seg_counts[MAX_SEGMENTS] = { 0 };
|
||||
#endif
|
||||
|
||||
vpx_prob no_pred_tree[SEG_TREE_PROBS];
|
||||
vpx_prob t_pred_tree[SEG_TREE_PROBS];
|
||||
vpx_prob t_nopred_prob[PREDICTION_PROBS];
|
||||
|
||||
#if CONFIG_MISC_FIXES
|
||||
(void) xd;
|
||||
#else
|
||||
// Set default state for the segment tree probabilities and the
|
||||
// temporal coding probabilities
|
||||
memset(seg->tree_probs, 255, sizeof(seg->tree_probs));
|
||||
memset(seg->pred_probs, 255, sizeof(seg->pred_probs));
|
||||
memset(segp->tree_probs, 255, sizeof(segp->tree_probs));
|
||||
memset(segp->pred_probs, 255, sizeof(segp->pred_probs));
|
||||
#endif
|
||||
|
||||
// First of all generate stats regarding how well the last segment map
|
||||
// predicts this one
|
||||
@ -237,14 +269,14 @@ void vp10_choose_segmap_coding_method(VP10_COMMON *cm, MACROBLOCKD *xd) {
|
||||
|
||||
// Work out probability tree for coding segments without prediction
|
||||
// and the cost.
|
||||
calc_segtree_probs(no_pred_segcounts, no_pred_tree);
|
||||
calc_segtree_probs(no_pred_segcounts, no_pred_tree, segp->tree_probs);
|
||||
no_pred_cost = cost_segmap(no_pred_segcounts, no_pred_tree);
|
||||
|
||||
// Key frames cannot use temporal prediction
|
||||
if (!frame_is_intra_only(cm)) {
|
||||
// Work out probability tree for coding those segments not
|
||||
// predicted using the temporal method and the cost.
|
||||
calc_segtree_probs(t_unpred_seg_counts, t_pred_tree);
|
||||
calc_segtree_probs(t_unpred_seg_counts, t_pred_tree, segp->tree_probs);
|
||||
t_pred_cost = cost_segmap(t_unpred_seg_counts, t_pred_tree);
|
||||
|
||||
// Add in the cost of the signaling for each prediction context.
|
||||
@ -252,7 +284,13 @@ void vp10_choose_segmap_coding_method(VP10_COMMON *cm, MACROBLOCKD *xd) {
|
||||
const int count0 = temporal_predictor_count[i][0];
|
||||
const int count1 = temporal_predictor_count[i][1];
|
||||
|
||||
#if CONFIG_MISC_FIXES
|
||||
vp10_prob_diff_update_savings_search(temporal_predictor_count[i],
|
||||
segp->pred_probs[i],
|
||||
&t_nopred_prob[i], DIFF_UPDATE_PROB);
|
||||
#else
|
||||
t_nopred_prob[i] = get_binary_prob(count0, count1);
|
||||
#endif
|
||||
|
||||
// Add in the predictor signaling cost
|
||||
t_pred_cost += count0 * vp10_cost_zero(t_nopred_prob[i]) +
|
||||
@ -263,19 +301,30 @@ void vp10_choose_segmap_coding_method(VP10_COMMON *cm, MACROBLOCKD *xd) {
|
||||
// Now choose which coding method to use.
|
||||
if (t_pred_cost < no_pred_cost) {
|
||||
seg->temporal_update = 1;
|
||||
memcpy(seg->tree_probs, t_pred_tree, sizeof(t_pred_tree));
|
||||
memcpy(seg->pred_probs, t_nopred_prob, sizeof(t_nopred_prob));
|
||||
#if !CONFIG_MISC_FIXES
|
||||
memcpy(segp->tree_probs, t_pred_tree, sizeof(t_pred_tree));
|
||||
memcpy(segp->pred_probs, t_nopred_prob, sizeof(t_nopred_prob));
|
||||
#endif
|
||||
} else {
|
||||
seg->temporal_update = 0;
|
||||
memcpy(seg->tree_probs, no_pred_tree, sizeof(no_pred_tree));
|
||||
#if !CONFIG_MISC_FIXES
|
||||
memcpy(segp->tree_probs, no_pred_tree, sizeof(no_pred_tree));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void vp10_reset_segment_features(struct segmentation *seg) {
|
||||
void vp10_reset_segment_features(VP10_COMMON *cm) {
|
||||
struct segmentation *seg = &cm->seg;
|
||||
#if !CONFIG_MISC_FIXES
|
||||
struct segmentation_probs *segp = &cm->segp;
|
||||
#endif
|
||||
|
||||
// Set up default state for MB feature flags
|
||||
seg->enabled = 0;
|
||||
seg->update_map = 0;
|
||||
seg->update_data = 0;
|
||||
memset(seg->tree_probs, 255, sizeof(seg->tree_probs));
|
||||
#if !CONFIG_MISC_FIXES
|
||||
memset(segp->tree_probs, 255, sizeof(segp->tree_probs));
|
||||
#endif
|
||||
vp10_clearall_segfeatures(seg);
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ void vp10_set_segment_data(struct segmentation *seg, signed char *feature_data,
|
||||
|
||||
void vp10_choose_segmap_coding_method(VP10_COMMON *cm, MACROBLOCKD *xd);
|
||||
|
||||
void vp10_reset_segment_features(struct segmentation *seg);
|
||||
void vp10_reset_segment_features(VP10_COMMON *cm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
Loading…
x
Reference in New Issue
Block a user