From: Ronald S. Bultje Date: Tue, 13 Oct 2015 18:06:28 +0000 (-0400) Subject: vp10: make segmentation probs use generic probability model. X-Git-Tag: v1.5.0~28^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6e5a1165bef829b3fcc73c36e5c950592b5c6801;p=libvpx vp10: make segmentation probs use generic probability model. Locate them (code-wise) in frame_context, and have them be updated as any other probability using the subexp forward and adaptive bw updates. See issue 1040 point 1. TODOs: - real-world default probabilities - why is counts sometimes NULL in the decoder? Does that mean bw adaptivity updates only work on some frames? (I haven't looked very closely yet, maybe this is a red herring.) Change-Id: I23b57b4e5e7574b75f16eb64823b29c22fbab42e --- diff --git a/vp10/common/entropymode.c b/vp10/common/entropymode.c index 370e1c287..5a729f0b2 100644 --- a/vp10/common/entropymode.c +++ b/vp10/common/entropymode.c @@ -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) { diff --git a/vp10/common/entropymode.h b/vp10/common/entropymode.h index 098126331..c5e3bc771 100644 --- a/vp10/common/entropymode.h +++ b/vp10/common/entropymode.h @@ -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]; diff --git a/vp10/common/onyxc_int.h b/vp10/common/onyxc_int.h index 73157b88d..4a20bb589 100644 --- a/vp10/common/onyxc_int.h +++ b/vp10/common/onyxc_int.h @@ -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. diff --git a/vp10/common/pred_common.h b/vp10/common/pred_common.h index 1b55f5384..d6d7146d7 100644 --- a/vp10/common/pred_common.h +++ b/vp10/common/pred_common.h @@ -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) { diff --git a/vp10/common/seg_common.h b/vp10/common/seg_common.h index 97b875c9c..cd38e8ee0 100644 --- a/vp10/common/seg_common.h +++ b/vp10/common/seg_common.h @@ -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) { diff --git a/vp10/common/thread_common.c b/vp10/common/thread_common.c index bbc6d115d..e83cb8e67 100644 --- a/vp10/common/thread_common.c +++ b/vp10/common/thread_common.c @@ -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 } diff --git a/vp10/decoder/decodeframe.c b/vp10/decoder/decodeframe.c index cbc70abfa..1e1bba875 100644 --- a/vp10/decoder/decodeframe.c +++ b/vp10/decoder/decodeframe.c @@ -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; diff --git a/vp10/decoder/decodemv.c b/vp10/decoder/decodemv.c index e82ddd697..90a98b40f 100644 --- a/vp10/decoder/decodemv.c +++ b/vp10/decoder/decodemv.c @@ -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; diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c index ca9b17b80..7dd8e4a34 100644 --- a/vp10/encoder/bitstream.c +++ b/vp10/encoder/bitstream.c @@ -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; diff --git a/vp10/encoder/encoder.c b/vp10/encoder/encoder.c index f3d7877cf..3c7c19347 100644 --- a/vp10/encoder/encoder.c +++ b/vp10/encoder/encoder.c @@ -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) { diff --git a/vp10/encoder/encoder.h b/vp10/encoder/encoder.h index a957b6382..98ded30d1 100644 --- a/vp10/encoder/encoder.h +++ b/vp10/encoder/encoder.h @@ -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; diff --git a/vp10/encoder/segmentation.c b/vp10/encoder/segmentation.c index e5d827bab..6a20ee47d 100644 --- a/vp10/encoder/segmentation.c +++ b/vp10/encoder/segmentation.c @@ -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]; - - 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); + 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(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); } diff --git a/vp10/encoder/segmentation.h b/vp10/encoder/segmentation.h index 91a9937f5..b8e6c06c6 100644 --- a/vp10/encoder/segmentation.h +++ b/vp10/encoder/segmentation.h @@ -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"