• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 
12 #include "vpx_ports/config.h"
13 #include "encodemb.h"
14 #include "vp8/common/reconinter.h"
15 #include "quantize.h"
16 #include "tokenize.h"
17 #include "vp8/common/invtrans.h"
18 #include "vp8/common/recon.h"
19 #include "vp8/common/reconintra.h"
20 #include "dct.h"
21 #include "vpx_mem/vpx_mem.h"
22 
23 #if CONFIG_RUNTIME_CPU_DETECT
24 #define IF_RTCD(x) (x)
25 #else
26 #define IF_RTCD(x) NULL
27 #endif
vp8_subtract_b_c(BLOCK * be,BLOCKD * bd,int pitch)28 void vp8_subtract_b_c(BLOCK *be, BLOCKD *bd, int pitch)
29 {
30     unsigned char *src_ptr = (*(be->base_src) + be->src);
31     short *diff_ptr = be->src_diff;
32     unsigned char *pred_ptr = bd->predictor;
33     int src_stride = be->src_stride;
34 
35     int r, c;
36 
37     for (r = 0; r < 4; r++)
38     {
39         for (c = 0; c < 4; c++)
40         {
41             diff_ptr[c] = src_ptr[c] - pred_ptr[c];
42         }
43 
44         diff_ptr += pitch;
45         pred_ptr += pitch;
46         src_ptr  += src_stride;
47     }
48 }
49 
vp8_subtract_mbuv_c(short * diff,unsigned char * usrc,unsigned char * vsrc,unsigned char * pred,int stride)50 void vp8_subtract_mbuv_c(short *diff, unsigned char *usrc, unsigned char *vsrc, unsigned char *pred, int stride)
51 {
52     short *udiff = diff + 256;
53     short *vdiff = diff + 320;
54     unsigned char *upred = pred + 256;
55     unsigned char *vpred = pred + 320;
56 
57     int r, c;
58 
59     for (r = 0; r < 8; r++)
60     {
61         for (c = 0; c < 8; c++)
62         {
63             udiff[c] = usrc[c] - upred[c];
64         }
65 
66         udiff += 8;
67         upred += 8;
68         usrc  += stride;
69     }
70 
71     for (r = 0; r < 8; r++)
72     {
73         for (c = 0; c < 8; c++)
74         {
75             vdiff[c] = vsrc[c] - vpred[c];
76         }
77 
78         vdiff += 8;
79         vpred += 8;
80         vsrc  += stride;
81     }
82 }
83 
vp8_subtract_mby_c(short * diff,unsigned char * src,unsigned char * pred,int stride)84 void vp8_subtract_mby_c(short *diff, unsigned char *src, unsigned char *pred, int stride)
85 {
86     int r, c;
87 
88     for (r = 0; r < 16; r++)
89     {
90         for (c = 0; c < 16; c++)
91         {
92             diff[c] = src[c] - pred[c];
93         }
94 
95         diff += 16;
96         pred += 16;
97         src  += stride;
98     }
99 }
100 
vp8_subtract_mb(const VP8_ENCODER_RTCD * rtcd,MACROBLOCK * x)101 static void vp8_subtract_mb(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
102 {
103     ENCODEMB_INVOKE(&rtcd->encodemb, submby)(x->src_diff, x->src.y_buffer, x->e_mbd.predictor, x->src.y_stride);
104     ENCODEMB_INVOKE(&rtcd->encodemb, submbuv)(x->src_diff, x->src.u_buffer, x->src.v_buffer, x->e_mbd.predictor, x->src.uv_stride);
105 }
106 
build_dcblock(MACROBLOCK * x)107 static void build_dcblock(MACROBLOCK *x)
108 {
109     short *src_diff_ptr = &x->src_diff[384];
110     int i;
111 
112     for (i = 0; i < 16; i++)
113     {
114         src_diff_ptr[i] = x->coeff[i * 16];
115     }
116 }
117 
vp8_transform_mbuv(MACROBLOCK * x)118 void vp8_transform_mbuv(MACROBLOCK *x)
119 {
120     int i;
121 
122     for (i = 16; i < 24; i += 2)
123     {
124         x->vp8_short_fdct8x4(&x->block[i].src_diff[0],
125             &x->block[i].coeff[0], 16);
126     }
127 }
128 
129 
vp8_transform_intra_mby(MACROBLOCK * x)130 void vp8_transform_intra_mby(MACROBLOCK *x)
131 {
132     int i;
133 
134     for (i = 0; i < 16; i += 2)
135     {
136         x->vp8_short_fdct8x4(&x->block[i].src_diff[0],
137             &x->block[i].coeff[0], 32);
138     }
139 
140     // build dc block from 16 y dc values
141     build_dcblock(x);
142 
143     // do 2nd order transform on the dc block
144     x->short_walsh4x4(&x->block[24].src_diff[0],
145         &x->block[24].coeff[0], 8);
146 
147 }
148 
149 
transform_mb(MACROBLOCK * x)150 static void transform_mb(MACROBLOCK *x)
151 {
152     int i;
153 
154     for (i = 0; i < 16; i += 2)
155     {
156         x->vp8_short_fdct8x4(&x->block[i].src_diff[0],
157             &x->block[i].coeff[0], 32);
158     }
159 
160     // build dc block from 16 y dc values
161     if (x->e_mbd.mode_info_context->mbmi.mode != SPLITMV)
162         build_dcblock(x);
163 
164     for (i = 16; i < 24; i += 2)
165     {
166         x->vp8_short_fdct8x4(&x->block[i].src_diff[0],
167             &x->block[i].coeff[0], 16);
168     }
169 
170     // do 2nd order transform on the dc block
171     if (x->e_mbd.mode_info_context->mbmi.mode != SPLITMV)
172         x->short_walsh4x4(&x->block[24].src_diff[0],
173         &x->block[24].coeff[0], 8);
174 
175 }
176 
177 
transform_mby(MACROBLOCK * x)178 static void transform_mby(MACROBLOCK *x)
179 {
180     int i;
181 
182     for (i = 0; i < 16; i += 2)
183     {
184         x->vp8_short_fdct8x4(&x->block[i].src_diff[0],
185             &x->block[i].coeff[0], 32);
186     }
187 
188     // build dc block from 16 y dc values
189     if (x->e_mbd.mode_info_context->mbmi.mode != SPLITMV)
190     {
191         build_dcblock(x);
192         x->short_walsh4x4(&x->block[24].src_diff[0],
193             &x->block[24].coeff[0], 8);
194     }
195 }
196 
197 
vp8_stuff_inter16x16(MACROBLOCK * x)198 void vp8_stuff_inter16x16(MACROBLOCK *x)
199 {
200     vp8_build_inter_predictors_mb_s(&x->e_mbd);
201     /*
202         // recon = copy from predictors to destination
203         {
204             BLOCKD *b = &x->e_mbd.block[0];
205             unsigned char *pred_ptr = b->predictor;
206             unsigned char *dst_ptr = *(b->base_dst) + b->dst;
207             int stride = b->dst_stride;
208 
209             int i;
210             for(i=0;i<16;i++)
211                 vpx_memcpy(dst_ptr+i*stride,pred_ptr+16*i,16);
212 
213             b = &x->e_mbd.block[16];
214             pred_ptr = b->predictor;
215             dst_ptr = *(b->base_dst) + b->dst;
216             stride = b->dst_stride;
217 
218             for(i=0;i<8;i++)
219                 vpx_memcpy(dst_ptr+i*stride,pred_ptr+8*i,8);
220 
221             b = &x->e_mbd.block[20];
222             pred_ptr = b->predictor;
223             dst_ptr = *(b->base_dst) + b->dst;
224             stride = b->dst_stride;
225 
226             for(i=0;i<8;i++)
227                 vpx_memcpy(dst_ptr+i*stride,pred_ptr+8*i,8);
228         }
229     */
230 }
231 
232 #if !(CONFIG_REALTIME_ONLY)
233 #define RDCOST(RM,DM,R,D) ( ((128+(R)*(RM)) >> 8) + (DM)*(D) )
234 #define RDTRUNC(RM,DM,R,D) ( (128+(R)*(RM)) & 0xFF )
235 
236 typedef struct vp8_token_state vp8_token_state;
237 
238 struct vp8_token_state{
239   int           rate;
240   int           error;
241   signed char   next;
242   signed char   token;
243   short         qc;
244 };
245 
246 // TODO: experiments to find optimal multiple numbers
247 #define Y1_RD_MULT 4
248 #define UV_RD_MULT 2
249 #define Y2_RD_MULT 16
250 
251 static const int plane_rd_mult[4]=
252 {
253     Y1_RD_MULT,
254     Y2_RD_MULT,
255     UV_RD_MULT,
256     Y1_RD_MULT
257 };
258 
optimize_b(MACROBLOCK * mb,int ib,int type,ENTROPY_CONTEXT * a,ENTROPY_CONTEXT * l,const VP8_ENCODER_RTCD * rtcd)259 static void optimize_b(MACROBLOCK *mb, int ib, int type,
260                        ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l,
261                        const VP8_ENCODER_RTCD *rtcd)
262 {
263     BLOCK *b;
264     BLOCKD *d;
265     vp8_token_state tokens[17][2];
266     unsigned best_mask[2];
267     const short *dequant_ptr;
268     const short *coeff_ptr;
269     short *qcoeff_ptr;
270     short *dqcoeff_ptr;
271     int eob;
272     int i0;
273     int rc;
274     int x;
275     int sz;
276     int next;
277     int rdmult;
278     int rddiv;
279     int final_eob;
280     int rd_cost0;
281     int rd_cost1;
282     int rate0;
283     int rate1;
284     int error0;
285     int error1;
286     int t0;
287     int t1;
288     int best;
289     int band;
290     int pt;
291     int i;
292     int err_mult = plane_rd_mult[type];
293 
294     b = &mb->block[ib];
295     d = &mb->e_mbd.block[ib];
296 
297     /* Enable this to test the effect of RDO as a replacement for the dynamic
298      *  zero bin instead of an augmentation of it.
299      */
300 #if 0
301     vp8_strict_quantize_b(b, d);
302 #endif
303 
304     dequant_ptr = d->dequant;
305     coeff_ptr = b->coeff;
306     qcoeff_ptr = d->qcoeff;
307     dqcoeff_ptr = d->dqcoeff;
308     i0 = !type;
309     eob = d->eob;
310 
311     /* Now set up a Viterbi trellis to evaluate alternative roundings. */
312     rdmult = mb->rdmult * err_mult;
313     if(mb->e_mbd.mode_info_context->mbmi.ref_frame==INTRA_FRAME)
314         rdmult = (rdmult * 9)>>4;
315 
316     rddiv = mb->rddiv;
317     best_mask[0] = best_mask[1] = 0;
318     /* Initialize the sentinel node of the trellis. */
319     tokens[eob][0].rate = 0;
320     tokens[eob][0].error = 0;
321     tokens[eob][0].next = 16;
322     tokens[eob][0].token = DCT_EOB_TOKEN;
323     tokens[eob][0].qc = 0;
324     *(tokens[eob] + 1) = *(tokens[eob] + 0);
325     next = eob;
326     for (i = eob; i-- > i0;)
327     {
328         int base_bits;
329         int d2;
330         int dx;
331 
332         rc = vp8_default_zig_zag1d[i];
333         x = qcoeff_ptr[rc];
334         /* Only add a trellis state for non-zero coefficients. */
335         if (x)
336         {
337             int shortcut=0;
338             error0 = tokens[next][0].error;
339             error1 = tokens[next][1].error;
340             /* Evaluate the first possibility for this state. */
341             rate0 = tokens[next][0].rate;
342             rate1 = tokens[next][1].rate;
343             t0 = (vp8_dct_value_tokens_ptr + x)->Token;
344             /* Consider both possible successor states. */
345             if (next < 16)
346             {
347                 band = vp8_coef_bands[i + 1];
348                 pt = vp8_prev_token_class[t0];
349                 rate0 +=
350                     mb->token_costs[type][band][pt][tokens[next][0].token];
351                 rate1 +=
352                     mb->token_costs[type][band][pt][tokens[next][1].token];
353             }
354             rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0);
355             rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1);
356             if (rd_cost0 == rd_cost1)
357             {
358                 rd_cost0 = RDTRUNC(rdmult, rddiv, rate0, error0);
359                 rd_cost1 = RDTRUNC(rdmult, rddiv, rate1, error1);
360             }
361             /* And pick the best. */
362             best = rd_cost1 < rd_cost0;
363             base_bits = *(vp8_dct_value_cost_ptr + x);
364             dx = dqcoeff_ptr[rc] - coeff_ptr[rc];
365             d2 = dx*dx;
366             tokens[i][0].rate = base_bits + (best ? rate1 : rate0);
367             tokens[i][0].error = d2 + (best ? error1 : error0);
368             tokens[i][0].next = next;
369             tokens[i][0].token = t0;
370             tokens[i][0].qc = x;
371             best_mask[0] |= best << i;
372             /* Evaluate the second possibility for this state. */
373             rate0 = tokens[next][0].rate;
374             rate1 = tokens[next][1].rate;
375 
376             if((abs(x)*dequant_ptr[rc]>abs(coeff_ptr[rc])) &&
377                (abs(x)*dequant_ptr[rc]<abs(coeff_ptr[rc])+dequant_ptr[rc]))
378                 shortcut = 1;
379             else
380                 shortcut = 0;
381 
382             if(shortcut)
383             {
384                 sz = -(x < 0);
385                 x -= 2*sz + 1;
386             }
387 
388             /* Consider both possible successor states. */
389             if (!x)
390             {
391                 /* If we reduced this coefficient to zero, check to see if
392                  *  we need to move the EOB back here.
393                  */
394                 t0 = tokens[next][0].token == DCT_EOB_TOKEN ?
395                     DCT_EOB_TOKEN : ZERO_TOKEN;
396                 t1 = tokens[next][1].token == DCT_EOB_TOKEN ?
397                     DCT_EOB_TOKEN : ZERO_TOKEN;
398             }
399             else
400             {
401                 t0=t1 = (vp8_dct_value_tokens_ptr + x)->Token;
402             }
403             if (next < 16)
404             {
405                 band = vp8_coef_bands[i + 1];
406                 if(t0!=DCT_EOB_TOKEN)
407                 {
408                     pt = vp8_prev_token_class[t0];
409                     rate0 += mb->token_costs[type][band][pt][
410                         tokens[next][0].token];
411                 }
412                 if(t1!=DCT_EOB_TOKEN)
413                 {
414                     pt = vp8_prev_token_class[t1];
415                     rate1 += mb->token_costs[type][band][pt][
416                         tokens[next][1].token];
417                 }
418             }
419 
420             rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0);
421             rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1);
422             if (rd_cost0 == rd_cost1)
423             {
424                 rd_cost0 = RDTRUNC(rdmult, rddiv, rate0, error0);
425                 rd_cost1 = RDTRUNC(rdmult, rddiv, rate1, error1);
426             }
427             /* And pick the best. */
428             best = rd_cost1 < rd_cost0;
429             base_bits = *(vp8_dct_value_cost_ptr + x);
430 
431             if(shortcut)
432             {
433                 dx -= (dequant_ptr[rc] + sz) ^ sz;
434                 d2 = dx*dx;
435             }
436             tokens[i][1].rate = base_bits + (best ? rate1 : rate0);
437             tokens[i][1].error = d2 + (best ? error1 : error0);
438             tokens[i][1].next = next;
439             tokens[i][1].token =best?t1:t0;
440             tokens[i][1].qc = x;
441             best_mask[1] |= best << i;
442             /* Finally, make this the new head of the trellis. */
443             next = i;
444         }
445         /* There's no choice to make for a zero coefficient, so we don't
446          *  add a new trellis node, but we do need to update the costs.
447          */
448         else
449         {
450             band = vp8_coef_bands[i + 1];
451             t0 = tokens[next][0].token;
452             t1 = tokens[next][1].token;
453             /* Update the cost of each path if we're past the EOB token. */
454             if (t0 != DCT_EOB_TOKEN)
455             {
456                 tokens[next][0].rate += mb->token_costs[type][band][0][t0];
457                 tokens[next][0].token = ZERO_TOKEN;
458             }
459             if (t1 != DCT_EOB_TOKEN)
460             {
461                 tokens[next][1].rate += mb->token_costs[type][band][0][t1];
462                 tokens[next][1].token = ZERO_TOKEN;
463             }
464             /* Don't update next, because we didn't add a new node. */
465         }
466     }
467 
468     /* Now pick the best path through the whole trellis. */
469     band = vp8_coef_bands[i + 1];
470     VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
471     rate0 = tokens[next][0].rate;
472     rate1 = tokens[next][1].rate;
473     error0 = tokens[next][0].error;
474     error1 = tokens[next][1].error;
475     t0 = tokens[next][0].token;
476     t1 = tokens[next][1].token;
477     rate0 += mb->token_costs[type][band][pt][t0];
478     rate1 += mb->token_costs[type][band][pt][t1];
479     rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0);
480     rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1);
481     if (rd_cost0 == rd_cost1)
482     {
483         rd_cost0 = RDTRUNC(rdmult, rddiv, rate0, error0);
484         rd_cost1 = RDTRUNC(rdmult, rddiv, rate1, error1);
485     }
486     best = rd_cost1 < rd_cost0;
487     final_eob = i0 - 1;
488     for (i = next; i < eob; i = next)
489     {
490         x = tokens[i][best].qc;
491         if (x)
492             final_eob = i;
493         rc = vp8_default_zig_zag1d[i];
494         qcoeff_ptr[rc] = x;
495         dqcoeff_ptr[rc] = x * dequant_ptr[rc];
496         next = tokens[i][best].next;
497         best = (best_mask[best] >> i) & 1;
498     }
499     final_eob++;
500 
501     d->eob = final_eob;
502     *a = *l = (d->eob != !type);
503 }
504 
optimize_mb(MACROBLOCK * x,const VP8_ENCODER_RTCD * rtcd)505 static void optimize_mb(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
506 {
507     int b;
508     int type;
509     int has_2nd_order;
510     ENTROPY_CONTEXT_PLANES t_above, t_left;
511     ENTROPY_CONTEXT *ta;
512     ENTROPY_CONTEXT *tl;
513 
514     vpx_memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
515     vpx_memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
516 
517     ta = (ENTROPY_CONTEXT *)&t_above;
518     tl = (ENTROPY_CONTEXT *)&t_left;
519 
520     has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED
521         && x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
522     type = has_2nd_order ? PLANE_TYPE_Y_NO_DC : PLANE_TYPE_Y_WITH_DC;
523 
524     for (b = 0; b < 16; b++)
525     {
526         optimize_b(x, b, type,
527             ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
528     }
529 
530     for (b = 16; b < 24; b++)
531     {
532         optimize_b(x, b, PLANE_TYPE_UV,
533             ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
534     }
535 
536     if (has_2nd_order)
537     {
538         b=24;
539         optimize_b(x, b, PLANE_TYPE_Y2,
540             ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
541     }
542 }
543 
544 
vp8_optimize_mby(MACROBLOCK * x,const VP8_ENCODER_RTCD * rtcd)545 void vp8_optimize_mby(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
546 {
547     int b;
548     int type;
549     int has_2nd_order;
550 
551     ENTROPY_CONTEXT_PLANES t_above, t_left;
552     ENTROPY_CONTEXT *ta;
553     ENTROPY_CONTEXT *tl;
554 
555     if (!x->e_mbd.above_context)
556         return;
557 
558     if (!x->e_mbd.left_context)
559         return;
560 
561     vpx_memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
562     vpx_memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
563 
564     ta = (ENTROPY_CONTEXT *)&t_above;
565     tl = (ENTROPY_CONTEXT *)&t_left;
566 
567     has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED
568         && x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
569     type = has_2nd_order ? PLANE_TYPE_Y_NO_DC : PLANE_TYPE_Y_WITH_DC;
570 
571     for (b = 0; b < 16; b++)
572     {
573         optimize_b(x, b, type,
574         ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
575     }
576 
577 
578     if (has_2nd_order)
579     {
580         b=24;
581         optimize_b(x, b, PLANE_TYPE_Y2,
582             ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
583     }
584 }
585 
vp8_optimize_mbuv(MACROBLOCK * x,const VP8_ENCODER_RTCD * rtcd)586 void vp8_optimize_mbuv(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
587 {
588     int b;
589     ENTROPY_CONTEXT_PLANES t_above, t_left;
590     ENTROPY_CONTEXT *ta;
591     ENTROPY_CONTEXT *tl;
592 
593     if (!x->e_mbd.above_context)
594         return;
595 
596     if (!x->e_mbd.left_context)
597         return;
598 
599     vpx_memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
600     vpx_memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
601 
602     ta = (ENTROPY_CONTEXT *)&t_above;
603     tl = (ENTROPY_CONTEXT *)&t_left;
604 
605     for (b = 16; b < 24; b++)
606     {
607         optimize_b(x, b, PLANE_TYPE_UV,
608             ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
609     }
610 }
611 #endif
612 
vp8_encode_inter16x16(const VP8_ENCODER_RTCD * rtcd,MACROBLOCK * x)613 void vp8_encode_inter16x16(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
614 {
615     vp8_build_inter_predictors_mb(&x->e_mbd);
616 
617     vp8_subtract_mb(rtcd, x);
618 
619     transform_mb(x);
620 
621     vp8_quantize_mb(x);
622 
623 #if !(CONFIG_REALTIME_ONLY)
624     if (x->optimize)
625         optimize_mb(x, rtcd);
626 #endif
627 
628     vp8_inverse_transform_mb(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
629 
630     RECON_INVOKE(&rtcd->common->recon, recon_mb)
631         (IF_RTCD(&rtcd->common->recon), &x->e_mbd);
632 }
633 
634 
635 /* this funciton is used by first pass only */
vp8_encode_inter16x16y(const VP8_ENCODER_RTCD * rtcd,MACROBLOCK * x)636 void vp8_encode_inter16x16y(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
637 {
638     vp8_build_inter_predictors_mby(&x->e_mbd);
639 
640     ENCODEMB_INVOKE(&rtcd->encodemb, submby)(x->src_diff, x->src.y_buffer, x->e_mbd.predictor, x->src.y_stride);
641 
642     transform_mby(x);
643 
644     vp8_quantize_mby(x);
645 
646     vp8_inverse_transform_mby(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
647 
648     RECON_INVOKE(&rtcd->common->recon, recon_mby)
649         (IF_RTCD(&rtcd->common->recon), &x->e_mbd);
650 }
651 
652 
vp8_encode_inter16x16uvrd(const VP8_ENCODER_RTCD * rtcd,MACROBLOCK * x)653 void vp8_encode_inter16x16uvrd(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
654 {
655     vp8_build_inter_predictors_mbuv(&x->e_mbd);
656     ENCODEMB_INVOKE(&rtcd->encodemb, submbuv)(x->src_diff, x->src.u_buffer, x->src.v_buffer, x->e_mbd.predictor, x->src.uv_stride);
657 
658     vp8_transform_mbuv(x);
659 
660     vp8_quantize_mbuv(x);
661 
662 }
663