encodeframe.c 47.1 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
    cpi->last_frame_distortion = cpi->frame_distortion;
#endif

    /* Update the average activity for the next frame.
     * This is feed-forward for now; it could also be saved in two-pass, or
     *  done during lookahead when that is eventually added.
     */
    cpi->activity_avg = (unsigned int )(x->activity_sum/cpi->common.MBs);
    if (cpi->activity_avg < VP8_ACTIVITY_AVG_MIN)
        cpi->activity_avg = VP8_ACTIVITY_AVG_MIN;

John Koleszar's avatar
John Koleszar committed
}
void vp8_setup_block_ptrs(MACROBLOCK *x)
{
    int r, c;
    int i;

    for (r = 0; r < 4; r++)
    {
        for (c = 0; c < 4; c++)
        {
            x->block[r*4+c].src_diff = x->src_diff + r * 4 * 16 + c * 4;
        }
    }

    for (r = 0; r < 2; r++)
    {
        for (c = 0; c < 2; c++)
        {
            x->block[16 + r*2+c].src_diff = x->src_diff + 256 + r * 4 * 8 + c * 4;
        }
    }


    for (r = 0; r < 2; r++)
    {
        for (c = 0; c < 2; c++)
        {
            x->block[20 + r*2+c].src_diff = x->src_diff + 320 + r * 4 * 8 + c * 4;
        }
    }

    x->block[24].src_diff = x->src_diff + 384;


    for (i = 0; i < 25; i++)
    {
        x->block[i].coeff = x->coeff + i * 16;
    }
}

void vp8_build_block_offsets(MACROBLOCK *x)
{
    int block = 0;
    int br, bc;

    vp8_build_block_doffsets(&x->e_mbd);

    // y blocks
    for (br = 0; br < 4; br++)
    {
        for (bc = 0; bc < 4; bc++)
        {
            BLOCK *this_block = &x->block[block];
            this_block->base_src = &x->src.y_buffer;
            this_block->src_stride = x->src.y_stride;
            this_block->src = 4 * br * this_block->src_stride + 4 * bc;
            ++block;
        }
    }

    // u blocks
    for (br = 0; br < 2; br++)
    {
        for (bc = 0; bc < 2; bc++)
        {
            BLOCK *this_block = &x->block[block];
            this_block->base_src = &x->src.u_buffer;
            this_block->src_stride = x->src.uv_stride;
            this_block->src = 4 * br * this_block->src_stride + 4 * bc;
            ++block;
        }
    }

    // v blocks
    for (br = 0; br < 2; br++)
    {
        for (bc = 0; bc < 2; bc++)
        {
            BLOCK *this_block = &x->block[block];
            this_block->base_src = &x->src.v_buffer;
            this_block->src_stride = x->src.uv_stride;
            this_block->src = 4 * br * this_block->src_stride + 4 * bc;
            ++block;
        }
    }
}

static void sum_intra_stats(VP8_COMP *cpi, MACROBLOCK *x)
{
    const MACROBLOCKD *xd = & x->e_mbd;
    const MB_PREDICTION_MODE m = xd->mode_info_context->mbmi.mode;
    const MB_PREDICTION_MODE uvm = xd->mode_info_context->mbmi.uv_mode;
John Koleszar's avatar
John Koleszar committed

#ifdef MODE_STATS
    const int is_key = cpi->common.frame_type == KEY_FRAME;

    ++ (is_key ? uv_modes : inter_uv_modes)[uvm];

    if (m == B_PRED)
    {
        unsigned int *const bct = is_key ? b_modes : inter_b_modes;

        int b = 0;

        do
        {
            ++ bct[xd->block[b].bmi.mode];
        }
        while (++b < 16);
    }

#endif

    ++cpi->ymode_count[m];
    ++cpi->uv_mode_count[uvm];

}
int vp8cx_encode_intra_macro_block(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t)
{
    int Error4x4, Error16x16, error_uv;
    B_PREDICTION_MODE intra_bmodes[16];
    int rate4x4, rate16x16, rateuv;
    int dist4x4, dist16x16, distuv;
    int rate = 0;
    int rate4x4_tokenonly = 0;
    int rate16x16_tokenonly = 0;
    int rateuv_tokenonly = 0;
    int i;

    x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
John Koleszar's avatar
John Koleszar committed

#if !(CONFIG_REALTIME_ONLY)

    if (cpi->sf.RD || cpi->compressor_speed != 2)
    {
        Error4x4 = vp8_rd_pick_intra4x4mby_modes(cpi, x, &rate4x4, &rate4x4_tokenonly, &dist4x4);

        //save the b modes for possible later use
        for (i = 0; i < 16; i++)
            intra_bmodes[i] = x->e_mbd.block[i].bmi.mode;

        Error16x16 = vp8_rd_pick_intra16x16mby_mode(cpi, x, &rate16x16, &rate16x16_tokenonly, &dist16x16);

        error_uv = vp8_rd_pick_intra_mbuv_mode(cpi, x, &rateuv, &rateuv_tokenonly, &distuv);

        vp8_encode_intra16x16mbuv(IF_RTCD(&cpi->rtcd), x);
        rate += rateuv;

        if (Error4x4 < Error16x16)
        {
            rate += rate4x4;
            x->e_mbd.mode_info_context->mbmi.mode = B_PRED;
John Koleszar's avatar
John Koleszar committed

            // get back the intra block modes
            for (i = 0; i < 16; i++)
                x->e_mbd.block[i].bmi.mode = intra_bmodes[i];

            vp8_encode_intra4x4mby(IF_RTCD(&cpi->rtcd), x);
            cpi->prediction_error += Error4x4 ;
#if 0
            // Experimental RD code
            cpi->frame_distortion += dist4x4;
#endif
        }
        else
        {
            vp8_encode_intra16x16mby(IF_RTCD(&cpi->rtcd), x);
            rate += rate16x16;

#if 0
            // Experimental RD code
            cpi->prediction_error += Error16x16;
            cpi->frame_distortion += dist16x16;
#endif
        }

        sum_intra_stats(cpi, x);

        vp8_tokenize_mb(cpi, &x->e_mbd, t);
    }
    else
#endif
    {

        int rate2, distortion2;
        MB_PREDICTION_MODE mode, best_mode = DC_PRED;
        int this_rd;
        Error16x16 = INT_MAX;

        for (mode = DC_PRED; mode <= TM_PRED; mode ++)
        {
            x->e_mbd.mode_info_context->mbmi.mode = mode;
John Koleszar's avatar
John Koleszar committed
            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);

        if (Error4x4 < Error16x16)
        {
            x->e_mbd.mode_info_context->mbmi.mode = B_PRED;
John Koleszar's avatar
John Koleszar committed
            vp8_encode_intra4x4mby(IF_RTCD(&cpi->rtcd), x);
            cpi->prediction_error += Error4x4;
        }
        else
        {
            x->e_mbd.mode_info_context->mbmi.mode = best_mode;
John Koleszar's avatar
John Koleszar committed
            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(MACROBLOCKD *x);
John Koleszar's avatar
John Koleszar committed

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->mode_info_context->mbmi.segment_id];
John Koleszar's avatar
John Koleszar committed
    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->mode_info_context->mbmi.segment_id == 1) &&
                ((xd->mode_info_context->mbmi.ref_frame != LAST_FRAME) || (xd->mode_info_context->mbmi.mode != ZEROMV)))
John Koleszar's avatar
John Koleszar committed
            {
                xd->mode_info_context->mbmi.segment_id = 0;
John Koleszar's avatar
John Koleszar committed
            }
        }

        // Experimental code. Special case for gf and arf zeromv modes. Increase zbin size to supress noise
        if (cpi->zbin_mode_boost_enabled)
        {
            if ( xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME )
                 cpi->zbin_mode_boost = 0;
John Koleszar's avatar
John Koleszar committed
            else
            {
                if (xd->mode_info_context->mbmi.mode == ZEROMV)
                {
                    if (xd->mode_info_context->mbmi.ref_frame != LAST_FRAME)
                        cpi->zbin_mode_boost = GF_ZEROMV_ZBIN_BOOST;
                    else
                        cpi->zbin_mode_boost = LF_ZEROMV_ZBIN_BOOST;
                }
                else if (xd->mode_info_context->mbmi.mode == SPLITMV)
                    cpi->zbin_mode_boost = 0;
                else
                    cpi->zbin_mode_boost = MV_ZBIN_BOOST;
            }
John Koleszar's avatar
John Koleszar committed
        }
        else
            cpi->zbin_mode_boost = 0;
John Koleszar's avatar
John Koleszar committed

        vp8cx_mb_init_quantizer(cpi,  x);
    }

    cpi->count_mb_ref_frame_usage[xd->mode_info_context->mbmi.ref_frame] ++;
    if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME)
John Koleszar's avatar
John Koleszar committed
    {
        vp8_encode_intra16x16mbuv(IF_RTCD(&cpi->rtcd), x);

        if (xd->mode_info_context->mbmi.mode == B_PRED)
John Koleszar's avatar
John Koleszar committed
        {
            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];
John Koleszar's avatar
John Koleszar committed

        vp8_find_near_mvs(xd, xd->mode_info_context,
                          &nearest, &nearby, &best_ref_mv, mdcounts, xd->mode_info_context->mbmi.ref_frame, cpi->common.ref_frame_sign_bias);
John Koleszar's avatar
John Koleszar committed

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

        if (xd->mode_info_context->mbmi.ref_frame == LAST_FRAME)
            ref_fb_idx = cpi->common.lst_fb_idx;
        else if (xd->mode_info_context->mbmi.ref_frame == GOLDEN_FRAME)
            ref_fb_idx = cpi->common.gld_fb_idx;
John Koleszar's avatar
John Koleszar committed
        else
            ref_fb_idx = cpi->common.alt_fb_idx;

        xd->pre.y_buffer = cpi->common.yv12_fb[ref_fb_idx].y_buffer + recon_yoffset;
        xd->pre.u_buffer = cpi->common.yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
        xd->pre.v_buffer = cpi->common.yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
        if (xd->mode_info_context->mbmi.mode == SPLITMV)
John Koleszar's avatar
John Koleszar committed
        {
            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->mode_info_context->mbmi.mode == NEWMV)
John Koleszar's avatar
John Koleszar committed
        {
            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.mode_info_context->mbmi.force_no_skip)
John Koleszar's avatar
John Koleszar committed
        {
            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->mode_info_context->mbmi.mb_skip_coeff = 0;
John Koleszar's avatar
John Koleszar committed

        }
        else
            vp8_stuff_inter16x16(x);
    }

    if (!x->skip)
        vp8_tokenize_mb(cpi, xd, t);
    else
    {
        if (cpi->common.mb_no_coeff_skip)
        {
            if (xd->mode_info_context->mbmi.mode != B_PRED && xd->mode_info_context->mbmi.mode != SPLITMV)
                xd->mode_info_context->mbmi.dc_diff = 0;
John Koleszar's avatar
John Koleszar committed
            else
                xd->mode_info_context->mbmi.dc_diff = 1;
            xd->mode_info_context->mbmi.mb_skip_coeff = 1;
John Koleszar's avatar
John Koleszar committed
            cpi->skip_true_count ++;
            vp8_fix_contexts(xd);
John Koleszar's avatar
John Koleszar committed
        }
        else
        {
            vp8_stuff_mb(cpi, xd, t);
            xd->mode_info_context->mbmi.mb_skip_coeff = 0;
John Koleszar's avatar
John Koleszar committed
            cpi->skip_false_count ++;
        }
    }

    return rate;
}