1474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org/*
2474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *
4474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  Use of this source code is governed by a BSD-style license
5474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  that can be found in the LICENSE file in the root of the source
6474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  tree. An additional intellectual property rights grant can be found
7474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  in the file PATENTS.  All contributing project authors may
8474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  be found in the AUTHORS file in the root of the source tree.
9474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org */
10474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
11474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
12167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org#include "vpx_config.h"
136fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#include "vp8_rtcd.h"
14474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "encodemb.h"
15474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "vp8/common/reconinter.h"
16474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "quantize.h"
17474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "tokenize.h"
18474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "vp8/common/invtrans.h"
19474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "vpx_mem/vpx_mem.h"
20474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "rdopt.h"
21474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
22474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgvoid vp8_subtract_b_c(BLOCK *be, BLOCKD *bd, int pitch)
23474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
24474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    unsigned char *src_ptr = (*(be->base_src) + be->src);
25474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    short *diff_ptr = be->src_diff;
26474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    unsigned char *pred_ptr = bd->predictor;
27474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int src_stride = be->src_stride;
28474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
29474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int r, c;
30474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
31474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    for (r = 0; r < 4; r++)
32474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
33474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        for (c = 0; c < 4; c++)
34474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        {
35474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            diff_ptr[c] = src_ptr[c] - pred_ptr[c];
36474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        }
37474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
38474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        diff_ptr += pitch;
39474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        pred_ptr += pitch;
40474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        src_ptr  += src_stride;
41474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
42474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
43474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
44167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.orgvoid vp8_subtract_mbuv_c(short *diff, unsigned char *usrc, unsigned char *vsrc,
45167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                         int src_stride, unsigned char *upred,
46167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                         unsigned char *vpred, int pred_stride)
47474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
48474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    short *udiff = diff + 256;
49474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    short *vdiff = diff + 320;
50474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
51474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int r, c;
52474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
53474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    for (r = 0; r < 8; r++)
54474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
55474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        for (c = 0; c < 8; c++)
56474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        {
57474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            udiff[c] = usrc[c] - upred[c];
58474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        }
59474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
60474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        udiff += 8;
61167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        upred += pred_stride;
62167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        usrc  += src_stride;
63474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
64474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
65474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    for (r = 0; r < 8; r++)
66474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
67474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        for (c = 0; c < 8; c++)
68474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        {
69474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            vdiff[c] = vsrc[c] - vpred[c];
70474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        }
71474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
72474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        vdiff += 8;
73167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        vpred += pred_stride;
74167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        vsrc  += src_stride;
75474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
76474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
77474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
78167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.orgvoid vp8_subtract_mby_c(short *diff, unsigned char *src, int src_stride,
79167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                        unsigned char *pred, int pred_stride)
80474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
81474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int r, c;
82474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
83474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    for (r = 0; r < 16; r++)
84474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
85474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        for (c = 0; c < 16; c++)
86474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        {
87474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            diff[c] = src[c] - pred[c];
88474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        }
89474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
90474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        diff += 16;
91167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        pred += pred_stride;
92167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        src  += src_stride;
93474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
94474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
95474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
965c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.orgstatic void vp8_subtract_mb(MACROBLOCK *x)
97474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
98474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    BLOCK *b = &x->block[0];
99474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
1005c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org    vp8_subtract_mby(x->src_diff, *(b->base_src),
101167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        b->src_stride, x->e_mbd.dst.y_buffer, x->e_mbd.dst.y_stride);
1025c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org    vp8_subtract_mbuv(x->src_diff, x->src.u_buffer,
103167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        x->src.v_buffer, x->src.uv_stride, x->e_mbd.dst.u_buffer,
104167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        x->e_mbd.dst.v_buffer, x->e_mbd.dst.uv_stride);
105474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
106474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
107474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstatic void build_dcblock(MACROBLOCK *x)
108474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
109474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    short *src_diff_ptr = &x->src_diff[384];
110474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int i;
111474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
112474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    for (i = 0; i < 16; i++)
113474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
114474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        src_diff_ptr[i] = x->coeff[i * 16];
115474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
116474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
117474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
118474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgvoid vp8_transform_mbuv(MACROBLOCK *x)
119474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
120474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int i;
121474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
122474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    for (i = 16; i < 24; i += 2)
123474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
1245c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org        x->short_fdct8x4(&x->block[i].src_diff[0],
125474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            &x->block[i].coeff[0], 16);
126474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
127474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
128474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
129474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
130474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgvoid vp8_transform_intra_mby(MACROBLOCK *x)
131474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
132474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int i;
133474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
134474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    for (i = 0; i < 16; i += 2)
135474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
1365c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org        x->short_fdct8x4(&x->block[i].src_diff[0],
137474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            &x->block[i].coeff[0], 32);
138474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
139474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
140ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org    /* build dc block from 16 y dc values */
141474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    build_dcblock(x);
142474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
143ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org    /* do 2nd order transform on the dc block */
144474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    x->short_walsh4x4(&x->block[24].src_diff[0],
145474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        &x->block[24].coeff[0], 8);
146474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
147474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
148474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
149474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
150474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstatic void transform_mb(MACROBLOCK *x)
151474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
152474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int i;
153474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
154474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    for (i = 0; i < 16; i += 2)
155474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
1565c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org        x->short_fdct8x4(&x->block[i].src_diff[0],
157474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            &x->block[i].coeff[0], 32);
158474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
159474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
160ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org    /* build dc block from 16 y dc values */
161474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    if (x->e_mbd.mode_info_context->mbmi.mode != SPLITMV)
162474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        build_dcblock(x);
163474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
164474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    for (i = 16; i < 24; i += 2)
165474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
1665c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org        x->short_fdct8x4(&x->block[i].src_diff[0],
167474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            &x->block[i].coeff[0], 16);
168474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
169474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
170ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org    /* do 2nd order transform on the dc block */
171474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    if (x->e_mbd.mode_info_context->mbmi.mode != SPLITMV)
172474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        x->short_walsh4x4(&x->block[24].src_diff[0],
173474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        &x->block[24].coeff[0], 8);
174474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
175474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
176474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
177474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
178474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstatic void transform_mby(MACROBLOCK *x)
179474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
180474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int i;
181474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
182474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    for (i = 0; i < 16; i += 2)
183474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
1845c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org        x->short_fdct8x4(&x->block[i].src_diff[0],
185474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            &x->block[i].coeff[0], 32);
186474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
187474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
188ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org    /* build dc block from 16 y dc values */
189474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    if (x->e_mbd.mode_info_context->mbmi.mode != SPLITMV)
190474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
191474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        build_dcblock(x);
192474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        x->short_walsh4x4(&x->block[24].src_diff[0],
193474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            &x->block[24].coeff[0], 8);
194474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
195474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
196474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
197474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
198474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
199474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#define RDTRUNC(RM,DM,R,D) ( (128+(R)*(RM)) & 0xFF )
200474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
201474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgtypedef struct vp8_token_state vp8_token_state;
202474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
203474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstruct vp8_token_state{
204474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  int           rate;
205474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  int           error;
206474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  signed char   next;
207474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  signed char   token;
208474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  short         qc;
209474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org};
210474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
211ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org/* TODO: experiments to find optimal multiple numbers */
212474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#define Y1_RD_MULT 4
213474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#define UV_RD_MULT 2
214474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#define Y2_RD_MULT 16
215474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
216474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstatic const int plane_rd_mult[4]=
217474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
218474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    Y1_RD_MULT,
219474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    Y2_RD_MULT,
220474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    UV_RD_MULT,
221474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    Y1_RD_MULT
222474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org};
223474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
224474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstatic void optimize_b(MACROBLOCK *mb, int ib, int type,
2255c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org                       ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l)
226474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
227474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    BLOCK *b;
228474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    BLOCKD *d;
229474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    vp8_token_state tokens[17][2];
230474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    unsigned best_mask[2];
231474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    const short *dequant_ptr;
232474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    const short *coeff_ptr;
233474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    short *qcoeff_ptr;
234474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    short *dqcoeff_ptr;
235474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int eob;
236474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int i0;
237474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int rc;
238474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int x;
239474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int sz = 0;
240474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int next;
241474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int rdmult;
242474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int rddiv;
243474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int final_eob;
244474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int rd_cost0;
245474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int rd_cost1;
246474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int rate0;
247474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int rate1;
248474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int error0;
249474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int error1;
250474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int t0;
251474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int t1;
252474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int best;
253474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int band;
254474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int pt;
255474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int i;
256474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int err_mult = plane_rd_mult[type];
257474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
258474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    b = &mb->block[ib];
259474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    d = &mb->e_mbd.block[ib];
260474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
261474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    dequant_ptr = d->dequant;
262474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    coeff_ptr = b->coeff;
263474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    qcoeff_ptr = d->qcoeff;
264474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    dqcoeff_ptr = d->dqcoeff;
265474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    i0 = !type;
266167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    eob = *d->eob;
267474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
268474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    /* Now set up a Viterbi trellis to evaluate alternative roundings. */
269474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    rdmult = mb->rdmult * err_mult;
270474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    if(mb->e_mbd.mode_info_context->mbmi.ref_frame==INTRA_FRAME)
271474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        rdmult = (rdmult * 9)>>4;
272474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
273474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    rddiv = mb->rddiv;
274474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    best_mask[0] = best_mask[1] = 0;
275474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    /* Initialize the sentinel node of the trellis. */
276474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    tokens[eob][0].rate = 0;
277474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    tokens[eob][0].error = 0;
278474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    tokens[eob][0].next = 16;
279474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    tokens[eob][0].token = DCT_EOB_TOKEN;
280474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    tokens[eob][0].qc = 0;
281474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    *(tokens[eob] + 1) = *(tokens[eob] + 0);
282474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    next = eob;
283474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    for (i = eob; i-- > i0;)
284474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
285474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        int base_bits;
286474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        int d2;
287474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        int dx;
288474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
289474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        rc = vp8_default_zig_zag1d[i];
290474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        x = qcoeff_ptr[rc];
291474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        /* Only add a trellis state for non-zero coefficients. */
292474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        if (x)
293474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        {
294474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            int shortcut=0;
295474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            error0 = tokens[next][0].error;
296474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            error1 = tokens[next][1].error;
297474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            /* Evaluate the first possibility for this state. */
298474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            rate0 = tokens[next][0].rate;
299474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            rate1 = tokens[next][1].rate;
300474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            t0 = (vp8_dct_value_tokens_ptr + x)->Token;
301474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            /* Consider both possible successor states. */
302474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            if (next < 16)
303474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            {
304474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                band = vp8_coef_bands[i + 1];
305474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                pt = vp8_prev_token_class[t0];
306474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                rate0 +=
307474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                    mb->token_costs[type][band][pt][tokens[next][0].token];
308474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                rate1 +=
309474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                    mb->token_costs[type][band][pt][tokens[next][1].token];
310474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            }
311474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0);
312474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1);
313474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            if (rd_cost0 == rd_cost1)
314474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            {
315474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                rd_cost0 = RDTRUNC(rdmult, rddiv, rate0, error0);
316474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                rd_cost1 = RDTRUNC(rdmult, rddiv, rate1, error1);
317474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            }
318474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            /* And pick the best. */
319474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            best = rd_cost1 < rd_cost0;
320474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            base_bits = *(vp8_dct_value_cost_ptr + x);
321474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            dx = dqcoeff_ptr[rc] - coeff_ptr[rc];
322474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            d2 = dx*dx;
323474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            tokens[i][0].rate = base_bits + (best ? rate1 : rate0);
324474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            tokens[i][0].error = d2 + (best ? error1 : error0);
325474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            tokens[i][0].next = next;
326474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            tokens[i][0].token = t0;
327474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            tokens[i][0].qc = x;
328474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            best_mask[0] |= best << i;
329474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            /* Evaluate the second possibility for this state. */
330474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            rate0 = tokens[next][0].rate;
331474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            rate1 = tokens[next][1].rate;
332474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
333474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            if((abs(x)*dequant_ptr[rc]>abs(coeff_ptr[rc])) &&
334474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org               (abs(x)*dequant_ptr[rc]<abs(coeff_ptr[rc])+dequant_ptr[rc]))
335474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                shortcut = 1;
336474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            else
337474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                shortcut = 0;
338474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
339474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            if(shortcut)
340474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            {
341474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                sz = -(x < 0);
342474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                x -= 2*sz + 1;
343474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            }
344474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
345474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            /* Consider both possible successor states. */
346474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            if (!x)
347474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            {
348474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                /* If we reduced this coefficient to zero, check to see if
349474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                 *  we need to move the EOB back here.
350474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                 */
351474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                t0 = tokens[next][0].token == DCT_EOB_TOKEN ?
352474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                    DCT_EOB_TOKEN : ZERO_TOKEN;
353474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                t1 = tokens[next][1].token == DCT_EOB_TOKEN ?
354474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                    DCT_EOB_TOKEN : ZERO_TOKEN;
355474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            }
356474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            else
357474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            {
358474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                t0=t1 = (vp8_dct_value_tokens_ptr + x)->Token;
359474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            }
360474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            if (next < 16)
361474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            {
362474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                band = vp8_coef_bands[i + 1];
363474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                if(t0!=DCT_EOB_TOKEN)
364474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                {
365474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                    pt = vp8_prev_token_class[t0];
366474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                    rate0 += mb->token_costs[type][band][pt][
367474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                        tokens[next][0].token];
368474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                }
369474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                if(t1!=DCT_EOB_TOKEN)
370474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                {
371474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                    pt = vp8_prev_token_class[t1];
372474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                    rate1 += mb->token_costs[type][band][pt][
373474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                        tokens[next][1].token];
374474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                }
375474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            }
376474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
377474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0);
378474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1);
379474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            if (rd_cost0 == rd_cost1)
380474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            {
381474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                rd_cost0 = RDTRUNC(rdmult, rddiv, rate0, error0);
382474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                rd_cost1 = RDTRUNC(rdmult, rddiv, rate1, error1);
383474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            }
384474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            /* And pick the best. */
385474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            best = rd_cost1 < rd_cost0;
386474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            base_bits = *(vp8_dct_value_cost_ptr + x);
387474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
388474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            if(shortcut)
389474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            {
390474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                dx -= (dequant_ptr[rc] + sz) ^ sz;
391474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                d2 = dx*dx;
392474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            }
393474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            tokens[i][1].rate = base_bits + (best ? rate1 : rate0);
394474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            tokens[i][1].error = d2 + (best ? error1 : error0);
395474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            tokens[i][1].next = next;
396474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            tokens[i][1].token =best?t1:t0;
397474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            tokens[i][1].qc = x;
398474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            best_mask[1] |= best << i;
399474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            /* Finally, make this the new head of the trellis. */
400474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            next = i;
401474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        }
402474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        /* There's no choice to make for a zero coefficient, so we don't
403474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org         *  add a new trellis node, but we do need to update the costs.
404474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org         */
405474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        else
406474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        {
407474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            band = vp8_coef_bands[i + 1];
408474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            t0 = tokens[next][0].token;
409474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            t1 = tokens[next][1].token;
410474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            /* Update the cost of each path if we're past the EOB token. */
411474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            if (t0 != DCT_EOB_TOKEN)
412474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            {
413474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                tokens[next][0].rate += mb->token_costs[type][band][0][t0];
414474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                tokens[next][0].token = ZERO_TOKEN;
415474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            }
416474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            if (t1 != DCT_EOB_TOKEN)
417474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            {
418474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                tokens[next][1].rate += mb->token_costs[type][band][0][t1];
419474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                tokens[next][1].token = ZERO_TOKEN;
420474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            }
421474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            /* Don't update next, because we didn't add a new node. */
422474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        }
423474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
424474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
425474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    /* Now pick the best path through the whole trellis. */
426474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    band = vp8_coef_bands[i + 1];
427474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
428474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    rate0 = tokens[next][0].rate;
429474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    rate1 = tokens[next][1].rate;
430474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    error0 = tokens[next][0].error;
431474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    error1 = tokens[next][1].error;
432474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    t0 = tokens[next][0].token;
433474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    t1 = tokens[next][1].token;
434474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    rate0 += mb->token_costs[type][band][pt][t0];
435474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    rate1 += mb->token_costs[type][band][pt][t1];
436474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0);
437474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1);
438474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    if (rd_cost0 == rd_cost1)
439474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
440474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        rd_cost0 = RDTRUNC(rdmult, rddiv, rate0, error0);
441474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        rd_cost1 = RDTRUNC(rdmult, rddiv, rate1, error1);
442474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
443474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    best = rd_cost1 < rd_cost0;
444474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    final_eob = i0 - 1;
445474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    for (i = next; i < eob; i = next)
446474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
447474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        x = tokens[i][best].qc;
448474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        if (x)
449474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            final_eob = i;
450474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        rc = vp8_default_zig_zag1d[i];
451474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        qcoeff_ptr[rc] = x;
452474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        dqcoeff_ptr[rc] = x * dequant_ptr[rc];
453474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        next = tokens[i][best].next;
454474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        best = (best_mask[best] >> i) & 1;
455474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
456474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    final_eob++;
457474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
458167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    *a = *l = (final_eob != !type);
459167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    *d->eob = (char)final_eob;
460167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org}
461167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.orgstatic void check_reset_2nd_coeffs(MACROBLOCKD *x, int type,
462167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                                   ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l)
463167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org{
464167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    int sum=0;
465167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    int i;
466167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    BLOCKD *bd = &x->block[24];
467167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org
468167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    if(bd->dequant[0]>=35 && bd->dequant[1]>=35)
469167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        return;
470167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org
471167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    for(i=0;i<(*bd->eob);i++)
472167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    {
473167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        int coef = bd->dqcoeff[vp8_default_zig_zag1d[i]];
474167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        sum+= (coef>=0)?coef:-coef;
475167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        if(sum>=35)
476167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org            return;
477167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    }
478167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    /**************************************************************************
479167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    our inverse hadamard transform effectively is weighted sum of all 16 inputs
480167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    with weight either 1 or -1. It has a last stage scaling of (sum+3)>>3. And
481167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    dc only idct is (dc+4)>>3. So if all the sums are between -35 and 29, the
482167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    output after inverse wht and idct will be all zero. A sum of absolute value
483167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    smaller than 35 guarantees all 16 different (+1/-1) weighted sums in wht
484167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    fall between -35 and +35.
485167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    **************************************************************************/
486167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    if(sum < 35)
487167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    {
488167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        for(i=0;i<(*bd->eob);i++)
489167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        {
490167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org            int rc = vp8_default_zig_zag1d[i];
491167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org            bd->qcoeff[rc]=0;
492167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org            bd->dqcoeff[rc]=0;
493167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        }
494167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        *bd->eob = 0;
495167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        *a = *l = (*bd->eob != !type);
496167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    }
497474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
498474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
4995c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.orgstatic void optimize_mb(MACROBLOCK *x)
500474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
501474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int b;
502474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int type;
503474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int has_2nd_order;
504167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org
505474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    ENTROPY_CONTEXT_PLANES t_above, t_left;
506474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    ENTROPY_CONTEXT *ta;
507474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    ENTROPY_CONTEXT *tl;
508474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
509474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    vpx_memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
510474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    vpx_memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
511474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
512474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    ta = (ENTROPY_CONTEXT *)&t_above;
513474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    tl = (ENTROPY_CONTEXT *)&t_left;
514474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
515474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED
516474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        && x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
517474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    type = has_2nd_order ? PLANE_TYPE_Y_NO_DC : PLANE_TYPE_Y_WITH_DC;
518474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
519474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    for (b = 0; b < 16; b++)
520474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
521474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        optimize_b(x, b, type,
5225c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org            ta + vp8_block2above[b], tl + vp8_block2left[b]);
523474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
524474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
525474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    for (b = 16; b < 24; b++)
526474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
527474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        optimize_b(x, b, PLANE_TYPE_UV,
5285c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org            ta + vp8_block2above[b], tl + vp8_block2left[b]);
529474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
530474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
531474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    if (has_2nd_order)
532474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
533474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        b=24;
534474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        optimize_b(x, b, PLANE_TYPE_Y2,
5355c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org            ta + vp8_block2above[b], tl + vp8_block2left[b]);
536167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        check_reset_2nd_coeffs(&x->e_mbd, PLANE_TYPE_Y2,
537167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org            ta + vp8_block2above[b], tl + vp8_block2left[b]);
538474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
539474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
540474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
541474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
5425c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.orgvoid vp8_optimize_mby(MACROBLOCK *x)
543474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
544474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int b;
545474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int type;
546474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int has_2nd_order;
547474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
548474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    ENTROPY_CONTEXT_PLANES t_above, t_left;
549474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    ENTROPY_CONTEXT *ta;
550474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    ENTROPY_CONTEXT *tl;
551474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
552474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    if (!x->e_mbd.above_context)
553474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        return;
554474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
555474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    if (!x->e_mbd.left_context)
556474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        return;
557474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
558474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    vpx_memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
559474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    vpx_memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
560474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
561474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    ta = (ENTROPY_CONTEXT *)&t_above;
562474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    tl = (ENTROPY_CONTEXT *)&t_left;
563474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
564474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED
565474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        && x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
566474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    type = has_2nd_order ? PLANE_TYPE_Y_NO_DC : PLANE_TYPE_Y_WITH_DC;
567474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
568474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    for (b = 0; b < 16; b++)
569474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
570474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        optimize_b(x, b, type,
5715c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org            ta + vp8_block2above[b], tl + vp8_block2left[b]);
572474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
573474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
574474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
575474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    if (has_2nd_order)
576474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
577474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        b=24;
578474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        optimize_b(x, b, PLANE_TYPE_Y2,
5795c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org            ta + vp8_block2above[b], tl + vp8_block2left[b]);
580167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        check_reset_2nd_coeffs(&x->e_mbd, PLANE_TYPE_Y2,
581167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org            ta + vp8_block2above[b], tl + vp8_block2left[b]);
582474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
583474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
584474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
5855c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.orgvoid vp8_optimize_mbuv(MACROBLOCK *x)
586474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
587474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    int b;
588474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    ENTROPY_CONTEXT_PLANES t_above, t_left;
589474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    ENTROPY_CONTEXT *ta;
590474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    ENTROPY_CONTEXT *tl;
591474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
592474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    if (!x->e_mbd.above_context)
593474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        return;
594474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
595474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    if (!x->e_mbd.left_context)
596474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        return;
597474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
598474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    vpx_memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
599474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    vpx_memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
600474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
601474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    ta = (ENTROPY_CONTEXT *)&t_above;
602474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    tl = (ENTROPY_CONTEXT *)&t_left;
603474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
604474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    for (b = 16; b < 24; b++)
605474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
606474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        optimize_b(x, b, PLANE_TYPE_UV,
6075c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org            ta + vp8_block2above[b], tl + vp8_block2left[b]);
608474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
609474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
610474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
6115c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.orgvoid vp8_encode_inter16x16(MACROBLOCK *x)
612474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
613474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    vp8_build_inter_predictors_mb(&x->e_mbd);
614474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
6155c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org    vp8_subtract_mb(x);
616474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
617474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    transform_mb(x);
618474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
619474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    vp8_quantize_mb(x);
620474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
621474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    if (x->optimize)
6225c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org        optimize_mb(x);
623474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
624474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
625474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org/* this funciton is used by first pass only */
6265c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.orgvoid vp8_encode_inter16x16y(MACROBLOCK *x)
627474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
628474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    BLOCK *b = &x->block[0];
629474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
630167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    vp8_build_inter16x16_predictors_mby(&x->e_mbd, x->e_mbd.dst.y_buffer,
631167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                                        x->e_mbd.dst.y_stride);
632474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
6335c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org    vp8_subtract_mby(x->src_diff, *(b->base_src),
634167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        b->src_stride, x->e_mbd.dst.y_buffer, x->e_mbd.dst.y_stride);
635474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
636474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    transform_mby(x);
637474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
638474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    vp8_quantize_mby(x);
639474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
6405c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org    vp8_inverse_transform_mby(&x->e_mbd);
641474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
642