/*
 *  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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <assert.h>

#include "math.h"
#include "common.h"
#include "ratectrl.h"
#include "entropymode.h"
#include "vpx_mem/vpx_mem.h"
#include "systemdependent.h"
#include "encodemv.h"


#define MIN_BPB_FACTOR          0.01
#define MAX_BPB_FACTOR          50

extern const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES];
extern const MV_REFERENCE_FRAME vp8_ref_frame_order[MAX_MODES];



#ifdef MODE_STATS
extern int y_modes[5];
extern int uv_modes[4];
extern int b_modes[10];

extern int inter_y_modes[10];
extern int inter_uv_modes[4];
extern int inter_b_modes[10];
#endif

// Bits Per MB at different Q (Multiplied by 512)
#define BPER_MB_NORMBITS    9

const int vp8_bits_per_mb[2][QINDEX_RANGE] =
{
    // (Updated 19 March 08) Baseline estimate of INTRA-frame Bits Per MB at each Q:
    {
        674781, 606845, 553905, 524293, 500428, 452540, 435379, 414719,
        390970, 371082, 359416, 341807, 336957, 317263, 303724, 298402,
        285688, 275237, 268455, 262560, 256038, 248734, 241087, 237615,
        229247, 225211, 219112, 213920, 211559, 202714, 198482, 193401,
        187866, 183453, 179212, 175965, 171852, 167235, 163972, 160560,
        156032, 154349, 151390, 148725, 145708, 142311, 139981, 137700,
        134084, 131863, 129746, 128498, 126077, 123461, 121290, 117782,
        114883, 112332, 108410, 105685, 103434, 101192,  98587,  95959,
        94059,  92017,  89970,  87936,  86142,  84801,  82736,  81106,
        79668,  78135,  76641,  75103,  73943,  72693,  71401,  70098,
        69165,  67901,  67170,  65987,  64923,  63534,  62378,  61302,
        59921,  58941,  57844,  56782,  55960,  54973,  54257,  53454,
        52230,  50938,  49962,  49190,  48288,  47270,  46738,  46037,
        45020,  44027,  43216,  42287,  41594,  40702,  40081,  39414,
        38282,  37627,  36987,  36375,  35808,  35236,  34710,  34162,
        33659,  33327,  32751,  32384,  31936,  31461,  30982,  30582,
    },

    // (Updated 19 March 08) Baseline estimate of INTER-frame Bits Per MB at each Q:
    {
        497401, 426316, 372064, 352732, 335763, 283921, 273848, 253321,
        233181, 217727, 210030, 196685, 194836, 178396, 167753, 164116,
        154119, 146929, 142254, 138488, 133591, 127741, 123166, 120226,
        114188, 111756, 107882, 104749, 102522,  96451,  94424,  90905,
        87286,  84931,  82111,  80534,  77610,  74700,  73037,  70715,
        68006,  67235,  65374,  64009,  62134,  60180,  59105,  57691,
        55509,  54512,  53318,  52693,  51194,  49840,  48944,  46980,
        45668,  44177,  42348,  40994,  39859,  38889,  37717,  36391,
        35482,  34622,  33795,  32756,  32002,  31492,  30573,  29737,
        29152,  28514,  27941,  27356,  26859,  26329,  25874,  25364,
        24957,  24510,  24290,  23689,  23380,  22845,  22481,  22066,
        21587,  21219,  20880,  20452,  20260,  19926,  19661,  19334,
        18915,  18391,  18046,  17833,  17441,  17105,  16888,  16729,
        16383,  16023,  15706,  15442,  15222,  14938,  14673,  14452,
        14005,  13807,  13611,  13447,  13223,  13102,  12963,  12801,
        12627,  12534,  12356,  12228,  12056,  11907,  11746,  11643,
    }
};

const int vp8_kf_boost_qadjustment[QINDEX_RANGE] =
{
    128, 129, 130, 131, 132, 133, 134, 135,
    136, 137, 138, 139, 140, 141, 142, 143,
    144, 145, 146, 147, 148, 149, 150, 151,
    152, 153, 154, 155, 156, 157, 158, 159,
    160, 161, 162, 163, 164, 165, 166, 167,
    168, 169, 170, 171, 172, 173, 174, 175,
    176, 177, 178, 179, 180, 181, 182, 183,
    184, 185, 186, 187, 188, 189, 190, 191,
    192, 193, 194, 195, 196, 197, 198, 199,
    200, 200, 201, 201, 202, 203, 203, 203,
    204, 204, 205, 205, 206, 206, 207, 207,
    208, 208, 209, 209, 210, 210, 211, 211,
    212, 212, 213, 213, 214, 214, 215, 215,
    216, 216, 217, 217, 218, 218, 219, 219,
    220, 220, 220, 220, 220, 220, 220, 220,
    220, 220, 220, 220, 220, 220, 220, 220,
};

//#define GFQ_ADJUSTMENT (Q+100)
#define GFQ_ADJUSTMENT vp8_gf_boost_qadjustment[Q]
const int vp8_gf_boost_qadjustment[QINDEX_RANGE] =
{
    80, 82, 84, 86, 88, 90, 92, 94,
    96, 97, 98, 99, 100, 101, 102, 103,
    104, 105, 106, 107, 108, 109, 110, 111,
    112, 113, 114, 115, 116, 117, 118, 119,
    120, 121, 122, 123, 124, 125, 126, 127,
    128, 129, 130, 131, 132, 133, 134, 135,
    136, 137, 138, 139, 140, 141, 142, 143,
    144, 145, 146, 147, 148, 149, 150, 151,
    152, 153, 154, 155, 156, 157, 158, 159,
    160, 161, 162, 163, 164, 165, 166, 167,
    168, 169, 170, 171, 172, 173, 174, 175,
    176, 177, 178, 179, 180, 181, 182, 183,
    184, 184, 185, 185, 186, 186, 187, 187,
    188, 188, 189, 189, 190, 190, 191, 191,
    192, 192, 193, 193, 194, 194, 194, 194,
    195, 195, 196, 196, 197, 197, 198, 198
};

/*
const int vp8_gf_boost_qadjustment[QINDEX_RANGE] =
{
    100,101,102,103,104,105,105,106,
    106,107,107,108,109,109,110,111,
    112,113,114,115,116,117,118,119,
    120,121,122,123,124,125,126,127,
    128,129,130,131,132,133,134,135,
    136,137,138,139,140,141,142,143,
    144,145,146,147,148,149,150,151,
    152,153,154,155,156,157,158,159,
    160,161,162,163,164,165,166,167,
    168,169,170,170,171,171,172,172,
    173,173,173,174,174,174,175,175,
    175,176,176,176,177,177,177,177,
    178,178,179,179,180,180,181,181,
    182,182,183,183,184,184,185,185,
    186,186,187,187,188,188,189,189,
    190,190,191,191,192,192,193,193,
};
*/

const int vp8_kf_gf_boost_qlimits[QINDEX_RANGE] =
{
    150, 155, 160, 165, 170, 175, 180, 185,
    190, 195, 200, 205, 210, 215, 220, 225,
    230, 235, 240, 245, 250, 255, 260, 265,
    270, 275, 280, 285, 290, 295, 300, 305,
    310, 320, 330, 340, 350, 360, 370, 380,
    390, 400, 410, 420, 430, 440, 450, 460,
    470, 480, 490, 500, 510, 520, 530, 540,
    550, 560, 570, 580, 590, 600, 600, 600,
    600, 600, 600, 600, 600, 600, 600, 600,
    600, 600, 600, 600, 600, 600, 600, 600,
    600, 600, 600, 600, 600, 600, 600, 600,
    600, 600, 600, 600, 600, 600, 600, 600,
    600, 600, 600, 600, 600, 600, 600, 600,
    600, 600, 600, 600, 600, 600, 600, 600,
    600, 600, 600, 600, 600, 600, 600, 600,
    600, 600, 600, 600, 600, 600, 600, 600,
};

// % adjustment to target kf size based on seperation from previous frame
const int vp8_kf_boost_seperationt_adjustment[16] =
{
    30,   40,   50,   55,   60,   65,   70,   75,
    80,   85,   90,   95,  100,  100,  100,  100,
};


const int vp8_gf_adjust_table[101] =
{
    100,
    115, 130, 145, 160, 175, 190, 200, 210, 220, 230,
    240, 260, 270, 280, 290, 300, 310, 320, 330, 340,
    350, 360, 370, 380, 390, 400, 400, 400, 400, 400,
    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
};

const int vp8_gf_intra_useage_adjustment[20] =
{
    125, 120, 115, 110, 105, 100,  95,  85,  80,  75,
    70,  65,  60,  55,  50,  50,  50,  50,  50,  50,
};

const int vp8_gf_interval_table[101] =
{
    7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
    8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
};

static const unsigned int prior_key_frame_weight[KEY_FRAME_CONTEXT] = { 1, 2, 3, 4, 5 };


void vp8_save_coding_context(VP8_COMP *cpi)
{
    CODING_CONTEXT *const cc = & cpi->coding_context;

    // Stores a snapshot of key state variables which can subsequently be
    // restored with a call to vp8_restore_coding_context. These functions are
    // intended for use in a re-code loop in vp8_compress_frame where the
    // quantizer value is adjusted between loop iterations.

    cc->frames_since_key          = cpi->frames_since_key;
    cc->filter_level             = cpi->common.filter_level;
    cc->frames_till_gf_update_due   = cpi->frames_till_gf_update_due;
    cc->frames_since_golden       = cpi->common.frames_since_golden;

    vp8_copy(cc->mvc,      cpi->common.fc.mvc);
    vp8_copy(cc->mvcosts,  cpi->mb.mvcosts);

    vp8_copy(cc->kf_ymode_prob,   cpi->common.kf_ymode_prob);
    vp8_copy(cc->ymode_prob,   cpi->common.fc.ymode_prob);
    vp8_copy(cc->kf_uv_mode_prob,  cpi->common.kf_uv_mode_prob);
    vp8_copy(cc->uv_mode_prob,  cpi->common.fc.uv_mode_prob);

    vp8_copy(cc->ymode_count, cpi->ymode_count);
    vp8_copy(cc->uv_mode_count, cpi->uv_mode_count);


    // Stats
#ifdef MODE_STATS
    vp8_copy(cc->y_modes,       y_modes);
    vp8_copy(cc->uv_modes,      uv_modes);
    vp8_copy(cc->b_modes,       b_modes);
    vp8_copy(cc->inter_y_modes,  inter_y_modes);
    vp8_copy(cc->inter_uv_modes, inter_uv_modes);
    vp8_copy(cc->inter_b_modes,  inter_b_modes);
#endif

    cc->this_frame_percent_intra = cpi->this_frame_percent_intra;
}


void vp8_restore_coding_context(VP8_COMP *cpi)
{
    CODING_CONTEXT *const cc = & cpi->coding_context;

    // Restore key state variables to the snapshot state stored in the
    // previous call to vp8_save_coding_context.

    cpi->frames_since_key         =   cc->frames_since_key;
    cpi->common.filter_level     =   cc->filter_level;
    cpi->frames_till_gf_update_due  =   cc->frames_till_gf_update_due;
    cpi->common.frames_since_golden       =   cc->frames_since_golden;

    vp8_copy(cpi->common.fc.mvc, cc->mvc);

    vp8_copy(cpi->mb.mvcosts, cc->mvcosts);

    vp8_copy(cpi->common.kf_ymode_prob,   cc->kf_ymode_prob);
    vp8_copy(cpi->common.fc.ymode_prob,   cc->ymode_prob);
    vp8_copy(cpi->common.kf_uv_mode_prob,  cc->kf_uv_mode_prob);
    vp8_copy(cpi->common.fc.uv_mode_prob,  cc->uv_mode_prob);

    vp8_copy(cpi->ymode_count, cc->ymode_count);
    vp8_copy(cpi->uv_mode_count, cc->uv_mode_count);

    // Stats
#ifdef MODE_STATS
    vp8_copy(y_modes, cc->y_modes);
    vp8_copy(uv_modes, cc->uv_modes);
    vp8_copy(b_modes, cc->b_modes);
    vp8_copy(inter_y_modes, cc->inter_y_modes);
    vp8_copy(inter_uv_modes, cc->inter_uv_modes);
    vp8_copy(inter_b_modes, cc->inter_b_modes);
#endif


    cpi->this_frame_percent_intra = cc->this_frame_percent_intra;
}


void vp8_setup_key_frame(VP8_COMP *cpi)
{
    // Setup for Key frame:

    vp8_default_coef_probs(& cpi->common);
    vp8_kf_default_bmode_probs(cpi->common.kf_bmode_prob);

    vpx_memcpy(cpi->common.fc.mvc, vp8_default_mv_context, sizeof(vp8_default_mv_context));
    {
        int flag[2] = {1, 1};
        vp8_build_component_cost_table(cpi->mb.mvcost, cpi->mb.mvsadcost, (const MV_CONTEXT *) cpi->common.fc.mvc, flag);
    }

    vpx_memset(cpi->common.fc.pre_mvc, 0, sizeof(cpi->common.fc.pre_mvc));  //initialize pre_mvc to all zero.

    //cpi->common.filter_level = 0;      // Reset every key frame.
    cpi->common.filter_level = cpi->common.base_qindex * 3 / 8 ;

    // Provisional interval before next GF
    if (cpi->auto_gold)
        //cpi->frames_till_gf_update_due = DEFAULT_GF_INTERVAL;
        cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
    else
        cpi->frames_till_gf_update_due = cpi->goldfreq;

    cpi->common.refresh_golden_frame = TRUE;
}

void vp8_calc_auto_iframe_target_size(VP8_COMP *cpi)
{
    // boost defaults to half second
    int kf_boost;

    // Clear down mmx registers to allow floating point in what follows
    vp8_clear_system_state();  //__asm emms;

    if (cpi->oxcf.fixed_q >= 0)
    {
        vp8_calc_iframe_target_size(cpi);
        return;
    }

    if (cpi->pass == 2)
    {
        cpi->this_frame_target = cpi->per_frame_bandwidth;      // New Two pass RC
    }
    else
    {
        // Boost depends somewhat on frame rate
        kf_boost = (int)(2 * cpi->output_frame_rate - 16);

        // adjustment up based on q
        kf_boost = kf_boost * vp8_kf_boost_qadjustment[cpi->ni_av_qi] / 100;

        // frame separation adjustment ( down)
        if (cpi->frames_since_key  < cpi->output_frame_rate / 2)
            kf_boost = (int)(kf_boost * cpi->frames_since_key / (cpi->output_frame_rate / 2));

        if (kf_boost < 16)
            kf_boost = 16;

        // Reset the active worst quality to the baseline value for key frames.
        cpi->active_worst_quality = cpi->worst_quality;

        cpi->this_frame_target = ((16 + kf_boost)  * cpi->per_frame_bandwidth) >> 4;
    }


    // Should the next frame be an altref frame
    if (cpi->pass != 2)
    {
        // For now Alt ref is not allowed except in 2 pass modes.
        cpi->source_alt_ref_pending = FALSE;

        /*if ( cpi->oxcf.fixed_q == -1)
        {
            if ( cpi->oxcf.play_alternate && ( (cpi->last_boost/2) > (100+(AF_THRESH*cpi->frames_till_gf_update_due)) ) )
                cpi->source_alt_ref_pending = TRUE;
            else
                cpi->source_alt_ref_pending = FALSE;
        }*/
    }

    if (0)
    {
        FILE *f;

        f = fopen("kf_boost.stt", "a");
        //fprintf(f, " %8d %10d %10d %10d %10d %10d %10d\n",
        //  cpi->common.current_video_frame,  cpi->target_bandwidth, cpi->frames_to_key, kf_boost_qadjustment[cpi->ni_av_qi], cpi->kf_boost, (cpi->this_frame_target *100 / cpi->per_frame_bandwidth), cpi->this_frame_target );

        fprintf(f, " %8u %10d %10d %10d\n",
                cpi->common.current_video_frame,  cpi->gfu_boost, cpi->baseline_gf_interval, cpi->source_alt_ref_pending);

        fclose(f);
    }
}

//  Do the best we can to define the parameteres for the next GF based on what information we have available.
static void calc_gf_params(VP8_COMP *cpi)
{
    int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
    int Boost = 0;

    int gf_frame_useage = 0;      // Golden frame useage since last GF
    int tot_mbs = cpi->recent_ref_frame_usage[INTRA_FRAME]  +
                  cpi->recent_ref_frame_usage[LAST_FRAME]   +
                  cpi->recent_ref_frame_usage[GOLDEN_FRAME] +
                  cpi->recent_ref_frame_usage[ALTREF_FRAME];

    int pct_gf_active = (100 * cpi->gf_active_count) / (cpi->common.mb_rows * cpi->common.mb_cols);

    // Reset the last boost indicator
    //cpi->last_boost = 100;

    if (tot_mbs)
        gf_frame_useage = (cpi->recent_ref_frame_usage[GOLDEN_FRAME] + cpi->recent_ref_frame_usage[ALTREF_FRAME]) * 100 / tot_mbs;

    if (pct_gf_active > gf_frame_useage)
        gf_frame_useage = pct_gf_active;

    // Not two pass
    if (cpi->pass != 2)
    {
        // Single Pass lagged mode: TBD
        if (FALSE)
        {
        }

        // Single Pass compression: Has to use current and historical data
        else
        {
#if 0
            // Experimental code
            int index = cpi->one_pass_frame_index;
            int frames_to_scan = (cpi->max_gf_interval <= MAX_LAG_BUFFERS) ? cpi->max_gf_interval : MAX_LAG_BUFFERS;

            /*
            // *************** Experimental code - incomplete
            double decay_val = 1.0;
            double IIAccumulator = 0.0;
            double last_iiaccumulator = 0.0;
            double IIRatio;

            cpi->one_pass_frame_index = cpi->common.current_video_frame%MAX_LAG_BUFFERS;

            for ( i = 0; i < (frames_to_scan - 1); i++ )
            {
                if ( index < 0 )
                    index = MAX_LAG_BUFFERS;
                index --;

                if ( cpi->one_pass_frame_stats[index].frame_coded_error > 0.0 )
                {
                    IIRatio = cpi->one_pass_frame_stats[index].frame_intra_error / cpi->one_pass_frame_stats[index].frame_coded_error;

                    if ( IIRatio > 30.0 )
                        IIRatio = 30.0;
                }
                else
                    IIRatio = 30.0;

                IIAccumulator += IIRatio * decay_val;

                decay_val = decay_val * cpi->one_pass_frame_stats[index].frame_pcnt_inter;

                if (    (i > MIN_GF_INTERVAL) &&
                        ((IIAccumulator - last_iiaccumulator) < 2.0) )
                {
                    break;
                }
                last_iiaccumulator = IIAccumulator;
            }

            Boost = IIAccumulator*100.0/16.0;
            cpi->baseline_gf_interval = i;

            */
#else

            /*************************************************************/
            // OLD code

            // Adjust boost based upon ambient Q
            Boost = GFQ_ADJUSTMENT;

            // Adjust based upon most recently measure intra useage
            Boost = Boost * vp8_gf_intra_useage_adjustment[(cpi->this_frame_percent_intra < 15) ? cpi->this_frame_percent_intra : 14] / 100;

            // Adjust gf boost based upon GF usage since last GF
            Boost = Boost * vp8_gf_adjust_table[gf_frame_useage] / 100;
#endif
        }

        // golden frame boost without recode loop often goes awry.  be safe by keeping numbers down.
        if (!cpi->sf.recode_loop)
        {
            if (cpi->compressor_speed == 2)
                Boost = Boost / 2;
        }

        // Apply an upper limit based on Q for 1 pass encodes
        if (Boost > vp8_kf_gf_boost_qlimits[Q] && (cpi->pass == 0))
            Boost = vp8_kf_gf_boost_qlimits[Q];

        // Apply lower limits to boost.
        else if (Boost < 110)
            Boost = 110;

        // Note the boost used
        cpi->last_boost = Boost;

    }

    // Estimate next interval
    // This is updated once the real frame size/boost is known.
    if (cpi->oxcf.fixed_q == -1)
    {
        if (cpi->pass == 2)         // 2 Pass
        {
            cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
        }
        else                            // 1 Pass
        {
            cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;

            if (cpi->last_boost > 750)
                cpi->frames_till_gf_update_due++;

            if (cpi->last_boost > 1000)
                cpi->frames_till_gf_update_due++;

            if (cpi->last_boost > 1250)
                cpi->frames_till_gf_update_due++;

            if (cpi->last_boost >= 1500)
                cpi->frames_till_gf_update_due ++;

            if (vp8_gf_interval_table[gf_frame_useage] > cpi->frames_till_gf_update_due)
                cpi->frames_till_gf_update_due = vp8_gf_interval_table[gf_frame_useage];

            if (cpi->frames_till_gf_update_due > cpi->max_gf_interval)
                cpi->frames_till_gf_update_due = cpi->max_gf_interval;
        }
    }
    else
        cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;

    // ARF on or off
    if (cpi->pass != 2)
    {
        // For now Alt ref is not allowed except in 2 pass modes.
        cpi->source_alt_ref_pending = FALSE;

        /*if ( cpi->oxcf.fixed_q == -1)
        {
            if ( cpi->oxcf.play_alternate && (cpi->last_boost > (100 + (AF_THRESH*cpi->frames_till_gf_update_due)) ) )
                cpi->source_alt_ref_pending = TRUE;
            else
                cpi->source_alt_ref_pending = FALSE;
        }*/
    }
}
/* This is equvialent to estimate_bits_at_q without the rate_correction_factor. */
static int baseline_bits_at_q(int frame_kind, int Q, int MBs)
{
    int Bpm = vp8_bits_per_mb[frame_kind][Q];

    /* Attempt to retain reasonable accuracy without overflow. The cutoff is
     * chosen such that the maximum product of Bpm and MBs fits 31 bits. The
     * largest Bpm takes 20 bits.
     */
    if (MBs > (1 << 11))
        return (Bpm >> BPER_MB_NORMBITS) * MBs;
    else
        return (Bpm * MBs) >> BPER_MB_NORMBITS;
}

void vp8_calc_iframe_target_size(VP8_COMP *cpi)
{
    int Q;
    int Boost = 100;

    Q = (cpi->oxcf.fixed_q >= 0) ? cpi->oxcf.fixed_q : cpi->avg_frame_qindex;

    if (cpi->auto_adjust_key_quantizer == 1)
    {
        // If (auto_adjust_key_quantizer==1) then a lower Q is selected for key-frames.
        // The enhanced Q is calculated so as to boost the key frame size by a factor
        // specified in kf_boost_qadjustment. Also, can adjust based on distance
        // between key frames.

        // Adjust boost based upon ambient Q
        Boost = vp8_kf_boost_qadjustment[Q];

        // Make the Key frame boost less if the seperation from the previous key frame is small
        if (cpi->frames_since_key < 16)
            Boost = Boost * vp8_kf_boost_seperationt_adjustment[cpi->frames_since_key] / 100;
        else
            Boost = Boost * vp8_kf_boost_seperationt_adjustment[15] / 100;

        // Apply limits on boost
        if (Boost > vp8_kf_gf_boost_qlimits[Q])
            Boost = vp8_kf_gf_boost_qlimits[Q];
        else if (Boost < 120)
            Boost = 120;
    }

    // Keep a record of the boost that was used
    cpi->last_boost = Boost;

    // Should the next frame be an altref frame
    if (cpi->pass != 2)
    {
        // For now Alt ref is not allowed except in 2 pass modes.
        cpi->source_alt_ref_pending = FALSE;

        /*if ( cpi->oxcf.fixed_q == -1)
        {
            if ( cpi->oxcf.play_alternate && ( (cpi->last_boost/2) > (100+(AF_THRESH*cpi->frames_till_gf_update_due)) ) )
                cpi->source_alt_ref_pending = TRUE;
            else
                cpi->source_alt_ref_pending = FALSE;
        }*/
    }

    if (cpi->oxcf.fixed_q >= 0)
    {
        cpi->this_frame_target = (baseline_bits_at_q(0, Q, cpi->common.MBs) * Boost) / 100;
    }
    else
    {

        int bits_per_mb_at_this_q ;

        if (cpi->oxcf.error_resilient_mode == 1)
        {
            cpi->this_frame_target = 2 * cpi->av_per_frame_bandwidth;
            return;
        }

        // Rate targetted scenario:
        // Be careful of 32-bit OVERFLOW if restructuring the caluclation of cpi->this_frame_target
        bits_per_mb_at_this_q = (int)(.5 +
                                      cpi->key_frame_rate_correction_factor * vp8_bits_per_mb[0][Q]);

        cpi->this_frame_target = (((bits_per_mb_at_this_q * cpi->common.MBs) >> BPER_MB_NORMBITS) * Boost) / 100;

        // Reset the active worst quality to the baseline value for key frames.
        if (cpi->pass < 2)
            cpi->active_worst_quality = cpi->worst_quality;
    }
}



void vp8_calc_pframe_target_size(VP8_COMP *cpi)
{
    int min_frame_target;
    int Adjustment;

    // Set the min frame bandwidth.
    //min_frame_target = estimate_min_frame_size( cpi );
    min_frame_target = 0;

    if (cpi->pass == 2)
    {
        min_frame_target = cpi->min_frame_bandwidth;

        if (min_frame_target < (cpi->av_per_frame_bandwidth >> 5))
            min_frame_target = cpi->av_per_frame_bandwidth >> 5;
    }
    else if (min_frame_target < cpi->per_frame_bandwidth / 4)
        min_frame_target = cpi->per_frame_bandwidth / 4;


    // Special alt reference frame case
    if (cpi->common.refresh_alt_ref_frame)
    {
        if (cpi->pass == 2)
        {
            cpi->per_frame_bandwidth = cpi->gf_bits;                       // Per frame bit target for the alt ref frame
            cpi->this_frame_target = cpi->per_frame_bandwidth;
        }

        /* One Pass ??? TBD */
        /*else
        {
            int frames_in_section;
            int allocation_chunks;
            int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
            int alt_boost;
            int max_arf_rate;

            alt_boost = (cpi->gfu_boost * 3 * GFQ_ADJUSTMENT) / (2 * 100);
            alt_boost += (cpi->frames_till_gf_update_due * 50);

            // If alt ref is not currently active then we have a pottential double hit with GF and ARF so reduce the boost a bit.
            // A similar thing is done on GFs that preceed a arf update.
            if ( !cpi->source_alt_ref_active )
                alt_boost = alt_boost * 3 / 4;

            frames_in_section = cpi->frames_till_gf_update_due+1;                                   // Standard frames + GF
            allocation_chunks = (frames_in_section * 100) + alt_boost;

            // Normalize Altboost and allocations chunck down to prevent overflow
            while ( alt_boost > 1000 )
            {
                alt_boost /= 2;
                allocation_chunks /= 2;
            }

            else
            {
                int bits_in_section;

                if ( cpi->kf_overspend_bits > 0 )
                {
                    Adjustment = (cpi->kf_bitrate_adjustment <= cpi->kf_overspend_bits) ? cpi->kf_bitrate_adjustment : cpi->kf_overspend_bits;

                    if ( Adjustment > (cpi->per_frame_bandwidth - min_frame_target) )
                        Adjustment = (cpi->per_frame_bandwidth - min_frame_target);

                    cpi->kf_overspend_bits -= Adjustment;

                    // Calculate an inter frame bandwidth target for the next few frames designed to recover
                    // any extra bits spent on the key frame.
                    cpi->inter_frame_target = cpi->per_frame_bandwidth - Adjustment;
                    if ( cpi->inter_frame_target < min_frame_target )
                        cpi->inter_frame_target = min_frame_target;
                }
                else
                    cpi->inter_frame_target = cpi->per_frame_bandwidth;

                bits_in_section = cpi->inter_frame_target * frames_in_section;

                // Avoid loss of precision but avoid overflow
                if ( (bits_in_section>>7) > allocation_chunks )
                    cpi->this_frame_target = alt_boost * (bits_in_section / allocation_chunks);
                else
                    cpi->this_frame_target = (alt_boost * bits_in_section) / allocation_chunks;
            }
        }
        */
    }

    // Normal frames (gf,and inter)
    else
    {
        // 2 pass
        if (cpi->pass == 2)
        {
            cpi->this_frame_target = cpi->per_frame_bandwidth;
        }
        // 1 pass
        else
        {
            // Make rate adjustment to recover bits spent in key frame
            // Test to see if the key frame inter data rate correction should still be in force
            if (cpi->kf_overspend_bits > 0)
            {
                Adjustment = (cpi->kf_bitrate_adjustment <= cpi->kf_overspend_bits) ? cpi->kf_bitrate_adjustment : cpi->kf_overspend_bits;

                if (Adjustment > (cpi->per_frame_bandwidth - min_frame_target))
                    Adjustment = (cpi->per_frame_bandwidth - min_frame_target);

                cpi->kf_overspend_bits -= Adjustment;

                // Calculate an inter frame bandwidth target for the next few frames designed to recover
                // any extra bits spent on the key frame.
                cpi->this_frame_target = cpi->per_frame_bandwidth - Adjustment;

                if (cpi->this_frame_target < min_frame_target)
                    cpi->this_frame_target = min_frame_target;
            }
            else
                cpi->this_frame_target = cpi->per_frame_bandwidth;

            // If appropriate make an adjustment to recover bits spent on a recent GF
            if ((cpi->gf_overspend_bits > 0) && (cpi->this_frame_target > min_frame_target))
            {
                int Adjustment = (cpi->non_gf_bitrate_adjustment <= cpi->gf_overspend_bits) ? cpi->non_gf_bitrate_adjustment : cpi->gf_overspend_bits;

                if (Adjustment > (cpi->this_frame_target - min_frame_target))
                    Adjustment = (cpi->this_frame_target - min_frame_target);

                cpi->gf_overspend_bits -= Adjustment;
                cpi->this_frame_target -= Adjustment;
            }

            // Apply small + and - boosts for non gf frames
            if ((cpi->last_boost > 150) && (cpi->frames_till_gf_update_due > 0) &&
                (cpi->current_gf_interval >= (MIN_GF_INTERVAL << 1)))
            {
                // % Adjustment limited to the range 1% to 10%
                Adjustment = (cpi->last_boost - 100) >> 5;

                if (Adjustment < 1)
                    Adjustment = 1;
                else if (Adjustment > 10)
                    Adjustment = 10;

                // Convert to bits
                Adjustment = (cpi->this_frame_target * Adjustment) / 100;

                if (Adjustment > (cpi->this_frame_target - min_frame_target))
                    Adjustment = (cpi->this_frame_target - min_frame_target);

                if (cpi->common.frames_since_golden == (cpi->current_gf_interval >> 1))
                    cpi->this_frame_target += ((cpi->current_gf_interval - 1) * Adjustment);
                else
                    cpi->this_frame_target -= Adjustment;
            }
        }
    }

    // Set a reduced data rate target for our initial Q calculation.
    // This should help to save bits during earier sections.
    if ((cpi->oxcf.under_shoot_pct > 0) && (cpi->oxcf.under_shoot_pct <= 100))
        cpi->this_frame_target = (cpi->this_frame_target * cpi->oxcf.under_shoot_pct) / 100;

    // Sanity check that the total sum of adjustments is not above the maximum allowed
    // That is that having allowed for KF and GF penalties we have not pushed the
    // current interframe target to low. If the adjustment we apply here is not capable of recovering
    // all the extra bits we have spent in the KF or GF then the remainder will have to be recovered over
    // a longer time span via other buffer / rate control mechanisms.
    if (cpi->this_frame_target < min_frame_target)
        cpi->this_frame_target = min_frame_target;

    if (!cpi->common.refresh_alt_ref_frame)
        // Note the baseline target data rate for this inter frame.
        cpi->inter_frame_target = cpi->this_frame_target;

    // One Pass specific code
    if (cpi->pass == 0)
    {
        // Adapt target frame size with respect to any buffering constraints:
        if (cpi->buffered_mode)
        {
            int one_percent_bits = 1 + cpi->oxcf.optimal_buffer_level / 100;

            if ((cpi->buffer_level < cpi->oxcf.optimal_buffer_level) || (cpi->bits_off_target < cpi->oxcf.optimal_buffer_level))
            {
                int percent_low = 0;

                // Decide whether or not we need to adjust the frame data rate target.
                //
                // If we are are below the optimal buffer fullness level and adherence
                // to buffering contraints is important to the end useage then adjust
                // the per frame target.
                if ((cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) && (cpi->buffer_level < cpi->oxcf.optimal_buffer_level))
                {
                    percent_low = (cpi->oxcf.optimal_buffer_level - cpi->buffer_level) / one_percent_bits;

                    if (percent_low > 100)
                        percent_low = 100;
                    else if (percent_low < 0)
                        percent_low = 0;
                }
                // Are we overshooting the long term clip data rate...
                else if (cpi->bits_off_target < 0)
                {
                    // Adjust per frame data target downwards to compensate.
                    percent_low = (int)(100 * -cpi->bits_off_target / (cpi->total_byte_count * 8));

                    if (percent_low > 100)
                        percent_low = 100;
                    else if (percent_low < 0)
                        percent_low = 0;
                }

                // lower the target bandwidth for this frame.
                cpi->this_frame_target = (cpi->this_frame_target * (100 - (percent_low / 2))) / 100;

                // Are we using allowing control of active_worst_allowed_q according to buffer level.
                if (cpi->auto_worst_q)
                {
                    int critical_buffer_level;

                    // For streaming applications the most important factor is cpi->buffer_level as this takes
                    // into account the specified short term buffering constraints. However, hitting the long
                    // term clip data rate target is also important.
                    if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
                    {
                        // Take the smaller of cpi->buffer_level and cpi->bits_off_target
                        critical_buffer_level = (cpi->buffer_level < cpi->bits_off_target) ? cpi->buffer_level : cpi->bits_off_target;
                    }
                    // For local file playback short term buffering contraints are less of an issue
                    else
                    {
                        // Consider only how we are doing for the clip as a whole
                        critical_buffer_level = cpi->bits_off_target;
                    }

                    // Set the active worst quality based upon the selected buffer fullness number.
                    if (critical_buffer_level < cpi->oxcf.optimal_buffer_level)
                    {
                        if (critical_buffer_level > (cpi->oxcf.optimal_buffer_level / 4))
                        {
                            int qadjustment_range = cpi->worst_quality - cpi->ni_av_qi;
                            int above_base = (critical_buffer_level - (cpi->oxcf.optimal_buffer_level / 4));

                            // Step active worst quality down from cpi->ni_av_qi when (critical_buffer_level == cpi->optimal_buffer_level)
                            // to cpi->oxcf.worst_allowed_q when (critical_buffer_level == cpi->optimal_buffer_level/4)
                            cpi->active_worst_quality = cpi->worst_quality - ((qadjustment_range * above_base) / (cpi->oxcf.optimal_buffer_level * 3 / 4));
                        }
                        else
                        {
                            cpi->active_worst_quality = cpi->worst_quality;
                        }
                    }
                    else
                    {
                        cpi->active_worst_quality = cpi->ni_av_qi;
                    }
                }
                else
                {
                    cpi->active_worst_quality = cpi->worst_quality;
                }
            }
            else
            {
                int percent_high;

                if (cpi->bits_off_target > cpi->oxcf.optimal_buffer_level)
                {
                    percent_high = (int)(100 * (cpi->bits_off_target - cpi->oxcf.optimal_buffer_level) / (cpi->total_byte_count * 8));

                    if (percent_high > 100)
                        percent_high = 100;
                    else if (percent_high < 0)
                        percent_high = 0;

                    cpi->this_frame_target = (cpi->this_frame_target * (100 + (percent_high / 2))) / 100;

                }

                // Are we allowing control of active_worst_allowed_q according to bufferl level.
                if (cpi->auto_worst_q)
                {
                    // When using the relaxed buffer model stick to the user specified value
                    cpi->active_worst_quality = cpi->ni_av_qi;
                }
                else
                {
                    cpi->active_worst_quality = cpi->worst_quality;
                }
            }

            // Set active_best_quality to prevent quality rising too high
            cpi->active_best_quality = cpi->best_quality;

            // Worst quality obviously must not be better than best quality
            if (cpi->active_worst_quality <= cpi->active_best_quality)
                cpi->active_worst_quality = cpi->active_best_quality + 1;

        }
        // Unbuffered mode (eg. video conferencing)
        else
        {
            // Set the active worst quality
            cpi->active_worst_quality = cpi->worst_quality;
        }
    }

    // Test to see if we have to drop a frame
    // The auto-drop frame code is only used in buffered mode.
    // In unbufferd mode (eg vide conferencing) the descision to
    // code or drop a frame is made outside the codec in response to real
    // world comms or buffer considerations.
    if (cpi->drop_frames_allowed && cpi->buffered_mode &&
        (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
        ((cpi->common.frame_type != KEY_FRAME))) //|| !cpi->oxcf.allow_spatial_resampling) )
    {
        // Check for a buffer underun-crisis in which case we have to drop a frame
        if ((cpi->buffer_level < 0))
        {
#if 0
            FILE *f = fopen("dec.stt", "a");
            fprintf(f, "%10d %10d %10d %10d ***** BUFFER EMPTY\n",
                    (int) cpi->common.current_video_frame,
                    cpi->decimation_factor, cpi->common.horiz_scale,
                    (cpi->buffer_level * 100) / cpi->oxcf.optimal_buffer_level);
            fclose(f);
#endif
            //vpx_log("Decoder: Drop frame due to bandwidth: %d \n",cpi->buffer_level, cpi->av_per_frame_bandwidth);

            cpi->drop_frame = TRUE;
        }

#if 0
        // Check for other drop frame crtieria (Note 2 pass cbr uses decimation on whole KF sections)
        else if ((cpi->buffer_level < cpi->oxcf.drop_frames_water_mark * cpi->oxcf.optimal_buffer_level / 100) &&
                 (cpi->drop_count < cpi->max_drop_count) && (cpi->pass == 0))
        {
            cpi->drop_frame = TRUE;
        }

#endif

        if (cpi->drop_frame)
        {
            // Update the buffer level variable.
            cpi->bits_off_target += cpi->av_per_frame_bandwidth;
            cpi->buffer_level = cpi->bits_off_target;
        }
        else
            cpi->drop_count = 0;
    }

    // Adjust target frame size for Golden Frames:
    if (cpi->oxcf.error_resilient_mode == 0 &&
        (cpi->frames_till_gf_update_due == 0) && !cpi->drop_frame)
    {
        //int Boost = 0;
        int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;

        int gf_frame_useage = 0;      // Golden frame useage since last GF
        int tot_mbs = cpi->recent_ref_frame_usage[INTRA_FRAME]  +
                      cpi->recent_ref_frame_usage[LAST_FRAME]   +
                      cpi->recent_ref_frame_usage[GOLDEN_FRAME] +
                      cpi->recent_ref_frame_usage[ALTREF_FRAME];

        int pct_gf_active = (100 * cpi->gf_active_count) / (cpi->common.mb_rows * cpi->common.mb_cols);

        // Reset the last boost indicator
        //cpi->last_boost = 100;

        if (tot_mbs)
            gf_frame_useage = (cpi->recent_ref_frame_usage[GOLDEN_FRAME] + cpi->recent_ref_frame_usage[ALTREF_FRAME]) * 100 / tot_mbs;

        if (pct_gf_active > gf_frame_useage)
            gf_frame_useage = pct_gf_active;

        // Is a fixed manual GF frequency being used
        if (!cpi->auto_gold)
            cpi->common.refresh_golden_frame = TRUE;
        else
        {
            // For one pass throw a GF if recent frame intra useage is low or the GF useage is high
            if ((cpi->pass == 0) && (cpi->this_frame_percent_intra < 15 || gf_frame_useage >= 5))
                cpi->common.refresh_golden_frame = TRUE;

            // Two pass GF descision
            else if (cpi->pass == 2)
                cpi->common.refresh_golden_frame = TRUE;
        }

#if 0

        // Debug stats
        if (0)
        {
            FILE *f;

            f = fopen("gf_useaget.stt", "a");
            fprintf(f, " %8ld %10ld %10ld %10ld %10ld\n",
                    cpi->common.current_video_frame,  cpi->gfu_boost, GFQ_ADJUSTMENT, cpi->gfu_boost, gf_frame_useage);
            fclose(f);
        }

#endif

        if (cpi->common.refresh_golden_frame == TRUE)
        {
#if 0

            if (0)   // p_gw
            {
                FILE *f;

                f = fopen("GFexit.stt", "a");
                fprintf(f, "%8ld GF coded\n", cpi->common.current_video_frame);
                fclose(f);
            }

#endif
            cpi->initial_gf_use = 0;

            if (cpi->auto_adjust_gold_quantizer)
            {
                calc_gf_params(cpi);
            }

            // If we are using alternate ref instead of gf then do not apply the boost
            // It will instead be applied to the altref update
            // Jims modified boost
            if (!cpi->source_alt_ref_active)
            {
                if (cpi->oxcf.fixed_q < 0)
                {
                    if (cpi->pass == 2)
                    {
                        cpi->this_frame_target = cpi->per_frame_bandwidth;          // The spend on the GF is defined in the two pass code for two pass encodes
                    }
                    else
                    {
                        int Boost = cpi->last_boost;
                        int frames_in_section = cpi->frames_till_gf_update_due + 1;
                        int allocation_chunks = (frames_in_section * 100) + (Boost - 100);
                        int bits_in_section = cpi->inter_frame_target * frames_in_section;

                        // Normalize Altboost and allocations chunck down to prevent overflow
                        while (Boost > 1000)
                        {
                            Boost /= 2;
                            allocation_chunks /= 2;
                        }

                        // Avoid loss of precision but avoid overflow
                        if ((bits_in_section >> 7) > allocation_chunks)
                            cpi->this_frame_target = Boost * (bits_in_section / allocation_chunks);
                        else
                            cpi->this_frame_target = (Boost * bits_in_section) / allocation_chunks;
                    }
                }
                else
                    cpi->this_frame_target = (baseline_bits_at_q(1, Q, cpi->common.MBs) * cpi->last_boost) / 100;

            }
            // If there is an active ARF at this location use the minimum
            // bits on this frame even if it is a contructed arf.
            // The active maximum quantizer insures that an appropriate
            // number of bits will be spent if needed for contstructed ARFs.
            else
            {
                cpi->this_frame_target = 0;
            }

            cpi->current_gf_interval = cpi->frames_till_gf_update_due;

        }
    }
}


void vp8_update_rate_correction_factors(VP8_COMP *cpi, int damp_var)
{
    int    Q = cpi->common.base_qindex;
    int    correction_factor = 100;
    double rate_correction_factor;
    double adjustment_limit;

    int    projected_size_based_on_q = 0;

    // Clear down mmx registers to allow floating point in what follows
    vp8_clear_system_state();  //__asm emms;

    if (cpi->common.frame_type == KEY_FRAME)
    {
        rate_correction_factor = cpi->key_frame_rate_correction_factor;
    }
    else
    {
        if (cpi->common.refresh_alt_ref_frame || cpi->common.refresh_golden_frame)
            rate_correction_factor = cpi->gf_rate_correction_factor;
        else
            rate_correction_factor = cpi->rate_correction_factor;
    }

    // Work out how big we would have expected the frame to be at this Q given the current correction factor.
    // Stay in double to avoid int overflow when values are large
    //projected_size_based_on_q = ((int)(.5 + rate_correction_factor * vp8_bits_per_mb[cpi->common.frame_type][Q]) * cpi->common.MBs) >> BPER_MB_NORMBITS;
    projected_size_based_on_q = (int)(((.5 + rate_correction_factor * vp8_bits_per_mb[cpi->common.frame_type][Q]) * cpi->common.MBs) / (1 << BPER_MB_NORMBITS));

    // Make some allowance for cpi->zbin_over_quant
    if (cpi->zbin_over_quant > 0)
    {
        int Z = cpi->zbin_over_quant;
        double Factor = 0.99;
        double factor_adjustment = 0.01 / 256.0; //(double)ZBIN_OQ_MAX;

        while (Z > 0)
        {
            Z --;
            projected_size_based_on_q =
                (int)(Factor * projected_size_based_on_q);
            Factor += factor_adjustment;

            if (Factor  >= 0.999)
                Factor = 0.999;
        }
    }

    // Work out a size correction factor.
    //if ( cpi->this_frame_target > 0 )
    //  correction_factor = (100 * cpi->projected_frame_size) / cpi->this_frame_target;
    if (projected_size_based_on_q > 0)
        correction_factor = (100 * cpi->projected_frame_size) / projected_size_based_on_q;

    // More heavily damped adjustment used if we have been oscillating either side of target
    switch (damp_var)
    {
    case 0:
        adjustment_limit = 0.75;
        break;
    case 1:
        adjustment_limit = 0.375;
        break;
    case 2:
    default:
        adjustment_limit = 0.25;
        break;
    }

    //if ( (correction_factor > 102) && (Q < cpi->active_worst_quality) )
    if (correction_factor > 102)
    {
        // We are not already at the worst allowable quality
        correction_factor = (int)(100.5 + ((correction_factor - 100) * adjustment_limit));
        rate_correction_factor = ((rate_correction_factor * correction_factor) / 100);

        // Keep rate_correction_factor within limits
        if (rate_correction_factor > MAX_BPB_FACTOR)
            rate_correction_factor = MAX_BPB_FACTOR;
    }
    //else if ( (correction_factor < 99) && (Q > cpi->active_best_quality) )
    else if (correction_factor < 99)
    {
        // We are not already at the best allowable quality
        correction_factor = (int)(100.5 - ((100 - correction_factor) * adjustment_limit));
        rate_correction_factor = ((rate_correction_factor * correction_factor) / 100);

        // Keep rate_correction_factor within limits
        if (rate_correction_factor < MIN_BPB_FACTOR)
            rate_correction_factor = MIN_BPB_FACTOR;
    }

    if (cpi->common.frame_type == KEY_FRAME)
        cpi->key_frame_rate_correction_factor = rate_correction_factor;
    else
    {
        if (cpi->common.refresh_alt_ref_frame || cpi->common.refresh_golden_frame)
            cpi->gf_rate_correction_factor = rate_correction_factor;
        else
            cpi->rate_correction_factor = rate_correction_factor;
    }
}

static int estimate_bits_at_q(VP8_COMP *cpi, int Q)
{
    int Bpm = (int)(.5 + cpi->rate_correction_factor * vp8_bits_per_mb[INTER_FRAME][Q]);

    /* Attempt to retain reasonable accuracy without overflow. The cutoff is
     * chosen such that the maximum product of Bpm and MBs fits 31 bits. The
     * largest Bpm takes 20 bits.
     */
    if (cpi->common.MBs > (1 << 11))
        return (Bpm >> BPER_MB_NORMBITS) * cpi->common.MBs;
    else
        return (Bpm * cpi->common.MBs) >> BPER_MB_NORMBITS;

}


int vp8_regulate_q(VP8_COMP *cpi, int target_bits_per_frame)
{
    int Q = cpi->active_worst_quality;

    // Reset Zbin OQ value
    cpi->zbin_over_quant = 0;

    if (cpi->oxcf.fixed_q >= 0)
    {
        Q = cpi->oxcf.fixed_q;

        if (cpi->common.frame_type == KEY_FRAME)
        {
            Q = cpi->oxcf.key_q;
        }
        else if (cpi->common.refresh_alt_ref_frame)
        {
            Q = cpi->oxcf.alt_q;
        }
        else if (cpi->common.refresh_golden_frame)
        {
            Q = cpi->oxcf.gold_q;
        }

    }
    else
    {
        int i;
        int last_error = INT_MAX;
        int target_bits_per_mb;
        int bits_per_mb_at_this_q;
        double correction_factor;

        // Select the appropriate correction factor based upon type of frame.
        if (cpi->common.frame_type == KEY_FRAME)
            correction_factor = cpi->key_frame_rate_correction_factor;
        else
        {
            if (cpi->common.refresh_alt_ref_frame || cpi->common.refresh_golden_frame)
                correction_factor = cpi->gf_rate_correction_factor;
            else
                correction_factor = cpi->rate_correction_factor;
        }

        // Calculate required scaling factor based on target frame size and size of frame produced using previous Q
        if (target_bits_per_frame >= (INT_MAX >> BPER_MB_NORMBITS))
            target_bits_per_mb = (target_bits_per_frame / cpi->common.MBs) << BPER_MB_NORMBITS;       // Case where we would overflow int
        else
            target_bits_per_mb = (target_bits_per_frame << BPER_MB_NORMBITS) / cpi->common.MBs;

        i = cpi->active_best_quality;

        do
        {
            bits_per_mb_at_this_q = (int)(.5 + correction_factor * vp8_bits_per_mb[cpi->common.frame_type][i]);

            if (bits_per_mb_at_this_q <= target_bits_per_mb)
            {
                if ((target_bits_per_mb - bits_per_mb_at_this_q) <= last_error)
                    Q = i;
                else
                    Q = i - 1;

                break;
            }
            else
                last_error = bits_per_mb_at_this_q - target_bits_per_mb;
        }
        while (++i <= cpi->active_worst_quality);


        // If we are at MAXQ then enable Q over-run which seeks to claw back additional bits through things like
        // the RD multiplier and zero bin size.
        if (Q >= MAXQ)
        {
            int zbin_oqmax;

            double Factor = 0.99;
            double factor_adjustment = 0.01 / 256.0; //(double)ZBIN_OQ_MAX;

            if (cpi->common.frame_type == KEY_FRAME)
                zbin_oqmax = 0; //ZBIN_OQ_MAX/16
            else if (cpi->common.refresh_alt_ref_frame || (cpi->common.refresh_golden_frame && !cpi->source_alt_ref_active))
                zbin_oqmax = 16;
            else
                zbin_oqmax = ZBIN_OQ_MAX;

            /*{
                double Factor = (double)target_bits_per_mb/(double)bits_per_mb_at_this_q;
                double Oq;

                Factor = Factor/1.2683;

                Oq = pow( Factor, (1.0/-0.165) );

                if ( Oq > zbin_oqmax )
                    Oq = zbin_oqmax;

                cpi->zbin_over_quant = (int)Oq;
            }*/

            // Each incrment in the zbin is assumed to have a fixed effect on bitrate. This is not of course true.
            // The effect will be highly clip dependent and may well have sudden steps.
            // The idea here is to acheive higher effective quantizers than the normal maximum by expanding the zero
            // bin and hence decreasing the number of low magnitude non zero coefficients.
            while (cpi->zbin_over_quant < zbin_oqmax)
            {
                cpi->zbin_over_quant ++;

                if (cpi->zbin_over_quant > zbin_oqmax)
                    cpi->zbin_over_quant = zbin_oqmax;

                // Adjust bits_per_mb_at_this_q estimate
                bits_per_mb_at_this_q = (int)(Factor * bits_per_mb_at_this_q);
                Factor += factor_adjustment;

                if (Factor  >= 0.999)
                    Factor = 0.999;

                if (bits_per_mb_at_this_q <= target_bits_per_mb)    // Break out if we get down to the target rate
                    break;
            }

        }
    }

    return Q;
}

static int estimate_min_frame_size(VP8_COMP *cpi)
{
    double correction_factor;
    int bits_per_mb_at_max_q;

    // This funtion returns a default value for the first few frames untill the correction factor has had time to adapt.
    if (cpi->common.current_video_frame < 10)
    {
        if (cpi->pass == 2)
            return (cpi->min_frame_bandwidth);
        else
            return cpi->per_frame_bandwidth / 3;
    }

    /*  // Select the appropriate correction factor based upon type of frame.
        if ( cpi->common.frame_type == KEY_FRAME )
            correction_factor = cpi->key_frame_rate_correction_factor;
        else
        {
            if ( cpi->common.refresh_alt_ref_frame || cpi->common.refresh_golden_frame )
                correction_factor = cpi->gf_rate_correction_factor;
            else
                correction_factor = cpi->rate_correction_factor;
        }*/

    // We estimate at half the value we get from vp8_bits_per_mb
    correction_factor = cpi->rate_correction_factor / 2.0;

    bits_per_mb_at_max_q = (int)(.5 + correction_factor * vp8_bits_per_mb[cpi->common.frame_type][MAXQ]);

    return (bits_per_mb_at_max_q * cpi->common.MBs) >> BPER_MB_NORMBITS;
}

void vp8_adjust_key_frame_context(VP8_COMP *cpi)
{
    int i;
    int av_key_frames_per_second;

    // Average key frame frequency and size
    unsigned int total_weight = 0;
    unsigned int av_key_frame_frequency = 0;
    unsigned int av_key_frame_bits = 0;

    unsigned int output_frame_rate = (unsigned int)(100 * cpi->output_frame_rate);
    unsigned int target_bandwidth = (unsigned int)(100 * cpi->target_bandwidth);

    // Clear down mmx registers to allow floating point in what follows
    vp8_clear_system_state();  //__asm emms;

    // Update the count of total key frame bits
    cpi->tot_key_frame_bits += cpi->projected_frame_size;

    // First key frame at start of sequence is a special case. We have no frequency data.
    if (cpi->key_frame_count == 1)
    {
        av_key_frame_frequency = (int)cpi->output_frame_rate * 2;            // Assume a default of 1 kf every 2 seconds
        av_key_frame_bits = cpi->projected_frame_size;
        av_key_frames_per_second  = output_frame_rate / av_key_frame_frequency;  // Note output_frame_rate not cpi->output_frame_rate
    }
    else
    {
        int last_kf_interval =
                (cpi->frames_since_key > 0) ? cpi->frames_since_key : 1;

        // reset keyframe context and calculate weighted average of last KEY_FRAME_CONTEXT keyframes
        for (i = 0; i < KEY_FRAME_CONTEXT; i++)
        {
            if (i < KEY_FRAME_CONTEXT - 1)
            {
                cpi->prior_key_frame_size[i]     = cpi->prior_key_frame_size[i+1];
                cpi->prior_key_frame_distance[i] = cpi->prior_key_frame_distance[i+1];
            }
            else
            {
                cpi->prior_key_frame_size[i]     = cpi->projected_frame_size;
                cpi->prior_key_frame_distance[i] = last_kf_interval;
            }

            av_key_frame_bits      += prior_key_frame_weight[i] * cpi->prior_key_frame_size[i];
            av_key_frame_frequency += prior_key_frame_weight[i] * cpi->prior_key_frame_distance[i];
            total_weight         += prior_key_frame_weight[i];
        }

        av_key_frame_bits       /= total_weight;
        av_key_frame_frequency  /= total_weight;
        av_key_frames_per_second  = output_frame_rate / av_key_frame_frequency;

    }

    // Do we have any key frame overspend to recover?
    if ((cpi->pass != 2) && (cpi->projected_frame_size > cpi->per_frame_bandwidth))
    {
        // Update the count of key frame overspend to be recovered in subsequent frames
        // A portion of the KF overspend is treated as gf overspend (and hence recovered more quickly)
        // as the kf is also a gf. Otherwise the few frames following each kf tend to get more bits
        // allocated than those following other gfs.
        cpi->kf_overspend_bits += (cpi->projected_frame_size - cpi->per_frame_bandwidth) * 7 / 8;
        cpi->gf_overspend_bits += (cpi->projected_frame_size - cpi->per_frame_bandwidth) * 1 / 8;

        // Work out how much to try and recover per frame.
        // For one pass we estimate the number of frames to spread it over based upon past history.
        // For two pass we know how many frames there will be till the next kf.
        if (cpi->pass == 2)
        {
            if (cpi->frames_to_key > 16)
                cpi->kf_bitrate_adjustment = cpi->kf_overspend_bits / (int)cpi->frames_to_key;
            else
                cpi->kf_bitrate_adjustment = cpi->kf_overspend_bits / 16;
        }
        else
            cpi->kf_bitrate_adjustment = cpi->kf_overspend_bits / (int)av_key_frame_frequency;
    }

    cpi->frames_since_key = 0;
    cpi->last_key_frame_size = cpi->projected_frame_size;
    cpi->key_frame_count++;
}

void vp8_compute_frame_size_bounds(VP8_COMP *cpi, int *frame_under_shoot_limit, int *frame_over_shoot_limit)
{
    // Set-up bounds on acceptable frame size:
    if (cpi->oxcf.fixed_q >= 0)
    {
        // Fixed Q scenario: frame size never outranges target (there is no target!)
        *frame_under_shoot_limit = 0;
        *frame_over_shoot_limit  = INT_MAX;
    }
    else
    {
        if (cpi->common.frame_type == KEY_FRAME)
        {
            *frame_over_shoot_limit  = cpi->this_frame_target * 9 / 8;
            *frame_under_shoot_limit = cpi->this_frame_target * 7 / 8;
        }
        else
        {
            if (cpi->common.refresh_alt_ref_frame || cpi->common.refresh_golden_frame)
            {
                *frame_over_shoot_limit  = cpi->this_frame_target * 9 / 8;
                *frame_under_shoot_limit = cpi->this_frame_target * 7 / 8;
            }
            else
            {
                // For CBR take buffer fullness into account
                if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
                {
                    if (cpi->buffer_level >= ((cpi->oxcf.optimal_buffer_level + cpi->oxcf.maximum_buffer_size) >> 1))
                    {
                        // Buffer is too full so relax overshoot and tighten undershoot
                        *frame_over_shoot_limit  = cpi->this_frame_target * 12 / 8;
                        *frame_under_shoot_limit = cpi->this_frame_target * 6 / 8;
                    }
                    else if (cpi->buffer_level <= (cpi->oxcf.optimal_buffer_level >> 1))
                    {
                        // Buffer is too low so relax undershoot and tighten overshoot
                        *frame_over_shoot_limit  = cpi->this_frame_target * 10 / 8;
                        *frame_under_shoot_limit = cpi->this_frame_target * 4 / 8;
                    }
                    else
                    {
                        *frame_over_shoot_limit  = cpi->this_frame_target * 11 / 8;
                        *frame_under_shoot_limit = cpi->this_frame_target * 5 / 8;
                    }
                }
                // VBR
                // Note that tighter restrictions here can help quality but hurt encode speed
                else
                {
                    *frame_over_shoot_limit  = cpi->this_frame_target * 11 / 8;
                    *frame_under_shoot_limit = cpi->this_frame_target * 5 / 8;
                }
            }
        }
    }
}
