OSDN Git Service

add FrameReconstructor.
[qtheora/main.git] / Lib / QTheoraEx / FrameReconstructor.c
1 /* FrameReconstructor.c */
2 /* 2009/07/02           */
3
4 #include "StdAfx.h"
5
6 #include "FrameReconstructor.h"
7
8 /* */
9
10 static void Block_Extract8x8(
11         const Plane_t* plane,
12         INT32          x,
13         INT32          y,
14         UINT8*         block)
15 {
16         INT32 i, j;
17
18         for (i = 0; i < 8; i++) {
19                 for (j = 0; j < 8; j++) {
20                         INT32 xx = x + j;
21                         INT32 yy = y + i;
22
23                         if (xx < 0) {
24                                 xx = 0;
25                         } else if (xx >= plane->CX) {
26                                 xx = plane->CX - 1;
27                         }
28
29                         if (yy < 0) {
30                                 yy = 0;
31                         } else if (yy >= plane->CY) {
32                                 yy = plane->CY - 1;
33                         }
34
35                         block[i * 8 + j] = plane->Plane[yy * plane->Pitch + xx];
36                 }
37         }
38 }
39
40 /* */
41
42 static void Block_CopyIntra8x8(
43         Plane_t*     p,
44         INT32        x,
45         INT32        y,
46         const INT16* block)
47 {
48         const INT16* s = block;
49
50         UINT8* d = p->Plane + y * p->Pitch + x;
51         UINT8* e = d + 8 * p->Pitch;
52
53         UINT8 v0[2] = { 0,   0 };
54         UINT8 v1[2] = { 0, 255 };
55
56         INT32 i;
57
58         for (; d < e; d += p->Pitch) {
59                 for (i = 0; i < 8; i++, s++) {
60                         INT32 pix = 128 + *s;
61                         v0[0] = pix;
62                         v1[0] = v0[pix <   0];
63                         d [i] = v1[pix > 255];
64                 }
65         }
66 }
67
68 static void Block_ReviseInter8x8(
69         Plane_t*     p,
70         INT32        x,
71         INT32        y,
72         const INT16* block)
73 {
74         const INT16* s = block;
75
76         UINT8* d = p->Plane + y * p->Pitch + x;
77         UINT8* e = d + 8 * p->Pitch;
78
79         UINT8 v0[2] = { 0,   0 };
80         UINT8 v1[2] = { 0, 255 };
81
82         INT32 i;
83
84         for (; d < e; d += p->Pitch) {
85                 for (i = 0; i < 8; i++, s++) {
86                         INT32 pix = d[i] + *s;
87                         v0[0] = pix;
88                         v1[0] = v0[pix <   0];
89                         d [i] = v1[pix > 255];
90                 }
91         }
92 }
93
94 /* */
95
96 static void Block_CopyPlane16x16(
97         Plane_t* p,
98         INT32    x,
99         INT32    y,
100         Plane_t* s)
101 {
102         UINT8* d0 = p->Plane + y * p->Pitch + x;
103         UINT8* e0 = d0 + 16 * p->Pitch;
104
105         const UINT8* s0 = s->Plane + y * s->Pitch + x;
106
107         for (; d0 < e0; d0 += p->Pitch, s0 += s->Pitch) {
108                 d0[ 0] = s0[ 0];
109                 d0[ 1] = s0[ 1];
110                 d0[ 2] = s0[ 2];
111                 d0[ 3] = s0[ 3];
112
113                 d0[ 4] = s0[ 4];
114                 d0[ 5] = s0[ 5];
115                 d0[ 6] = s0[ 6];
116                 d0[ 7] = s0[ 7];
117
118                 d0[ 8] = s0[ 8];
119                 d0[ 9] = s0[ 9];
120                 d0[10] = s0[10];
121                 d0[11] = s0[11];
122
123                 d0[12] = s0[12];
124                 d0[13] = s0[13];
125                 d0[14] = s0[14];
126                 d0[15] = s0[15];
127         }
128 }
129
130 static void Block_CopyPlane8x8(
131         Plane_t* p,
132         INT32    x,
133         INT32    y,
134         Plane_t* s)
135 {
136         UINT8* d0 = p->Plane + y * p->Pitch + x;
137         UINT8* e0 = d0 + 8 * p->Pitch;
138
139         const UINT8* s0 = s->Plane + y * s->Pitch + x;
140
141         for (; d0 < e0; d0 += p->Pitch, s0 += s->Pitch) {
142                 d0[0] = s0[0];
143                 d0[1] = s0[1];
144                 d0[2] = s0[2];
145                 d0[3] = s0[3];
146
147                 d0[4] = s0[4];
148                 d0[5] = s0[5];
149                 d0[6] = s0[6];
150                 d0[7] = s0[7];
151         }
152 }
153
154 /* */
155
156 static void MotionComp_Compensate8x8(
157         UINT8*         p,
158         INT32          pitch,
159         const Plane_t* r,
160         INT32          x,
161         INT32          y);
162
163 static void MotionComp_Compensate8x8H(
164         UINT8*         p,
165         INT32          pitch,
166         const Plane_t* r,
167         INT32          x0,
168         INT32          y0,
169         INT32          x1,
170         INT32          y1);
171
172 /* */
173
174 static void MotionComp_Compensate16x16(
175         UINT8*         p,
176         INT32          pitch,
177         const Plane_t* r,
178         INT32          x,
179         INT32          y)
180 {
181         if (x >= 0 && x + 16 < r->CX &&
182                 y >= 0 && y + 16 < r->CY) {
183                 const UINT8* s = r->Plane + y * r->Pitch + x;
184
185                 UINT8* d = p;
186                 UINT8* e = p + 16 * pitch;
187                 while (d < e) {
188                         d[ 0] = s[ 0];
189                         d[ 1] = s[ 1];
190                         d[ 2] = s[ 2];
191                         d[ 3] = s[ 3];
192
193                         d[ 4] = s[ 4];
194                         d[ 5] = s[ 5];
195                         d[ 6] = s[ 6];
196                         d[ 7] = s[ 7];
197
198                         d[ 8] = s[ 8];
199                         d[ 9] = s[ 9];
200                         d[10] = s[10];
201                         d[11] = s[11];
202
203                         d[12] = s[12];
204                         d[13] = s[13];
205                         d[14] = s[14];
206                         d[15] = s[15];
207
208                         s += r->Pitch;
209                         d += pitch;
210                 }
211
212         } else {
213                 MotionComp_Compensate8x8(p,                 pitch, r, x,     y    );
214                 MotionComp_Compensate8x8(p + 8,             pitch, r, x + 8, y    );
215                 MotionComp_Compensate8x8(p     + 8 * pitch, pitch, r, x,     y + 8);
216                 MotionComp_Compensate8x8(p + 8 + 8 * pitch, pitch, r, x + 8, y + 8);
217         }
218 }
219
220 static void MotionComp_Compensate8x8(
221         UINT8*         p,
222         INT32          pitch,
223         const Plane_t* r,
224         INT32          x,
225         INT32          y)
226 {
227         UINT8 b[64];
228
229         const UINT8* s0 = r->Plane + y * r->Pitch + x;
230         INT32        p0 = r->Pitch;
231
232         UINT8* d = p;
233         UINT8* e = p + 8 * pitch;
234
235         if (x < 0 || x + 8 >= r->CX ||
236                 y < 0 || y + 8 >= r->CY) {
237                 s0 = b;
238                 p0 = 8;
239                 Block_Extract8x8(r, x, y, b);
240         }
241
242         while (d < e) {
243                 d[ 0] = s0[ 0];
244                 d[ 1] = s0[ 1];
245                 d[ 2] = s0[ 2];
246                 d[ 3] = s0[ 3];
247
248                 d[ 4] = s0[ 4];
249                 d[ 5] = s0[ 5];
250                 d[ 6] = s0[ 6];
251                 d[ 7] = s0[ 7];
252
253                 s0 += p0;
254                 d  += pitch;
255         }
256 }
257
258 static void MotionComp_Compensate16x16H(
259         UINT8*         p,
260         INT32          pitch,
261         const Plane_t* r,
262         INT32          x0,
263         INT32          y0,
264         INT32          x1,
265         INT32          y1)
266 {
267         if (x0 >= 0 && x0 + 16 < r->CX &&
268                 y0 >= 0 && y0 + 16 < r->CY &&
269                 x1 >= 0 && x1 + 16 < r->CX &&
270                 y1 >= 0 && y1 + 16 < r->CY) {
271                 const UINT8* s0 = r->Plane + y0 * r->Pitch + x0;
272                 const UINT8* s1 = r->Plane + y1 * r->Pitch + x1;
273
274                 UINT8* d = p;
275                 UINT8* e = p + 16 * pitch;
276                 while (d < e) {
277                         d[ 0] = (s0[ 0] + s1[ 0]) >> 1;
278                         d[ 1] = (s0[ 1] + s1[ 1]) >> 1;
279                         d[ 2] = (s0[ 2] + s1[ 2]) >> 1;
280                         d[ 3] = (s0[ 3] + s1[ 3]) >> 1;
281
282                         d[ 4] = (s0[ 4] + s1[ 4]) >> 1;
283                         d[ 5] = (s0[ 5] + s1[ 5]) >> 1;
284                         d[ 6] = (s0[ 6] + s1[ 6]) >> 1;
285                         d[ 7] = (s0[ 7] + s1[ 7]) >> 1;
286
287                         d[ 8] = (s0[ 8] + s1[ 8]) >> 1;
288                         d[ 9] = (s0[ 9] + s1[ 9]) >> 1;
289                         d[10] = (s0[10] + s1[10]) >> 1;
290                         d[11] = (s0[11] + s1[11]) >> 1;
291
292                         d[12] = (s0[12] + s1[12]) >> 1;
293                         d[13] = (s0[13] + s1[13]) >> 1;
294                         d[14] = (s0[14] + s1[14]) >> 1;
295                         d[15] = (s0[15] + s1[15]) >> 1;
296
297                         s0 += r->Pitch;
298                         s1 += r->Pitch;
299                         d  += pitch;
300                 }
301
302         } else {
303                 MotionComp_Compensate8x8H(p,                 pitch, r, x0,     y0    , x1,     y1    );
304                 MotionComp_Compensate8x8H(p + 8,             pitch, r, x0 + 8, y0    , x1 + 8, y1    );
305                 MotionComp_Compensate8x8H(p     + 8 * pitch, pitch, r, x0,     y0 + 8, x1,     y1 + 8);
306                 MotionComp_Compensate8x8H(p + 8 + 8 * pitch, pitch, r, x0 + 8, y0 + 8, x1 + 8, y1 + 8);
307         }
308 }
309
310 static void MotionComp_Compensate8x8H(
311         UINT8*         p,
312         INT32          pitch,
313         const Plane_t* r,
314         INT32          x0,
315         INT32          y0,
316         INT32          x1,
317         INT32          y1)
318 {
319         UINT8 b0[64], b1[64];
320
321         const UINT8* s0 = r->Plane + y0 * r->Pitch + x0;
322         INT32        p0 = r->Pitch;
323
324         const UINT8* s1 = r->Plane + y1 * r->Pitch + x1;
325         INT32        p1 = r->Pitch;
326
327         UINT8* d = p;
328         UINT8* e = p + 8 * pitch;
329
330         if (x0 < 0 || x0 + 8 >= r->CX ||
331                 y0 < 0 || y0 + 8 >= r->CY ||
332                 x1 < 0 || x1 + 8 >= r->CX ||
333                 y1 < 0 || y1 + 8 >= r->CY) {
334                 s0 = b0;
335                 p0 = 8;
336
337                 s1 = b1;
338                 p1 = 8;
339
340                 Block_Extract8x8(r, x0, y0, b0);
341                 Block_Extract8x8(r, x1, y1, b1);
342         }
343
344         while (d < e) {
345                 d[0] = (s0[0] + s1[0]) >> 1;
346                 d[1] = (s0[1] + s1[1]) >> 1;
347                 d[2] = (s0[2] + s1[2]) >> 1;
348                 d[3] = (s0[3] + s1[3]) >> 1;
349
350                 d[4] = (s0[4] + s1[4]) >> 1;
351                 d[5] = (s0[5] + s1[5]) >> 1;
352                 d[6] = (s0[6] + s1[6]) >> 1;
353                 d[7] = (s0[7] + s1[7]) >> 1;
354
355                 s0 += p0;
356                 s1 += p1;
357                 d  += pitch;
358         }
359 }
360
361 /* */
362
363 static void MotionComp_Block16x16(
364         Plane_t*              p,
365         INT32                 x,
366         INT32                 y,
367         const Plane_t*        r,
368         const MotionVector_t* mv)
369 {
370         INT32 dx = ((mv->X & 1) != 0);
371         INT32 dy = ((mv->Y & 1) != 0);
372
373         INT32 vx[2] = { mv->X >> 1 };
374         INT32 vy[2] = { mv->Y >> 1 };
375
376         UINT8* d = p->Plane + y * p->Pitch + x;
377
378         if (dx == 0 && dy == 0) {
379                 MotionComp_Compensate16x16(
380                         d,
381                         p->Pitch,
382                         r,
383                         x + vx[0],
384                         y + vy[0]);
385
386         } else {
387                 vx[1] = vx[0];
388                 vy[1] = vy[0];
389
390                 vx[mv->X >= 0] += dx;
391                 vy[mv->Y >= 0] += dy;
392
393                 MotionComp_Compensate16x16H(
394                         d,
395                         p->Pitch,
396                         r,
397                         x + vx[0],
398                         y + vy[0],
399                         x + vx[1],
400                         y + vy[1]);
401         }
402 }
403
404 static void MotionComp_Block8x8Y(
405         Plane_t*              p,
406         INT32                 x,
407         INT32                 y,
408         const Plane_t*        r,
409         const MotionVector_t* mv)
410 {
411         INT32 dx = ((mv->X & 1) != 0);
412         INT32 dy = ((mv->Y & 1) != 0);
413
414         INT32 vx[2] = { mv->X >> 1 };
415         INT32 vy[2] = { mv->Y >> 1 };
416
417         UINT8* d = p->Plane + y * p->Pitch + x;
418
419         if (dx == 0 && dy == 0) {
420                 MotionComp_Compensate8x8(
421                         d,
422                         p->Pitch,
423                         r,
424                         x + vx[0],
425                         y + vy[0]);
426
427         } else {
428                 vx[1] = vx[0];
429                 vy[1] = vy[0];
430
431                 vx[mv->X >= 0] += dx;
432                 vy[mv->Y >= 0] += dy;
433
434                 MotionComp_Compensate8x8H(
435                         d,
436                         p->Pitch,
437                         r,
438                         x + vx[0],
439                         y + vy[0],
440                         x + vx[1],
441                         y + vy[1]);
442         }
443 }
444
445 static void MotionComp_Block8x8C(
446         Plane_t*              p,
447         INT32                 x,
448         INT32                 y,
449         const Plane_t*        r,
450         const MotionVector_t* mv0)
451 {
452         MotionVector_t mv = {
453                 (mv0->X >> 1) | (mv0->X & 1),
454                 (mv0->Y >> 1) | (mv0->Y & 1)
455         };
456
457         INT32 dx = ((mv.X & 1) != 0);
458         INT32 dy = ((mv.Y & 1) != 0);
459
460         INT32 vx[2] = { mv.X >> 1 };
461         INT32 vy[2] = { mv.Y >> 1 };
462
463         UINT8* d = p->Plane + y * p->Pitch + x;
464
465         if (dx == 0 && dy == 0) {
466                 MotionComp_Compensate8x8(
467                         d,
468                         p->Pitch,
469                         r,
470                         x + vx[0],
471                         y + vy[0]);
472
473         } else {
474                 vx[1] = vx[0];
475                 vy[1] = vy[0];
476
477                 vx[mv.X >= 0] += dx;
478                 vy[mv.Y >= 0] += dy;
479
480                 MotionComp_Compensate8x8H(
481                         d,
482                         p->Pitch,
483                         r,
484                         x + vx[0],
485                         y + vy[0],
486                         x + vx[1],
487                         y + vy[1]);
488         }
489 }
490
491 /* */
492
493 static const INT32 COS[8] = {
494         65536,
495         64277,
496         60547,
497         54491,
498         46341,
499         36410,
500         25080,
501         12785
502 };
503
504 #define MUL(T,X) ((COS[T] * (X)) >> 16)
505
506 static void IDCT_8(
507         const INT16* x,
508         INT16*       y)
509 {
510         INT32 t[8];
511         INT32 t_3, t_2, t_5;
512         INT16 s[2];
513
514         /* Stage.1 */
515
516         s[0] = x[0] + x[4];
517         s[1] = x[0] - x[4];
518
519         t[0] = MUL(4, s[0]);
520         t[1] = MUL(4, s[1]);
521
522         t[2] = MUL(6, x[2]) - MUL(2, x[6]);
523         t[3] = MUL(2, x[2]) + MUL(6, x[6]);
524
525         t[4] = MUL(7, x[1]) - MUL(1, x[7]);
526         t[5] = MUL(3, x[5]) - MUL(5, x[3]);
527         t[6] = MUL(5, x[5]) + MUL(3, x[3]);
528         t[7] = MUL(1, x[1]) + MUL(7, x[7]);
529
530         /* Stage.2 */
531
532         s[0] = t[4] - t[5];
533         s[1] = t[7] - t[6];
534
535         t[4] += t[5];
536         t[5]  = MUL(4, s[0]);
537
538         t[7] += t[6];
539         t[6]  = MUL(4, s[1]);
540
541         /* Stage.3 */
542
543         t_3 = t[0] - t[3];
544         t_2 = t[1] - t[2];
545         t_5 = t[6] - t[5];
546
547         t[0] += t[3];
548         t[1] += t[2];
549         t[6] += t[5];
550
551         /* Stage.4 */
552
553         y[0*8] = t[0] + t[7];
554         y[1*8] = t[1] + t[6];
555         y[2*8] = t_2  + t_5 ;
556         y[3*8] = t_3  + t[4];
557         y[4*8] = t_3  - t[4];
558         y[5*8] = t_2  - t_5 ;
559         y[6*8] = t[1] - t[6];
560         y[7*8] = t[0] - t[7];
561 }
562
563 /* */
564
565 static void IDCT_8x8(
566         const INT16* x,
567         INT16*       y)
568 {
569         const INT16* xx;
570         INT16*       yy;
571         INT16*       end;
572         INT16        w[64];
573
574         for (xx = x, yy = w, end = yy + 8; yy < end; xx += 4*8, yy += 4) {
575                 IDCT_8(xx + 0*8, yy + 0);
576                 IDCT_8(xx + 1*8, yy + 1);
577                 IDCT_8(xx + 2*8, yy + 2);
578                 IDCT_8(xx + 3*8, yy + 3);
579         }
580
581         for (xx = w, yy = y, end = yy + 8; yy < end; xx += 4*8, yy += 4) {
582                 IDCT_8(xx + 0*8, yy + 0);
583                 IDCT_8(xx + 1*8, yy + 1);
584                 IDCT_8(xx + 2*8, yy + 2);
585                 IDCT_8(xx + 3*8, yy + 3);
586         }
587
588         for (yy = y, end = yy + 64; yy < end; yy += 4) {
589                 yy[0] = (yy[0] + 8) >> 4;
590                 yy[1] = (yy[1] + 8) >> 4;
591                 yy[2] = (yy[2] + 8) >> 4;
592                 yy[3] = (yy[3] + 8) >> 4;
593         }
594 }
595
596 /* */
597
598 struct DecodeCoefficientsContext {
599
600         INT32 EOB_Run[64];
601
602         INT8*  Run  [64];
603         INT16* Coeff[64];
604
605 }; /* DecodeCoefficientsContext */
606
607 typedef struct DecodeCoefficientsContext DecodeCoefficientsContext_t;
608
609 static INT32 DecodeCoefficients(
610         FrameDecoder_t*              t,
611         DecodeCoefficientsContext_t* ctx,
612         INT16*                       block)
613 {
614         INT16* b = block;
615         INT16* e = b + 64;
616
617         INT32 i = 0;
618
619         while (b < e) {
620                 if (ctx->EOB_Run[i] > 0) {
621                         ctx->EOB_Run[i] -= 1;
622                         break;
623
624                 } else {
625                         INT32 run   = *((ctx->Run  [i])++);
626                         INT16 coeff = *((ctx->Coeff[i])++);
627
628                         if (run < 0) {
629                                 ctx->EOB_Run[i] = coeff;
630
631                         } else {
632                                 INT16* p = b + run;
633                                 if (p >= e) {
634                                         break;
635                                 }
636
637                                 while (b < p) {
638                                         *(b++) = 0;
639                                 }
640
641                                 *(b++) = coeff;
642
643                                 i = b - block;
644                         }
645                 }
646         }
647
648         while (b < e) {
649                 *(b++) = 0;
650         }
651
652         return i;
653 }
654
655 /* */
656
657 static const UINT8 ZIGZAG[64] = {
658          0, 1, 5, 6,14,15,27,28,
659          2, 4, 7,13,16,26,29,42,
660          3, 8,12,17,25,30,41,43,
661          9,11,18,24,31,40,44,53,
662         10,19,23,32,39,45,52,54,
663         20,22,33,38,46,51,55,60,
664         21,34,37,47,50,56,59,61,
665         35,36,48,49,57,58,62,63
666 };
667
668 static void Dequantize_DoDequantize(
669         const DequantizeMatrix_t* m,
670         INT32                     intra,
671         INT32                     plane,
672         INT16*                    block,
673         const INT16*              fragment)
674 {
675         const INT16* mat = m->Matrix[intra][plane];
676
677         INT32 i;
678         for (i = 0; i < 64; i++) {
679                 block[i] = fragment[ZIGZAG[i]] * mat[i];
680         }
681 }
682
683 /* */
684
685 static void Reconstruct_IntraBlock(
686         FrameDecoder_t*              t,
687         Plane_t*                     p,
688         INT32                        x,
689         INT32                        y,
690         INT16                        dc,
691         INT32                        plane,
692         Plane_t*                     r,
693         DecodeCoefficientsContext_t* ctx)
694 {
695         INT16 block[64];
696         INT16 coeff[64];
697
698         if (dc == NOT_CODED) {
699                 Block_CopyPlane8x8(p, x, y, r);
700                 return;
701         }
702
703         DecodeCoefficients(t, ctx, block);
704
705         block[0] = dc;
706
707 #if 0
708         {
709                 INT32 i;
710                 printf("DCT:\n");
711                 for (i = 0; i < 64; i++) {
712                         if ((i % 8) > 0) {
713                                 printf(" ");
714                         }
715                         printf("%d", block[i]);
716                         if ((i % 8) == 7) {
717                                 printf("\n");
718                         }
719                 }
720         }
721 #endif
722
723         Dequantize_DoDequantize(
724                 &(t->Dequantize),
725                 0,
726                 plane,
727                 coeff,
728                 block);
729
730         IDCT_8x8(coeff, coeff);
731
732         Block_CopyIntra8x8(p, x, y, coeff);
733 }
734
735 /* */
736
737 static void Reconstruct_InterBlock(
738         FrameDecoder_t*              t,
739         Plane_t*                     p,
740         INT32                        x,
741         INT32                        y,
742         INT16                        dc,
743         INT32                        plane,
744         Plane_t*                     r,
745         DecodeCoefficientsContext_t* ctx)
746 {
747         INT16 block[64];
748         INT16 coeff[64];
749
750         if (dc == NOT_CODED) {
751                 if (r != NULL) {
752                         Block_CopyPlane8x8(p, x, y, r);
753                 }
754                 return;
755         }
756
757         DecodeCoefficients(t, ctx, block);
758
759         block[0] = dc;
760
761         Dequantize_DoDequantize(
762                 &(t->Dequantize),
763                 1,
764                 plane,
765                 coeff,
766                 block);
767
768         IDCT_8x8(coeff, coeff);
769
770         Block_ReviseInter8x8(p, x, y, coeff);
771 }
772
773 /* */
774
775 static const INT8 S_PX[16] = {
776         0*8, 1*8, 1*8, 0*8,
777         0*8, 0*8, 1*8, 1*8,
778         2*8, 2*8, 3*8, 3*8,
779         3*8, 2*8, 2*8, 3*8
780 };
781
782 static const INT8 S_PY[16] = {
783         0*8, 0*8, 1*8, 1*8,
784         2*8, 3*8, 3*8, 2*8,
785         2*8, 3*8, 3*8, 2*8,
786         1*8, 1*8, 0*8, 0*8
787 };
788
789 static const INT8 M_PX[4] = {
790         0*16, 0*16,
791         1*16, 1*16
792 };
793
794 static const INT8 M_PY[4] = {
795         0*16, 1*16,
796         1*16, 0*16
797 };
798
799 /* */
800
801 static void Reconstruct_YPlane(
802         FrameDecoder_t* t)
803 {
804         INT32 x, y;
805
806         INT32 sx = t->Index->SX[0] * 32;
807         INT32 sy = t->Index->SY[0] * 32;
808
809         INT32 mx = t->Index->MX * 16;
810         INT32 my = t->Index->MY * 16;
811
812         INT32 bx = t->Index->BX[0];
813
814         const UINT16* bi = t->Index->BIndex[0];
815
816         Plane_t* g = t->Frame[0];
817         Plane_t* p = t->Frame[1];
818         Plane_t* r = t->Frame[2];
819
820         const UINT8*          mm = t->MBMode;
821         const MotionVector_t* mv = t->MV;
822
823         DecodeCoefficientsContext_t ctx = { 0 };
824
825         INT32 i;
826         for (i = 0; i < 64; i++) {
827                 ctx.Run  [i] = t->BRun  [0][i];
828                 ctx.Coeff[i] = t->BCoeff[0][i];
829         }
830
831         for (y = 0; y < sy; y += 32) {
832                 for (x = 0; x < sx; x += 32) {
833                         INT32 i = 0;
834
835                         INT32 m;
836                         for (m = 0; m < 4; m++, i += 4) {
837                                 INT32 x0 = x + M_PX[m];
838                                 INT32 y0 = y + M_PY[m];
839                                 if (x0 < mx && y0 < my) {
840                                         switch (*mm) {
841                                         case 0: /* INTER_NOMV */
842                                                 Block_CopyPlane16x16(p, x0, y0, r);
843
844                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 0], y + S_PY[i + 0], t->DC[bi[0]], 0, NULL, &ctx);
845                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 1], y + S_PY[i + 1], t->DC[bi[1]], 0, NULL, &ctx);
846                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 2], y + S_PY[i + 2], t->DC[bi[2]], 0, NULL, &ctx);
847                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 3], y + S_PY[i + 3], t->DC[bi[3]], 0, NULL, &ctx);
848                                                 break;
849
850                                         case 1: /* INTRA */
851                                                 Reconstruct_IntraBlock(t, p, x + S_PX[i + 0], y + S_PY[i + 0], t->DC[bi[0]], 0, r, &ctx);
852                                                 Reconstruct_IntraBlock(t, p, x + S_PX[i + 1], y + S_PY[i + 1], t->DC[bi[1]], 0, r, &ctx);
853                                                 Reconstruct_IntraBlock(t, p, x + S_PX[i + 2], y + S_PY[i + 2], t->DC[bi[2]], 0, r, &ctx);
854                                                 Reconstruct_IntraBlock(t, p, x + S_PX[i + 3], y + S_PY[i + 3], t->DC[bi[3]], 0, r, &ctx);
855                                                 break;
856
857                                         case 2: /* INTER_MV */
858                                         case 3: /* INTER_MV_LAST */
859                                         case 4: /* INTER_MV_LAST2 */
860                                                 MotionComp_Block16x16(p, x0, y0, r, mv);
861
862                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 0], y + S_PY[i + 0], t->DC[bi[0]], 0, r, &ctx);
863                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 1], y + S_PY[i + 1], t->DC[bi[1]], 0, r, &ctx);
864                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 2], y + S_PY[i + 2], t->DC[bi[2]], 0, r, &ctx);
865                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 3], y + S_PY[i + 3], t->DC[bi[3]], 0, r, &ctx);
866                                                 break;
867
868                                         case 5: /* INTER_GOLDEN_NOMV */
869                                                 Block_CopyPlane16x16(p, x0, y0, g);
870
871                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 0], y + S_PY[i + 0], t->DC[bi[0]], 0, r, &ctx);
872                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 1], y + S_PY[i + 1], t->DC[bi[1]], 0, r, &ctx);
873                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 2], y + S_PY[i + 2], t->DC[bi[2]], 0, r, &ctx);
874                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 3], y + S_PY[i + 3], t->DC[bi[3]], 0, r, &ctx);
875                                                 break;
876
877                                         case 6: /* INTER_GOLDEN_MV */
878                                                 MotionComp_Block16x16(p, x0, y0, g, mv);
879
880                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 0], y + S_PY[i + 0], t->DC[bi[0]], 0, r, &ctx);
881                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 1], y + S_PY[i + 1], t->DC[bi[1]], 0, r, &ctx);
882                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 2], y + S_PY[i + 2], t->DC[bi[2]], 0, r, &ctx);
883                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 3], y + S_PY[i + 3], t->DC[bi[3]], 0, r, &ctx);
884                                                 break;
885
886                                         case 7: /* INTER_MV_FOUR */
887                                         {
888                                                 const MotionVector_t* v = mv;
889
890                                                 const INT16* dc = t->DC + (x0 >> 3) + (y0 >> 3) * bx;
891
892                                                 if (dc[0] != NOT_CODED) {
893                                                         MotionComp_Block8x8Y(p, x0 + 0, y0 + 0, r, v++);
894                                                 }
895
896                                                 if (dc[1] != NOT_CODED) {
897                                                         MotionComp_Block8x8Y(p, x0 + 8, y0 + 0, r, v++);
898                                                 }
899
900                                                 if (dc[0 + bx] != NOT_CODED) {
901                                                         MotionComp_Block8x8Y(p, x0 + 0, y0 + 8, r, v++);
902                                                 }
903
904                                                 if (dc[1 + bx] != NOT_CODED) {
905                                                         MotionComp_Block8x8Y(p, x0 + 8, y0 + 8, r, v++);
906                                                 }
907
908                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 0], y + S_PY[i + 0], t->DC[bi[0]], 0, r, &ctx);
909                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 1], y + S_PY[i + 1], t->DC[bi[1]], 0, r, &ctx);
910                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 2], y + S_PY[i + 2], t->DC[bi[2]], 0, r, &ctx);
911                                                 Reconstruct_InterBlock(t, p, x + S_PX[i + 3], y + S_PY[i + 3], t->DC[bi[3]], 0, r, &ctx);
912                                                 break;
913                                         }
914
915                                         } /* switch */
916
917                                         bi += 4;
918                                         mm += 1;
919                                         mv += 4;
920                                 }
921                         }
922                 }
923         }
924 }
925
926 /* */
927
928 static void Reconstruct_CPlane(
929         FrameDecoder_t* t)
930 {
931         INT32 x, y;
932
933         INT32 sx = t->Index->SX[1] * 32;
934         INT32 sy = t->Index->SY[1] * 32;
935
936         INT32 mx = t->Index->MX * 8;
937         INT32 my = t->Index->MY * 8;
938
939         INT32 bx = t->Index->BX[1];
940
941         const UINT16* bi = t->Index->BIndex[1];
942
943         Plane_t* g = t->Frame[0];
944         Plane_t* p = t->Frame[1];
945         Plane_t* r = t->Frame[2];
946
947         const INT16* DC0 = t->DC + t->Index->BC[0];
948         const INT16* DC1 = DC0   + t->Index->BC[1];
949
950         const UINT8* m = t->BMode + t->Index->BC[0];
951
952         DecodeCoefficientsContext_t ctx[2] = { 0 };
953
954         INT32 i;
955         for (i = 0; i < 64; i++) {
956                 ctx[0].Run  [i] = t->BRun  [1][i];
957                 ctx[0].Coeff[i] = t->BCoeff[1][i];
958
959                 ctx[1].Run  [i] = t->BRun  [2][i];
960                 ctx[1].Coeff[i] = t->BCoeff[2][i];
961         }
962
963         for (y = 0; y < sy; y += 32) {
964                 for (x = 0; x < sx; x += 32) {
965                         INT32 i;
966                         for (i = 0; i < 16; i++) {
967                                 INT32 xx = x + S_PX[i];
968                                 INT32 yy = y + S_PY[i];
969
970                                 if (xx < mx && yy < my) {
971                                         INT32 idx = (xx >> 3) + (yy >> 3) * bx;
972
973                                         switch (m[idx]) {
974                                         case 0: /* INTER_NOMV */
975                                                 Block_CopyPlane8x8(p + 1, xx, yy, r + 1);
976                                                 Block_CopyPlane8x8(p + 2, xx, yy, r + 2);
977
978                                                 Reconstruct_InterBlock(t, p + 1, xx, yy, DC0[idx], 1, NULL, ctx + 0);
979                                                 Reconstruct_InterBlock(t, p + 2, xx, yy, DC1[idx], 2, NULL, ctx + 1);
980                                                 break;
981
982                                         case 1: /* INTRA */
983                                                 Reconstruct_IntraBlock(t, p + 1, xx, yy, DC0[idx], 1, r + 1, ctx + 0);
984                                                 Reconstruct_IntraBlock(t, p + 2, xx, yy, DC1[idx], 2, r + 2, ctx + 1);
985                                                 break;
986
987                                         case 2: /* INTER_MV */
988                                         case 3: /* INTER_MV_LAST */
989                                         case 4: /* INTER_MV_LAST2 */
990                                                 MotionComp_Block8x8C(p + 1, xx, yy, r + 1, t->MVC + idx);
991                                                 MotionComp_Block8x8C(p + 2, xx, yy, r + 2, t->MVC + idx);
992
993                                                 Reconstruct_InterBlock(t, p + 1, xx, yy, DC0[idx], 1, r + 1, ctx + 0);
994                                                 Reconstruct_InterBlock(t, p + 2, xx, yy, DC1[idx], 2, r + 2, ctx + 1);
995                                                 break;
996
997                                         case 5: /* INTER_GOLDEN_NOMV */
998                                                 Block_CopyPlane8x8(p + 1, xx, yy, g + 1);
999                                                 Block_CopyPlane8x8(p + 2, xx, yy, g + 2);
1000
1001                                                 Reconstruct_InterBlock(t, p + 1, xx, yy, DC0[idx], 1, r + 1, ctx + 0);
1002                                                 Reconstruct_InterBlock(t, p + 2, xx, yy, DC1[idx], 2, r + 2, ctx + 1);
1003                                                 break;
1004
1005                                         case 6: /* INTER_GOLDEN_MV */
1006                                                 MotionComp_Block8x8C(p + 1, xx, yy, g + 1, t->MVC + idx);
1007                                                 MotionComp_Block8x8C(p + 2, xx, yy, g + 2, t->MVC + idx);
1008
1009                                                 Reconstruct_InterBlock(t, p + 1, xx, yy, DC0[idx], 1, r + 1, ctx + 0);
1010                                                 Reconstruct_InterBlock(t, p + 2, xx, yy, DC1[idx], 2, r + 2, ctx + 1);
1011                                                 break;
1012
1013                                         case 7: /* INTER_MV_FOUR */
1014                                                 MotionComp_Block8x8C(p + 1, xx, yy, r + 1, t->MVC + idx);
1015                                                 MotionComp_Block8x8C(p + 2, xx, yy, r + 2, t->MVC + idx);
1016
1017                                                 Reconstruct_InterBlock(t, p + 1, xx, yy, DC0[idx], 1, r + 1, ctx + 0);
1018                                                 Reconstruct_InterBlock(t, p + 2, xx, yy, DC1[idx], 2, r + 2, ctx + 1);
1019                                                 break;
1020
1021                                         } /* switch */
1022                                 }
1023                         }
1024                 }
1025         }
1026 }
1027
1028 /* */
1029
1030 void QT_ReconstructFrame(
1031         FrameDecoder_t* t)
1032 {
1033         Reconstruct_YPlane(t);
1034
1035         Reconstruct_CPlane(t);
1036 }
1037
1038 /* */
1039