shithub: libvpx

ref: a742a736550c4fc1120c06832749bced0a209e1b
dir: /vp8/common/entropymode.c/

View raw version
/*
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */


#include "modecont.h"
#include "entropymode.h"
#include "entropymv.h"
#include "entropy.h"
#include "vpx_mem/vpx_mem.h"


const unsigned int kf_y_mode_cts[8][VP8_YMODES] =
{
#if CONFIG_NEWINTRAMODES
    /* DC V   H  D45 135 117 153 D27 D63 TM i8x8 BPRED */
    {12,  6,  5,  5,  5,  5,  5,  5,  5,  2, 22, 200},
    {25, 13, 13,  7,  7,  7,  7,  7,  7,  6, 27, 160},
    {31, 17, 18,  8,  8,  8,  8,  8,  8,  9, 26, 139},
    {40, 22, 23,  8,  8,  8,  8,  8,  8, 12, 27, 116},
    {53, 26, 28,  8,  8,  8,  8,  8,  8, 13, 26,  94},
    {68, 33, 35,  8,  8,  8,  8,  8,  8, 17, 20,  68},
    {78, 38, 38,  8,  8,  8,  8,  8,  8, 19, 16,  52},
    {89, 42, 42,  8,  8,  8,  8,  8,  8, 21, 12,  34},
#else
    {17,  6,  5,  2, 22, 203},
    {27, 13, 13,  6, 27, 170},
    {35, 17, 18,  9, 26, 152},
    {45, 22, 24, 12, 27, 126},
    {58, 26, 29, 13, 26, 104},
    {73, 33, 36, 17, 20,  78},
    {88, 38, 39, 19, 16,  57},
    {99, 42, 43, 21, 12,  39},
#endif
};

static const unsigned int y_mode_cts  [VP8_YMODES] =
#if CONFIG_NEWINTRAMODES
    /* DC V   H  D45 135 117 153 D27 D63 TM i8x8 BPRED */
    {98, 19, 15, 14, 14, 14, 14, 12, 12, 13, 16, 70};
#else
    {106, 25, 21, 13, 16, 74};
#endif

static const unsigned int uv_mode_cts [VP8_YMODES] [VP8_UV_MODES] ={
#if CONFIG_NEWINTRAMODES
    /* DC   V   H  D45 135 117 153 D27 D63 TM */
    { 200, 15, 15, 10, 10, 10, 10, 10, 10,  6}, /* DC */
    { 130, 75, 10, 10, 10, 10, 10, 10, 10,  6}, /* V */
    { 130, 10, 75, 10, 10, 10, 10, 10, 10,  6}, /* H */
    { 130, 15, 10, 75, 10, 10, 10, 10, 10,  6}, /* D45 */
    { 150, 15, 10, 10, 75, 10, 10, 10, 10,  6}, /* D135 */
    { 150, 15, 10, 10, 10, 75, 10, 10, 10,  6}, /* D117 */
    { 150, 15, 10, 10, 10, 10, 75, 10, 10,  6}, /* D153 */
    { 150, 15, 10, 10, 10, 10, 10, 75, 10,  6}, /* D27 */
    { 150, 15, 10, 10, 10, 10, 10, 10, 75,  6}, /* D63 */
    { 160, 30, 30, 10, 10, 10, 10, 10, 10, 16}, /* TM */
    { 132, 46, 40, 10, 10, 10, 10, 10, 10, 18}, /* i8x8 - never used */
    { 150, 35, 41, 10, 10, 10, 10, 10, 10, 10}, /* BPRED */
#else
    { 210, 20, 20,  6},
    { 180, 60, 10,  6},
    { 150, 20, 80,  6},
    { 170, 35, 35, 16},
    { 142, 51, 45, 18}, /* never used */
    { 160, 40, 46, 10},
#endif
};

static const unsigned int i8x8_mode_cts  [VP8_I8X8_MODES] =
#if CONFIG_NEWINTRAMODES
    /* DC V   H D45 135 117 153 D27 D63  TM */
    {73, 49, 61, 30, 30, 30, 30, 30, 30, 13};
#else
    {93, 69, 81, 13};
#endif

static const unsigned int kf_uv_mode_cts [VP8_YMODES] [VP8_UV_MODES] ={
#if CONFIG_NEWINTRAMODES
    // DC   V   H  D45 135 117 153 D27 D63 TM
    { 160, 24, 24, 20, 20, 20, 20, 20, 20,  8}, /* DC */
    { 102, 64, 30, 20, 20, 20, 20, 20, 20, 10}, /* V */
    { 102, 30, 64, 20, 20, 20, 20, 20, 20, 10}, /* H */
    { 102, 33, 20, 64, 20, 20, 20, 20, 20, 14}, /* D45 */
    { 102, 33, 20, 20, 64, 20, 20, 20, 20, 14}, /* D135 */
    { 122, 33, 20, 20, 20, 64, 20, 20, 20, 14}, /* D117 */
    { 102, 33, 20, 20, 20, 20, 64, 20, 20, 14}, /* D153 */
    { 102, 33, 20, 20, 20, 20, 20, 64, 20, 14}, /* D27 */
    { 102, 33, 20, 20, 20, 20, 20, 20, 64, 14}, /* D63 */
    { 132, 36, 30, 20, 20, 20, 20, 20, 20, 18}, /* TM */
    { 122, 41, 35, 20, 20, 20, 20, 20, 20, 18}, /* i8x8 - never used */
    { 122, 41, 35, 20, 20, 20, 20, 20, 20, 18}, /* BPRED */
#else
    { 180, 34, 34,  8},
    { 132, 74, 40, 10},
    { 132, 40, 74, 10},
    { 152, 46, 40, 18},
    { 142, 51, 45, 18}, /* never used */
    { 142, 51, 45, 18},
#endif
};

static const unsigned int bmode_cts[VP8_BINTRAMODES] =
{
    /* DC    TM     VE     HE   LD    RD    VR    VL    HD    HU */
    43891, 17694, 10036, 3920, 3363, 2546, 5119, 3221, 2471, 1723
};

typedef enum
{
    SUBMVREF_NORMAL,
    SUBMVREF_LEFT_ZED,
    SUBMVREF_ABOVE_ZED,
    SUBMVREF_LEFT_ABOVE_SAME,
    SUBMVREF_LEFT_ABOVE_ZED
} sumvfref_t;

int vp8_mv_cont(const int_mv *l, const int_mv *a)
{
    int lez = (l->as_int == 0);
    int aez = (a->as_int == 0);
    int lea = (l->as_int == a->as_int);

    if (lea && lez)
        return SUBMVREF_LEFT_ABOVE_ZED;

    if (lea)
        return SUBMVREF_LEFT_ABOVE_SAME;

    if (aez)
        return SUBMVREF_ABOVE_ZED;

    if (lez)
        return SUBMVREF_LEFT_ZED;

    return SUBMVREF_NORMAL;
}

static const vp8_prob sub_mv_ref_prob [VP8_SUBMVREFS-1] = { 180, 162, 25};

const vp8_prob vp8_sub_mv_ref_prob2 [SUBMVREF_COUNT][VP8_SUBMVREFS-1] =
{
    { 147, 136, 18 },
    { 106, 145, 1  },
    { 179, 121, 1  },
    { 223, 1  , 34 },
    { 208, 1  , 1  }
};



vp8_mbsplit vp8_mbsplits [VP8_NUMMBSPLITS] =
{
    {
        0,  0,  0,  0,
        0,  0,  0,  0,
        1,  1,  1,  1,
        1,  1,  1,  1,
    },
    {
        0,  0,  1,  1,
        0,  0,  1,  1,
        0,  0,  1,  1,
        0,  0,  1,  1,
    },
    {
        0,  0,  1,  1,
        0,  0,  1,  1,
        2,  2,  3,  3,
        2,  2,  3,  3,
    },
    {
        0,  1,  2,  3,
        4,  5,  6,  7,
        8,  9,  10, 11,
        12, 13, 14, 15,
    },
};

const int vp8_mbsplit_count [VP8_NUMMBSPLITS] = { 2, 2, 4, 16};

const vp8_prob vp8_mbsplit_probs [VP8_NUMMBSPLITS-1] = { 110, 111, 150};


/* Array indices are identical to previously-existing INTRAMODECONTEXTNODES. */

const vp8_tree_index vp8_bmode_tree[VP8_BINTRAMODES*2-2] =     /* INTRAMODECONTEXTNODE value */
{
    -B_DC_PRED, 2,                             /* 0 = DC_NODE */
    -B_TM_PRED, 4,                            /* 1 = TM_NODE */
    -B_VE_PRED, 6,                           /* 2 = VE_NODE */
    8, 12,                                  /* 3 = COM_NODE */
    -B_HE_PRED, 10,                        /* 4 = HE_NODE */
    -B_RD_PRED, -B_VR_PRED,               /* 5 = RD_NODE */
    -B_LD_PRED, 14,                        /* 6 = LD_NODE */
    -B_VL_PRED, 16,                      /* 7 = VL_NODE */
    -B_HD_PRED, -B_HU_PRED             /* 8 = HD_NODE */
};

#if CONFIG_NEWINTRAMODES
/* Again, these trees use the same probability indices as their
   explicitly-programmed predecessors. */
const vp8_tree_index vp8_ymode_tree[VP8_YMODES*2-2] =
{
    2, 14,
    -DC_PRED, 4,
    6, 8,
    -D45_PRED, -D135_PRED,
    10, 12,
    -D117_PRED, -D153_PRED,
    -D27_PRED, -D63_PRED,
    16, 18,
    -V_PRED, -H_PRED,
    -TM_PRED, 20,
    -B_PRED, -I8X8_PRED
};

const vp8_tree_index vp8_kf_ymode_tree[VP8_YMODES*2-2] =
{
    2, 14,
    -DC_PRED, 4,
    6, 8,
    -D45_PRED, -D135_PRED,
    10, 12,
    -D117_PRED, -D153_PRED,
    -D27_PRED, -D63_PRED,
    16, 18,
    -V_PRED, -H_PRED,
    -TM_PRED, 20,
    -B_PRED, -I8X8_PRED
};

const vp8_tree_index vp8_i8x8_mode_tree[VP8_I8X8_MODES*2-2] =
{
    2, 14,
    -DC_PRED, 4,
    6, 8,
    -D45_PRED, -D135_PRED,
    10, 12,
    -D117_PRED, -D153_PRED,
    -D27_PRED, -D63_PRED,
    -V_PRED, 16,
    -H_PRED, -TM_PRED
};

const vp8_tree_index vp8_uv_mode_tree[VP8_UV_MODES*2-2] =
{
    2, 14,
    -DC_PRED, 4,
    6, 8,
    -D45_PRED, -D135_PRED,
    10, 12,
    -D117_PRED, -D153_PRED,
    -D27_PRED, -D63_PRED,
    -V_PRED, 16,
    -H_PRED, -TM_PRED
};

#else  /* CONFIG_NEWINTRAMODES */

/* Again, these trees use the same probability indices as their
   explicitly-programmed predecessors. */
const vp8_tree_index vp8_ymode_tree[10] =
{
    -DC_PRED, 2,
    4, 6,
    -V_PRED, -H_PRED,
    -TM_PRED, 8,
    -B_PRED, -I8X8_PRED
};

const vp8_tree_index vp8_kf_ymode_tree[10] =
{
    -B_PRED, 2,
    4, 6,
    -DC_PRED, -V_PRED,
    -H_PRED, 8,
    -TM_PRED, -I8X8_PRED
};

const vp8_tree_index vp8_i8x8_mode_tree[6] =
{
    -DC_PRED, 2,
    -V_PRED, 4,
    -H_PRED, -TM_PRED
};
const vp8_tree_index vp8_uv_mode_tree[6] =
{
    -DC_PRED, 2,
    -V_PRED, 4,
    -H_PRED, -TM_PRED
};

#endif  /* CONFIG_NEWINTRAMODES */

const vp8_tree_index vp8_mbsplit_tree[6] =
{
    -3, 2,
    -2, 4,
    -0, -1
};

const vp8_tree_index vp8_mv_ref_tree[8] =
{
    -ZEROMV, 2,
    -NEARESTMV, 4,
    -NEARMV, 6,
    -NEWMV, -SPLITMV
};

const vp8_tree_index vp8_sub_mv_ref_tree[6] =
{
    -LEFT4X4, 2,
    -ABOVE4X4, 4,
    -ZERO4X4, -NEW4X4
};


struct vp8_token_struct vp8_bmode_encodings   [VP8_BINTRAMODES];
struct vp8_token_struct vp8_ymode_encodings   [VP8_YMODES];
struct vp8_token_struct vp8_kf_ymode_encodings [VP8_YMODES];
struct vp8_token_struct vp8_uv_mode_encodings  [VP8_UV_MODES];
struct vp8_token_struct vp8_i8x8_mode_encodings  [VP8_UV_MODES];
struct vp8_token_struct vp8_mbsplit_encodings [VP8_NUMMBSPLITS];

struct vp8_token_struct vp8_mv_ref_encoding_array    [VP8_MVREFS];
struct vp8_token_struct vp8_sub_mv_ref_encoding_array [VP8_SUBMVREFS];



void vp8_init_mbmode_probs(VP8_COMMON *x)
{
    unsigned int bct [VP8_YMODES] [2];      /* num Ymodes > num UV modes */

    vp8_tree_probs_from_distribution(
        VP8_YMODES, vp8_ymode_encodings, vp8_ymode_tree,
        x->fc.ymode_prob, bct, y_mode_cts,
        256, 1
    );
    {
        int i;
        for (i=0;i<8;i++)
        vp8_tree_probs_from_distribution(
            VP8_YMODES, vp8_kf_ymode_encodings, vp8_kf_ymode_tree,
            x->kf_ymode_prob[i], bct, kf_y_mode_cts[i],
            256, 1
            );
    }
    {
        int i;
        for (i=0;i<VP8_YMODES;i++)
        {
            vp8_tree_probs_from_distribution(
                VP8_UV_MODES, vp8_uv_mode_encodings, vp8_uv_mode_tree,
                x->kf_uv_mode_prob[i], bct, kf_uv_mode_cts[i],
                256, 1);
            vp8_tree_probs_from_distribution(
                VP8_UV_MODES, vp8_uv_mode_encodings, vp8_uv_mode_tree,
                x->fc.uv_mode_prob[i], bct, uv_mode_cts[i],
                256, 1);
        }
    }

    vp8_tree_probs_from_distribution(
        VP8_I8X8_MODES, vp8_i8x8_mode_encodings, vp8_i8x8_mode_tree,
        x->fc.i8x8_mode_prob, bct, i8x8_mode_cts,
        256, 1);

    vpx_memcpy(x->fc.sub_mv_ref_prob, sub_mv_ref_prob, sizeof(sub_mv_ref_prob));

}


static void intra_bmode_probs_from_distribution(
    vp8_prob p [VP8_BINTRAMODES-1],
    unsigned int branch_ct [VP8_BINTRAMODES-1] [2],
    const unsigned int events [VP8_BINTRAMODES]
)
{
    vp8_tree_probs_from_distribution(
        VP8_BINTRAMODES, vp8_bmode_encodings, vp8_bmode_tree,
        p, branch_ct, events,
        256, 1
    );
}

void vp8_default_bmode_probs(vp8_prob p [VP8_BINTRAMODES-1])
{
    unsigned int branch_ct [VP8_BINTRAMODES-1] [2];
    intra_bmode_probs_from_distribution(p, branch_ct, bmode_cts);
}

void vp8_kf_default_bmode_probs(vp8_prob p [VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES-1])
{
    unsigned int branch_ct [VP8_BINTRAMODES-1] [2];

    int i = 0;

    do
    {
        int j = 0;

        do
        {
            intra_bmode_probs_from_distribution(
                p[i][j], branch_ct, vp8_kf_default_bmode_counts[i][j]);

        }
        while (++j < VP8_BINTRAMODES);
    }
    while (++i < VP8_BINTRAMODES);
}


void vp8_entropy_mode_init()
{
    vp8_tokens_from_tree(vp8_bmode_encodings,   vp8_bmode_tree);
    vp8_tokens_from_tree(vp8_ymode_encodings,   vp8_ymode_tree);
    vp8_tokens_from_tree(vp8_kf_ymode_encodings, vp8_kf_ymode_tree);
    vp8_tokens_from_tree(vp8_uv_mode_encodings,  vp8_uv_mode_tree);
    vp8_tokens_from_tree(vp8_i8x8_mode_encodings,  vp8_i8x8_mode_tree);
    vp8_tokens_from_tree(vp8_mbsplit_encodings, vp8_mbsplit_tree);

    vp8_tokens_from_tree_offset(vp8_mv_ref_encoding_array,
                                vp8_mv_ref_tree, NEARESTMV);
    vp8_tokens_from_tree_offset(vp8_sub_mv_ref_encoding_array,
                                vp8_sub_mv_ref_tree, LEFT4X4);
}

void vp8_init_mode_contexts(VP8_COMMON *pc)
{
    vpx_memset(pc->mv_ref_ct, 0, sizeof(pc->mv_ref_ct));
    vpx_memset(pc->mv_ref_ct_a, 0, sizeof(pc->mv_ref_ct_a));

    vpx_memcpy( pc->mode_context,
                default_vp8_mode_contexts,
                sizeof (pc->mode_context));
    vpx_memcpy( pc->mode_context_a,
                default_vp8_mode_contexts,
                sizeof (pc->mode_context_a));

}

void vp8_accum_mv_refs(VP8_COMMON *pc,
                       MB_PREDICTION_MODE m,
                       const int ct[4])
{
    int (*mv_ref_ct)[4][2];

    if(pc->refresh_alt_ref_frame)
        mv_ref_ct = pc->mv_ref_ct_a;
    else
        mv_ref_ct = pc->mv_ref_ct;

    if (m == ZEROMV)
    {
        ++mv_ref_ct [ct[0]] [0] [0];
    }
    else
    {
        ++mv_ref_ct [ct[0]] [0] [1];
        if (m == NEARESTMV)
        {
            ++mv_ref_ct [ct[1]] [1] [0];
        }
        else
        {
            ++mv_ref_ct [ct[1]] [1] [1];
            if (m == NEARMV)
            {
                ++mv_ref_ct [ct[2]] [2] [0];
            }
            else
            {
                ++mv_ref_ct [ct[2]] [2] [1];
                if (m == NEWMV)
                {
                    ++mv_ref_ct [ct[3]] [3] [0];
                }
                else
                {
                    ++mv_ref_ct [ct[3]] [3] [1];
                }
            }
        }
    }
}

void vp8_update_mode_context(VP8_COMMON *pc)
{
    int i, j;
    int (*mv_ref_ct)[4][2];
    int (*mode_context)[4];

    if(pc->refresh_alt_ref_frame)
    {
        mv_ref_ct = pc->mv_ref_ct_a;
        mode_context = pc->mode_context_a;
    }
    else
    {
        mv_ref_ct = pc->mv_ref_ct;
        mode_context = pc->mode_context;
    }

    for (j = 0; j < 6; j++)
    {
        for (i = 0; i < 4; i++)
        {
            int this_prob;
            int count = mv_ref_ct[j][i][0] + mv_ref_ct[j][i][1];
            /* preventing rare occurances from skewing the probs */
            if (count>=4)
            {
                this_prob = 256 * mv_ref_ct[j][i][0] / count;
                this_prob = this_prob? (this_prob<255?this_prob:255):1;
                mode_context[j][i] = this_prob;
            }
        }
    }
}
#include "vp8/common/modecont.h"
void print_mode_contexts(VP8_COMMON *pc)
{
    int j, i;
    printf("\n====================\n");
    for(j=0; j<6; j++)
    {
        for (i = 0; i < 4; i++)
        {
            printf( "%4d ", pc->mode_context[j][i]);
        }
        printf("\n");
    }
    printf("====================\n");
    for(j=0; j<6; j++)
    {
        for (i = 0; i < 4; i++)
        {
            printf( "%4d ", pc->mode_context_a[j][i]);
        }
        printf("\n");
    }

}
void print_mv_ref_cts(VP8_COMMON *pc)
{
    int j, i;
    for(j=0; j<6; j++)
    {
        for (i = 0; i < 4; i++)
        {
            printf("(%4d:%4d) ",
                    pc->mv_ref_ct[j][i][0],
                    pc->mv_ref_ct[j][i][1]);
        }
        printf("\n");
    }
}

#if CONFIG_ADAPTIVE_ENTROPY
//#define MODE_COUNT_TESTING
#define MODE_COUNT_SAT 16
#define MODE_MAX_UPDATE_FACTOR 96
void vp8_adapt_mode_probs(VP8_COMMON *cm)
{
    int i, t, count, factor;
    unsigned int branch_ct[32][2];
    int update_factor = MODE_MAX_UPDATE_FACTOR; /* denominator 256 */
    int count_sat = MODE_COUNT_SAT;
    vp8_prob ymode_probs[VP8_YMODES-1];
    vp8_prob uvmode_probs[VP8_UV_MODES-1];
    vp8_prob bmode_probs[VP8_BINTRAMODES-1];
    vp8_prob i8x8_mode_probs[VP8_I8X8_MODES-1];
#ifdef MODE_COUNT_TESTING
    printf("static const unsigned int\nymode_counts"
           "[VP8_YMODES] = {\n");
    for (t = 0; t<VP8_YMODES; ++t) printf("%d, ", cm->fc.ymode_counts[t]);
    printf("};\n");
    printf("static const unsigned int\nuv_mode_counts"
           "[VP8_YMODES] [VP8_UV_MODES] = {\n");
    for (i = 0; i < VP8_YMODES; ++i)
    {
        printf("  {");
        for (t = 0; t < VP8_UV_MODES; ++t) printf("%d, ", cm->fc.uv_mode_counts[i][t]);
        printf("},\n");
    }
    printf("};\n");
    printf("static const unsigned int\nbmode_counts"
           "[VP8_BINTRAMODES] = {\n");
    for (t = 0; t<VP8_BINTRAMODES; ++t) printf("%d, ", cm->fc.bmode_counts[t]);
    printf("};\n");
    printf("static const unsigned int\ni8x8_mode_counts"
           "[VP8_I8X8_MODES] = {\n");
    for (t = 0; t<VP8_I8X8_MODES; ++t) printf("%d, ", cm->fc.i8x8_mode_counts[t]);
    printf("};\n");
#endif
    vp8_tree_probs_from_distribution(
        VP8_YMODES, vp8_ymode_encodings, vp8_ymode_tree,
        ymode_probs, branch_ct, cm->fc.ymode_counts,
        256, 1);
    for (t=0; t<VP8_YMODES-1; ++t)
    {
        int prob;
        count = branch_ct[t][0] + branch_ct[t][1];
        count = count > count_sat ? count_sat : count;
        factor = (update_factor * count / count_sat);
        prob = ((int)cm->fc.pre_ymode_prob[t] * (256-factor) +
                (int)ymode_probs[t] * factor + 128) >> 8;
        if (prob <= 0) cm->fc.ymode_prob[t] = 1;
        else if (prob > 255) cm->fc.ymode_prob[t] = 255;
        else cm->fc.ymode_prob[t] = prob;
    }
    for (i = 0; i < VP8_YMODES; ++i)
    {
        vp8_tree_probs_from_distribution(
            VP8_UV_MODES, vp8_uv_mode_encodings, vp8_uv_mode_tree,
            uvmode_probs, branch_ct, cm->fc.uv_mode_counts[i],
            256, 1);
        for (t = 0; t < VP8_UV_MODES-1; ++t)
        {
            int prob;
            count = branch_ct[t][0] + branch_ct[t][1];
            count = count > count_sat ? count_sat : count;
            factor = (update_factor * count / count_sat);
            prob = ((int)cm->fc.pre_uv_mode_prob[i][t] * (256-factor) +
                    (int)uvmode_probs[t] * factor + 128) >> 8;
            if (prob <= 0) cm->fc.uv_mode_prob[i][t] = 1;
            else if (prob > 255) cm->fc.uv_mode_prob[i][t] = 255;
            else cm->fc.uv_mode_prob[i][t] = prob;
        }
    }
    vp8_tree_probs_from_distribution(
        VP8_BINTRAMODES, vp8_bmode_encodings, vp8_bmode_tree,
        bmode_probs, branch_ct, cm->fc.bmode_counts,
        256, 1);
    for (t=0; t<VP8_BINTRAMODES-1; ++t)
    {
        int prob;
        count = branch_ct[t][0] + branch_ct[t][1];
        count = count > count_sat ? count_sat : count;
        factor = (update_factor * count / count_sat);
        prob = ((int)cm->fc.pre_bmode_prob[t] * (256-factor) +
                (int)bmode_probs[t] * factor + 128) >> 8;
        if (prob <= 0) cm->fc.bmode_prob[t] = 1;
        else if (prob > 255) cm->fc.bmode_prob[t] = 255;
        else cm->fc.bmode_prob[t] = prob;
    }
    vp8_tree_probs_from_distribution(
        VP8_I8X8_MODES, vp8_i8x8_mode_encodings, vp8_i8x8_mode_tree,
        i8x8_mode_probs, branch_ct, cm->fc.i8x8_mode_counts,
        256, 1);
    for (t=0; t<VP8_I8X8_MODES-1; ++t)
    {
        int prob;
        count = branch_ct[t][0] + branch_ct[t][1];
        count = count > count_sat ? count_sat : count;
        factor = (update_factor * count / count_sat);
        prob = ((int)cm->fc.pre_i8x8_mode_prob[t] * (256-factor) +
                (int)i8x8_mode_probs[t] * factor + 128) >> 8;
        if (prob <= 0) cm->fc.i8x8_mode_prob[t] = 1;
        else if (prob > 255) cm->fc.i8x8_mode_prob[t] = 255;
        else cm->fc.i8x8_mode_prob[t] = prob;
    }
}
#endif