encodeframe.c 38.9 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
            x->e_mbd.mbmi.mode = mode;
            vp8_build_intra_predictors_mby_ptr(&x->e_mbd);
            distortion2 = VARIANCE_INVOKE(&cpi->rtcd.variance, get16x16prederror)(x->src.y_buffer, x->src.y_stride, x->e_mbd.predictor, 16, 0x7fffffff);
            rate2  = x->mbmode_cost[x->e_mbd.frame_type][mode];
            this_rd = RD_ESTIMATE(x->rdmult, x->rddiv, rate2, distortion2);

            if (Error16x16 > this_rd)
            {
                Error16x16 = this_rd;
                best_mode = mode;
            }
        }

        vp8_pick_intra4x4mby_modes(IF_RTCD(&cpi->rtcd), x, &rate2, &distortion2);

        if (distortion2 == INT_MAX)
            Error4x4 = INT_MAX;
        else
            Error4x4 = RD_ESTIMATE(x->rdmult, x->rddiv, rate2, distortion2);

        x->e_mbd.mbmi.mb_skip_coeff = (cpi->common.mb_no_coeff_skip) ? 1 : 0;

        if (Error4x4 < Error16x16)
        {
            x->e_mbd.mbmi.mode = B_PRED;
            vp8_encode_intra4x4mby(IF_RTCD(&cpi->rtcd), x);
            cpi->prediction_error += Error4x4;
        }
        else
        {
            x->e_mbd.mbmi.mode = best_mode;
            vp8_encode_intra16x16mby(IF_RTCD(&cpi->rtcd), x);
            cpi->prediction_error += Error16x16;
        }

        vp8_pick_intra_mbuv_mode(x);
        vp8_encode_intra16x16mbuv(IF_RTCD(&cpi->rtcd), x);
        sum_intra_stats(cpi, x);
        vp8_tokenize_mb(cpi, &x->e_mbd, t);
    }

    return rate;
}
#ifdef SPEEDSTATS
extern int cnt_pm;
#endif

extern void vp8_fix_contexts(VP8_COMP *cpi, MACROBLOCKD *x);

int vp8cx_encode_inter_macroblock
(
    VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t,
    int recon_yoffset, int recon_uvoffset
)
{
    MACROBLOCKD *const xd = &x->e_mbd;
    int inter_error;
    int intra_error = 0;
    int rate;
    int distortion;

    x->skip = 0;

    if (xd->segmentation_enabled)
        x->encode_breakout = cpi->segment_encode_breakout[xd->mbmi.segment_id];
    else
        x->encode_breakout = cpi->oxcf.encode_breakout;

#if !(CONFIG_REALTIME_ONLY)

    if (cpi->sf.RD)
    {
        inter_error = vp8_rd_pick_inter_mode(cpi, x, recon_yoffset, recon_uvoffset, &rate, &distortion, &intra_error);
    }
    else
#endif
        inter_error = vp8_pick_inter_mode(cpi, x, recon_yoffset, recon_uvoffset, &rate, &distortion, &intra_error);


    cpi->prediction_error += inter_error;
    cpi->intra_error += intra_error;

#if 0
    // Experimental RD code
    cpi->frame_distortion += distortion;
    cpi->last_mb_distortion = distortion;
#endif

    // MB level adjutment to quantizer setup
    if (xd->segmentation_enabled || cpi->zbin_mode_boost_enabled)
    {
        // If cyclic update enabled
        if (cpi->cyclic_refresh_mode_enabled)
        {
            // Clear segment_id back to 0 if not coded (last frame 0,0)
            if ((xd->mbmi.segment_id == 1) &&
                ((xd->mbmi.ref_frame != LAST_FRAME) || (xd->mbmi.mode != ZEROMV)))
            {
                xd->mbmi.segment_id = 0;
            }
        }

        // Experimental code. Special case for gf and arf zeromv modes. Increase zbin size to supress noise
        if (cpi->zbin_mode_boost_enabled)
        {
            if ((xd->mbmi.mode == ZEROMV) && (xd->mbmi.ref_frame != LAST_FRAME))
                cpi->zbin_mode_boost = GF_ZEROMV_ZBIN_BOOST;
            else
                cpi->zbin_mode_boost = 0;
        }

        vp8cx_mb_init_quantizer(cpi,  x);
    }

    cpi->count_mb_ref_frame_usage[xd->mbmi.ref_frame] ++;

    if (xd->mbmi.ref_frame == INTRA_FRAME)
    {
        x->e_mbd.mbmi.mb_skip_coeff = (cpi->common.mb_no_coeff_skip) ? 1 : 0;

        vp8_encode_intra16x16mbuv(IF_RTCD(&cpi->rtcd), x);

        if (xd->mbmi.mode == B_PRED)
        {
            vp8_encode_intra4x4mby(IF_RTCD(&cpi->rtcd), x);
        }
        else
        {
            vp8_encode_intra16x16mby(IF_RTCD(&cpi->rtcd), x);
        }

        sum_intra_stats(cpi, x);
    }
    else
    {
        MV best_ref_mv;
        MV nearest, nearby;
        int mdcounts[4];

        vp8_find_near_mvs(xd, xd->mode_info_context,
                          &nearest, &nearby, &best_ref_mv, mdcounts, xd->mbmi.ref_frame, cpi->common.ref_frame_sign_bias);

        vp8_build_uvmvs(xd, cpi->common.full_pixel);

        // store motion vectors in our motion vector list
        if (xd->mbmi.ref_frame == LAST_FRAME)
        {
            // Set up pointers for this macro block into the previous frame recon buffer
            xd->pre.y_buffer = cpi->common.last_frame.y_buffer + recon_yoffset;
            xd->pre.u_buffer = cpi->common.last_frame.u_buffer + recon_uvoffset;
            xd->pre.v_buffer = cpi->common.last_frame.v_buffer + recon_uvoffset;
        }
        else if (xd->mbmi.ref_frame == GOLDEN_FRAME)
        {
            // Set up pointers for this macro block into the golden frame recon buffer
            xd->pre.y_buffer = cpi->common.golden_frame.y_buffer + recon_yoffset;
            xd->pre.u_buffer = cpi->common.golden_frame.u_buffer + recon_uvoffset;
            xd->pre.v_buffer = cpi->common.golden_frame.v_buffer + recon_uvoffset;
        }
        else
        {
            // Set up pointers for this macro block into the alternate reference frame recon buffer
            xd->pre.y_buffer = cpi->common.alt_ref_frame.y_buffer + recon_yoffset;
            xd->pre.u_buffer = cpi->common.alt_ref_frame.u_buffer + recon_uvoffset;
            xd->pre.v_buffer = cpi->common.alt_ref_frame.v_buffer + recon_uvoffset;
        }

        if (xd->mbmi.mode == SPLITMV)
        {
            int i;

            for (i = 0; i < 16; i++)
            {
                if (xd->block[i].bmi.mode == NEW4X4)
                {
                    cpi->MVcount[0][mv_max+((xd->block[i].bmi.mv.as_mv.row - best_ref_mv.row) >> 1)]++;
                    cpi->MVcount[1][mv_max+((xd->block[i].bmi.mv.as_mv.col - best_ref_mv.col) >> 1)]++;
                }
            }
        }
        else if (xd->mbmi.mode == NEWMV)
        {
            cpi->MVcount[0][mv_max+((xd->block[0].bmi.mv.as_mv.row - best_ref_mv.row) >> 1)]++;
            cpi->MVcount[1][mv_max+((xd->block[0].bmi.mv.as_mv.col - best_ref_mv.col) >> 1)]++;
        }

        if (!x->skip && !x->e_mbd.mbmi.force_no_skip)
        {
            vp8_encode_inter16x16(IF_RTCD(&cpi->rtcd), x);

            // Clear mb_skip_coeff if mb_no_coeff_skip is not set
            if (!cpi->common.mb_no_coeff_skip)
                xd->mbmi.mb_skip_coeff = 0;

        }
        else
            vp8_stuff_inter16x16(x);
    }

    if (!x->skip)
        vp8_tokenize_mb(cpi, xd, t);
    else
    {
        if (cpi->common.mb_no_coeff_skip)
        {
            if (xd->mbmi.mode != B_PRED && xd->mbmi.mode != SPLITMV)
                xd->mbmi.dc_diff = 0;
            else
                xd->mbmi.dc_diff = 1;

            xd->mbmi.mb_skip_coeff = 1;
            cpi->skip_true_count ++;
            vp8_fix_contexts(cpi, xd);
        }
        else
        {
            vp8_stuff_mb(cpi, xd, t);
            xd->mbmi.mb_skip_coeff = 0;
            cpi->skip_false_count ++;
        }
    }

    return rate;
}