/*
 *  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 "vpx_config.h"
#include "vp8_rtcd.h"
#include "./vpx_dsp_rtcd.h"
#include "vp8/encoder/quantize.h"
#include "vp8/common/reconintra4x4.h"
#include "encodemb.h"
#include "vp8/common/invtrans.h"
#include "encodeintra.h"


int vp8_encode_intra(VP8_COMP *cpi, MACROBLOCK *x, int use_dc_pred)
{

    int i;
    int intra_pred_var = 0;
    (void) cpi;

    if (use_dc_pred)
    {
        x->e_mbd.mode_info_context->mbmi.mode = DC_PRED;
        x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
        x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;

        vp8_encode_intra16x16mby(x);

        vp8_inverse_transform_mby(&x->e_mbd);
    }
    else
    {
        for (i = 0; i < 16; i++)
        {
            x->e_mbd.block[i].bmi.as_mode = B_DC_PRED;
            vp8_encode_intra4x4block(x, i);
        }
    }

    intra_pred_var = vpx_get_mb_ss(x->src_diff);

    return intra_pred_var;
}

void vp8_encode_intra4x4block(MACROBLOCK *x, int ib)
{
    BLOCKD *b = &x->e_mbd.block[ib];
    BLOCK *be = &x->block[ib];
    int dst_stride = x->e_mbd.dst.y_stride;
    unsigned char *dst = x->e_mbd.dst.y_buffer + b->offset;
    unsigned char *Above = dst - dst_stride;
    unsigned char *yleft = dst - 1;
    unsigned char top_left = Above[-1];

    vp8_intra4x4_predict(Above, yleft, dst_stride, b->bmi.as_mode,
                         b->predictor, 16, top_left);

    vp8_subtract_b(be, b, 16);

    x->short_fdct4x4(be->src_diff, be->coeff, 32);

    x->quantize_b(be, b);

    if (*b->eob > 1)
    {
      vp8_short_idct4x4llm(b->dqcoeff, b->predictor, 16, dst, dst_stride);
    }
    else
    {
      vp8_dc_only_idct_add(b->dqcoeff[0], b->predictor, 16, dst, dst_stride);
    }
}

void vp8_encode_intra4x4mby(MACROBLOCK *mb)
{
    int i;

    MACROBLOCKD *xd = &mb->e_mbd;
    intra_prediction_down_copy(xd, xd->dst.y_buffer - xd->dst.y_stride + 16);

    for (i = 0; i < 16; i++)
        vp8_encode_intra4x4block(mb, i);
    return;
}

void vp8_encode_intra16x16mby(MACROBLOCK *x)
{
    BLOCK *b = &x->block[0];
    MACROBLOCKD *xd = &x->e_mbd;

    vp8_build_intra_predictors_mby_s(xd,
                                         xd->dst.y_buffer - xd->dst.y_stride,
                                         xd->dst.y_buffer - 1,
                                         xd->dst.y_stride,
                                         xd->dst.y_buffer,
                                         xd->dst.y_stride);

    vp8_subtract_mby(x->src_diff, *(b->base_src),
        b->src_stride, xd->dst.y_buffer, xd->dst.y_stride);

    vp8_transform_intra_mby(x);

    vp8_quantize_mby(x);

    if (x->optimize)
        vp8_optimize_mby(x);
}

void vp8_encode_intra16x16mbuv(MACROBLOCK *x)
{
    MACROBLOCKD *xd = &x->e_mbd;

    vp8_build_intra_predictors_mbuv_s(xd, xd->dst.u_buffer - xd->dst.uv_stride,
                                      xd->dst.v_buffer - xd->dst.uv_stride,
                                      xd->dst.u_buffer - 1,
                                      xd->dst.v_buffer - 1,
                                      xd->dst.uv_stride,
                                      xd->dst.u_buffer, xd->dst.v_buffer,
                                      xd->dst.uv_stride);

    vp8_subtract_mbuv(x->src_diff, x->src.u_buffer,
        x->src.v_buffer, x->src.uv_stride, xd->dst.u_buffer,
        xd->dst.v_buffer, xd->dst.uv_stride);

    vp8_transform_mbuv(x);

    vp8_quantize_mbuv(x);

    if (x->optimize)
        vp8_optimize_mbuv(x);
}
