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 "reconinter.h"
15 #include "quantize.h"
16 #include "tokenize.h"
17 #include "invtrans.h"
18 #include "recon.h"
19 #include "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
vp8_build_dcblock(MACROBLOCK * x)107 void vp8_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 vp8_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
vp8_transform_mb(MACROBLOCK * x)150 void vp8_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 vp8_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
vp8_transform_mby(MACROBLOCK * x)177 void vp8_transform_mby(MACROBLOCK *x)
178 {
179 int i;
180
181 for (i = 0; i < 16; i += 2)
182 {
183 x->vp8_short_fdct8x4(&x->block[i].src_diff[0],
184 &x->block[i].coeff[0], 32);
185 }
186
187 // build dc block from 16 y dc values
188 if (x->e_mbd.mode_info_context->mbmi.mode != SPLITMV)
189 {
190 vp8_build_dcblock(x);
191 x->short_walsh4x4(&x->block[24].src_diff[0],
192 &x->block[24].coeff[0], 8);
193 }
194 }
195
196
vp8_stuff_inter16x16(MACROBLOCK * x)197 void vp8_stuff_inter16x16(MACROBLOCK *x)
198 {
199 vp8_build_inter_predictors_mb_s(&x->e_mbd);
200 /*
201 // recon = copy from predictors to destination
202 {
203 BLOCKD *b = &x->e_mbd.block[0];
204 unsigned char *pred_ptr = b->predictor;
205 unsigned char *dst_ptr = *(b->base_dst) + b->dst;
206 int stride = b->dst_stride;
207
208 int i;
209 for(i=0;i<16;i++)
210 vpx_memcpy(dst_ptr+i*stride,pred_ptr+16*i,16);
211
212 b = &x->e_mbd.block[16];
213 pred_ptr = b->predictor;
214 dst_ptr = *(b->base_dst) + b->dst;
215 stride = b->dst_stride;
216
217 for(i=0;i<8;i++)
218 vpx_memcpy(dst_ptr+i*stride,pred_ptr+8*i,8);
219
220 b = &x->e_mbd.block[20];
221 pred_ptr = b->predictor;
222 dst_ptr = *(b->base_dst) + b->dst;
223 stride = b->dst_stride;
224
225 for(i=0;i<8;i++)
226 vpx_memcpy(dst_ptr+i*stride,pred_ptr+8*i,8);
227 }
228 */
229 }
230
231 #if !(CONFIG_REALTIME_ONLY)
232 #define RDCOST(RM,DM,R,D) ( ((128+(R)*(RM)) >> 8) + (DM)*(D) )
233 #define RDTRUNC(RM,DM,R,D) ( (128+(R)*(RM)) & 0xFF )
234
235 typedef struct vp8_token_state vp8_token_state;
236
237 struct vp8_token_state{
238 int rate;
239 int error;
240 signed char next;
241 signed char token;
242 short qc;
243 };
244
245 // TODO: experiments to find optimal multiple numbers
246 #define Y1_RD_MULT 1
247 #define UV_RD_MULT 1
248 #define Y2_RD_MULT 4
249
250 static const int plane_rd_mult[4]=
251 {
252 Y1_RD_MULT,
253 Y2_RD_MULT,
254 UV_RD_MULT,
255 Y1_RD_MULT
256 };
257
vp8_optimize_b(MACROBLOCK * mb,int ib,int type,ENTROPY_CONTEXT * a,ENTROPY_CONTEXT * l,const VP8_ENCODER_RTCD * rtcd)258 void vp8_optimize_b(MACROBLOCK *mb, int ib, int type,
259 ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l,
260 const VP8_ENCODER_RTCD *rtcd)
261 {
262 BLOCK *b;
263 BLOCKD *d;
264 vp8_token_state tokens[17][2];
265 unsigned best_mask[2];
266 const short *dequant_ptr;
267 const short *coeff_ptr;
268 short *qcoeff_ptr;
269 short *dqcoeff_ptr;
270 int eob;
271 int i0;
272 int rc;
273 int x;
274 int sz;
275 int next;
276 int path;
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 /* TODO: These should vary with the block type, since the quantizer does. */
313 rdmult = (mb->rdmult << 2)*err_mult;
314 rddiv = mb->rddiv;
315 best_mask[0] = best_mask[1] = 0;
316 /* Initialize the sentinel node of the trellis. */
317 tokens[eob][0].rate = 0;
318 tokens[eob][0].error = 0;
319 tokens[eob][0].next = 16;
320 tokens[eob][0].token = DCT_EOB_TOKEN;
321 tokens[eob][0].qc = 0;
322 *(tokens[eob] + 1) = *(tokens[eob] + 0);
323 next = eob;
324 for (i = eob; i-- > i0;)
325 {
326 int base_bits;
327 int d2;
328 int dx;
329
330 rc = vp8_default_zig_zag1d[i];
331 x = qcoeff_ptr[rc];
332 /* Only add a trellis state for non-zero coefficients. */
333 if (x)
334 {
335 int shortcut=0;
336 error0 = tokens[next][0].error;
337 error1 = tokens[next][1].error;
338 /* Evaluate the first possibility for this state. */
339 rate0 = tokens[next][0].rate;
340 rate1 = tokens[next][1].rate;
341 t0 = (vp8_dct_value_tokens_ptr + x)->Token;
342 /* Consider both possible successor states. */
343 if (next < 16)
344 {
345 band = vp8_coef_bands[i + 1];
346 pt = vp8_prev_token_class[t0];
347 rate0 +=
348 mb->token_costs[type][band][pt][tokens[next][0].token];
349 rate1 +=
350 mb->token_costs[type][band][pt][tokens[next][1].token];
351 }
352 rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0);
353 rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1);
354 if (rd_cost0 == rd_cost1)
355 {
356 rd_cost0 = RDTRUNC(rdmult, rddiv, rate0, error0);
357 rd_cost1 = RDTRUNC(rdmult, rddiv, rate1, error1);
358 }
359 /* And pick the best. */
360 best = rd_cost1 < rd_cost0;
361 base_bits = *(vp8_dct_value_cost_ptr + x);
362 dx = dqcoeff_ptr[rc] - coeff_ptr[rc];
363 d2 = dx*dx;
364 tokens[i][0].rate = base_bits + (best ? rate1 : rate0);
365 tokens[i][0].error = d2 + (best ? error1 : error0);
366 tokens[i][0].next = next;
367 tokens[i][0].token = t0;
368 tokens[i][0].qc = x;
369 best_mask[0] |= best << i;
370 /* Evaluate the second possibility for this state. */
371 rate0 = tokens[next][0].rate;
372 rate1 = tokens[next][1].rate;
373
374 if((abs(x)*dequant_ptr[rc]>abs(coeff_ptr[rc])) &&
375 (abs(x)*dequant_ptr[rc]<abs(coeff_ptr[rc])+dequant_ptr[rc]))
376 shortcut = 1;
377 else
378 shortcut = 0;
379
380 if(shortcut)
381 {
382 sz = -(x < 0);
383 x -= 2*sz + 1;
384 }
385
386 /* Consider both possible successor states. */
387 if (!x)
388 {
389 /* If we reduced this coefficient to zero, check to see if
390 * we need to move the EOB back here.
391 */
392 t0 = tokens[next][0].token == DCT_EOB_TOKEN ?
393 DCT_EOB_TOKEN : ZERO_TOKEN;
394 t1 = tokens[next][1].token == DCT_EOB_TOKEN ?
395 DCT_EOB_TOKEN : ZERO_TOKEN;
396 }
397 else
398 {
399 t0=t1 = (vp8_dct_value_tokens_ptr + x)->Token;
400 }
401 if (next < 16)
402 {
403 band = vp8_coef_bands[i + 1];
404 if(t0!=DCT_EOB_TOKEN)
405 {
406 pt = vp8_prev_token_class[t0];
407 rate0 += mb->token_costs[type][band][pt][
408 tokens[next][0].token];
409 }
410 if(t1!=DCT_EOB_TOKEN)
411 {
412 pt = vp8_prev_token_class[t1];
413 rate1 += mb->token_costs[type][band][pt][
414 tokens[next][1].token];
415 }
416 }
417
418 rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0);
419 rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1);
420 if (rd_cost0 == rd_cost1)
421 {
422 rd_cost0 = RDTRUNC(rdmult, rddiv, rate0, error0);
423 rd_cost1 = RDTRUNC(rdmult, rddiv, rate1, error1);
424 }
425 /* And pick the best. */
426 best = rd_cost1 < rd_cost0;
427 base_bits = *(vp8_dct_value_cost_ptr + x);
428
429 if(shortcut)
430 {
431 dx -= (dequant_ptr[rc] + sz) ^ sz;
432 d2 = dx*dx;
433 }
434 tokens[i][1].rate = base_bits + (best ? rate1 : rate0);
435 tokens[i][1].error = d2 + (best ? error1 : error0);
436 tokens[i][1].next = next;
437 tokens[i][1].token =best?t1:t0;
438 tokens[i][1].qc = x;
439 best_mask[1] |= best << i;
440 /* Finally, make this the new head of the trellis. */
441 next = i;
442 }
443 /* There's no choice to make for a zero coefficient, so we don't
444 * add a new trellis node, but we do need to update the costs.
445 */
446 else
447 {
448 band = vp8_coef_bands[i + 1];
449 t0 = tokens[next][0].token;
450 t1 = tokens[next][1].token;
451 /* Update the cost of each path if we're past the EOB token. */
452 if (t0 != DCT_EOB_TOKEN)
453 {
454 tokens[next][0].rate += mb->token_costs[type][band][0][t0];
455 tokens[next][0].token = ZERO_TOKEN;
456 }
457 if (t1 != DCT_EOB_TOKEN)
458 {
459 tokens[next][1].rate += mb->token_costs[type][band][0][t1];
460 tokens[next][1].token = ZERO_TOKEN;
461 }
462 /* Don't update next, because we didn't add a new node. */
463 }
464 }
465
466 /* Now pick the best path through the whole trellis. */
467 band = vp8_coef_bands[i + 1];
468 VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
469 rate0 = tokens[next][0].rate;
470 rate1 = tokens[next][1].rate;
471 error0 = tokens[next][0].error;
472 error1 = tokens[next][1].error;
473 t0 = tokens[next][0].token;
474 t1 = tokens[next][1].token;
475 rate0 += mb->token_costs[type][band][pt][t0];
476 rate1 += mb->token_costs[type][band][pt][t1];
477 rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0);
478 rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1);
479 if (rd_cost0 == rd_cost1)
480 {
481 rd_cost0 = RDTRUNC(rdmult, rddiv, rate0, error0);
482 rd_cost1 = RDTRUNC(rdmult, rddiv, rate1, error1);
483 }
484 best = rd_cost1 < rd_cost0;
485 final_eob = i0 - 1;
486 for (i = next; i < eob; i = next)
487 {
488 x = tokens[i][best].qc;
489 if (x)
490 final_eob = i;
491 rc = vp8_default_zig_zag1d[i];
492 qcoeff_ptr[rc] = x;
493 dqcoeff_ptr[rc] = x * dequant_ptr[rc];
494 next = tokens[i][best].next;
495 best = (best_mask[best] >> i) & 1;
496 }
497 final_eob++;
498
499 d->eob = final_eob;
500 *a = *l = (d->eob != !type);
501 }
502
vp8_optimize_mb(MACROBLOCK * x,const VP8_ENCODER_RTCD * rtcd)503 void vp8_optimize_mb(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
504 {
505 int b;
506 int type;
507 int has_2nd_order;
508 ENTROPY_CONTEXT_PLANES t_above, t_left;
509 ENTROPY_CONTEXT *ta;
510 ENTROPY_CONTEXT *tl;
511
512 vpx_memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
513 vpx_memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
514
515 ta = (ENTROPY_CONTEXT *)&t_above;
516 tl = (ENTROPY_CONTEXT *)&t_left;
517
518 has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED
519 && x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
520 type = has_2nd_order ? 0 : 3;
521
522 for (b = 0; b < 16; b++)
523 {
524 vp8_optimize_b(x, b, type,
525 ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
526 }
527
528 for (b = 16; b < 20; b++)
529 {
530 vp8_optimize_b(x, b, vp8_block2type[b],
531 ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
532 }
533
534 for (b = 20; b < 24; b++)
535 {
536 vp8_optimize_b(x, b, vp8_block2type[b],
537 ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
538 }
539
540
541 if (has_2nd_order)
542 {
543 b=24;
544 vp8_optimize_b(x, b, vp8_block2type[b],
545 ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
546 }
547 }
548
549
vp8_optimize_mby(MACROBLOCK * x,const VP8_ENCODER_RTCD * rtcd)550 void vp8_optimize_mby(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
551 {
552 int b;
553 int type;
554 int has_2nd_order;
555
556 ENTROPY_CONTEXT_PLANES t_above, t_left;
557 ENTROPY_CONTEXT *ta;
558 ENTROPY_CONTEXT *tl;
559
560 if (!x->e_mbd.above_context)
561 return;
562
563 if (!x->e_mbd.left_context)
564 return;
565
566 vpx_memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
567 vpx_memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
568
569 ta = (ENTROPY_CONTEXT *)&t_above;
570 tl = (ENTROPY_CONTEXT *)&t_left;
571
572 has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED
573 && x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
574 type = has_2nd_order ? 0 : 3;
575
576 for (b = 0; b < 16; b++)
577 {
578 vp8_optimize_b(x, b, type,
579 ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
580 }
581
582
583 if (has_2nd_order)
584 {
585 b=24;
586 vp8_optimize_b(x, b, vp8_block2type[b],
587 ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
588 }
589 }
590
vp8_optimize_mbuv(MACROBLOCK * x,const VP8_ENCODER_RTCD * rtcd)591 void vp8_optimize_mbuv(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
592 {
593 int b;
594 ENTROPY_CONTEXT_PLANES t_above, t_left;
595 ENTROPY_CONTEXT *ta;
596 ENTROPY_CONTEXT *tl;
597
598 if (!x->e_mbd.above_context)
599 return;
600
601 if (!x->e_mbd.left_context)
602 return;
603
604 vpx_memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
605 vpx_memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
606
607 ta = (ENTROPY_CONTEXT *)&t_above;
608 tl = (ENTROPY_CONTEXT *)&t_left;
609
610 for (b = 16; b < 20; b++)
611 {
612 vp8_optimize_b(x, b, vp8_block2type[b],
613 ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
614 }
615
616 for (b = 20; b < 24; b++)
617 {
618 vp8_optimize_b(x, b, vp8_block2type[b],
619 ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
620 }
621
622 }
623 #endif
624
vp8_encode_inter16x16(const VP8_ENCODER_RTCD * rtcd,MACROBLOCK * x)625 void vp8_encode_inter16x16(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
626 {
627 vp8_build_inter_predictors_mb(&x->e_mbd);
628
629 vp8_subtract_mb(rtcd, x);
630
631 vp8_transform_mb(x);
632
633 vp8_quantize_mb(x);
634
635 #if !(CONFIG_REALTIME_ONLY)
636 if (x->optimize==2 ||(x->optimize && x->rddiv > 1))
637 vp8_optimize_mb(x, rtcd);
638 #endif
639
640 vp8_inverse_transform_mb(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
641
642 RECON_INVOKE(&rtcd->common->recon, recon_mb)
643 (IF_RTCD(&rtcd->common->recon), &x->e_mbd);
644 }
645
646
647 /* this funciton is used by first pass only */
vp8_encode_inter16x16y(const VP8_ENCODER_RTCD * rtcd,MACROBLOCK * x)648 void vp8_encode_inter16x16y(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
649 {
650 vp8_build_inter_predictors_mby(&x->e_mbd);
651
652 ENCODEMB_INVOKE(&rtcd->encodemb, submby)(x->src_diff, x->src.y_buffer, x->e_mbd.predictor, x->src.y_stride);
653
654 vp8_transform_mby(x);
655
656 vp8_quantize_mby(x);
657
658 vp8_inverse_transform_mby(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
659
660 RECON_INVOKE(&rtcd->common->recon, recon_mby)
661 (IF_RTCD(&rtcd->common->recon), &x->e_mbd);
662 }
663
664
vp8_encode_inter16x16uv(const VP8_ENCODER_RTCD * rtcd,MACROBLOCK * x)665 void vp8_encode_inter16x16uv(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
666 {
667 vp8_build_inter_predictors_mbuv(&x->e_mbd);
668
669 ENCODEMB_INVOKE(&rtcd->encodemb, submbuv)(x->src_diff, x->src.u_buffer, x->src.v_buffer, x->e_mbd.predictor, x->src.uv_stride);
670
671 vp8_transform_mbuv(x);
672
673 vp8_quantize_mbuv(x);
674
675 vp8_inverse_transform_mbuv(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
676
677 vp8_recon_intra_mbuv(IF_RTCD(&rtcd->common->recon), &x->e_mbd);
678 }
679
680
vp8_encode_inter16x16uvrd(const VP8_ENCODER_RTCD * rtcd,MACROBLOCK * x)681 void vp8_encode_inter16x16uvrd(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
682 {
683 vp8_build_inter_predictors_mbuv(&x->e_mbd);
684 ENCODEMB_INVOKE(&rtcd->encodemb, submbuv)(x->src_diff, x->src.u_buffer, x->src.v_buffer, x->e_mbd.predictor, x->src.uv_stride);
685
686 vp8_transform_mbuv(x);
687
688 vp8_quantize_mbuv(x);
689
690 }
691