shithub: libvpx

Download patch

ref: 6e5a1165bef829b3fcc73c36e5c950592b5c6801
parent: 7dd7a7da206bddb7d3d3deffa23984719bb89d87
author: Ronald S. Bultje <[email protected]>
date: Tue Oct 13 10:06:28 EDT 2015

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

--- a/vp10/common/entropymode.c
+++ b/vp10/common/entropymode.c
@@ -746,6 +746,14 @@
   { 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 @@
   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 @@
   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) {
--- 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 @@
   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 @@
   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 @@
   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];
--- a/vp10/common/onyxc_int.h
+++ b/vp10/common/onyxc_int.h
@@ -254,6 +254,9 @@
 
   struct loopfilter lf;
   struct segmentation seg;
+#if !CONFIG_MISC_FIXES
+  struct segmentation_probs segp;
+#endif
 
   int frame_parallel_decode;  // frame-based threading.
 
--- a/vp10/common/pred_common.h
+++ b/vp10/common/pred_common.h
@@ -48,9 +48,9 @@
   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) {
--- a/vp10/common/seg_common.h
+++ b/vp10/common/seg_common.h
@@ -42,11 +42,13 @@
   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,
--- a/vp10/common/thread_common.c
+++ b/vp10/common/thread_common.c
@@ -434,4 +434,15 @@
     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
 }
--- a/vp10/decoder/decodeframe.c
+++ b/vp10/decoder/decodeframe.c
@@ -1047,6 +1047,9 @@
 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 @@
     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
@@ -2130,6 +2136,17 @@
 
   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;
--- a/vp10/decoder/decodemv.c
+++ b/vp10/decoder/decodemv.c
@@ -73,8 +73,9 @@
   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 @@
       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 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 @@
   }
 
   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 @@
   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;
--- a/vp10/encoder/bitstream.c
+++ b/vp10/encoder/bitstream.c
@@ -251,9 +251,10 @@
 }
 
 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 @@
   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 @@
   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_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 @@
   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 @@
   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 @@
   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,9 +904,11 @@
     } 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)
@@ -897,6 +915,7 @@
           vpx_wb_write_literal(wb, prob, 8);
       }
     }
+#endif
   }
 
   // Segmentation data
@@ -925,6 +944,27 @@
 }
 
 #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 @@
 #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;
--- a/vp10/encoder/encoder.c
+++ b/vp10/encoder/encoder.c
@@ -418,7 +418,9 @@
   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 @@
   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 @@
     }
   }
 
-  vp10_reset_segment_features(&cm->seg);
+  vp10_reset_segment_features(cm);
   vp10_set_high_precision_mv(cpi, 0);
 
   {
@@ -3561,7 +3565,7 @@
   // 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) {
--- a/vp10/encoder/encoder.h
+++ b/vp10/encoder/encoder.h
@@ -55,7 +55,9 @@
   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;
 
--- 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 @@
 }
 
 // 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 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_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,6 +214,11 @@
 
 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;
@@ -203,18 +225,28 @@
 
   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,7 +269,7 @@
 
   // 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
@@ -244,7 +276,7 @@
   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 @@
       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 @@
   // 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);
 }
--- a/vp10/encoder/segmentation.h
+++ b/vp10/encoder/segmentation.h
@@ -44,7 +44,7 @@
 
 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"