2 * $Logfile: /Freespace2/src/movie/decoder16.cpp $
7 * 16-bit frame decoder for MVEs
10 * Revision 1.3 2005/10/01 21:48:01 taylor
12 * fix decoder to swap opcode 0xb since it screws up on PPC
13 * the previous opcode 0xc change was wrong since we had already determined that it messes up FS1 movies
15 * Revision 1.2 2005/03/29 07:50:34 taylor
16 * Update to newest movie code with much better video support and audio support from
17 * Pierre Willenbrock. Movies are enabled always now (no longer a build option)
18 * and but can be skipped with the "--nomovies" or "-n" cmdline options.
28 extern int g_width, g_height;
29 extern void *g_vBackBuf1, *g_vBackBuf2;
31 /* 16 bit decoding routines */
33 static ushort *backBuf1, *backBuf2;
34 static int lookup_initialized;
36 static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned char **pData, unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb);
37 static void genLoopkupTable();
39 void decodeFrame16(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain)
42 unsigned char *pOffData;
49 if (!lookup_initialized) {
53 backBuf1 = (ushort *)g_vBackBuf1;
54 backBuf2 = (ushort *)g_vBackBuf2;
59 offset = pData[0]|(pData[1]<<8);
61 pOffData = pData + offset;
66 length = offset - 2; /*dataRemain-2;*/
68 for (j=0; j<yb; j++) {
69 for (i=0; i<xb/2; i++) {
71 dispatchDecoder16((ushort **)&pFrame, op, &pData, &pOffData, &dataRemain, &i, &j);
74 if ((ushort *)pFrame < backBuf1)
75 fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
76 else if ((ushort *)pFrame >= backBuf1 + g_width*g_height)
77 fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
80 op = ((*pMap) >> 4) & 0xf;
81 dispatchDecoder16((ushort **)&pFrame, op, &pData, &pOffData, &dataRemain, &i, &j);
84 if ((ushort *)pFrame < backBuf1)
85 fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
86 else if ((ushort *)pFrame >= backBuf1 + g_width*g_height)
87 fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
94 pFrame += 7*g_width*2;
97 if ((length-(pData-pOrig)) != 0) {
98 nprintf(("MVE", "DEBUG: junk left over: %d,%d,%d\n", (pData-pOrig), length, (length-(pData-pOrig))));
102 static ushort GETPIXEL(unsigned char **buf, int off)
104 ushort val = (*buf)[0+off] | ((*buf)[1+off] << 8);
108 static ushort GETPIXELI(unsigned char **buf, int off)
110 ushort val = (*buf)[0+off] | ((*buf)[1+off] << 8);
115 static void relClose(int i, int *x, int *y)
126 static void relFar(int i, int sign, int *x, int *y)
129 *x = sign * (8 + (i % 7));
132 *x = sign * (-14 + (i - 56) % 29);
133 *y = sign * (8 + (i - 56) / 29);
137 static int close_table[512];
138 static int far_p_table[512];
139 static int far_n_table[512];
141 static void genLoopkupTable()
146 for (i = 0; i < 256; i++) {
149 close_table[i*2+0] = x;
150 close_table[i*2+1] = y;
152 relFar(i, 1, &x, &y);
154 far_p_table[i*2+0] = x;
155 far_p_table[i*2+1] = y;
157 relFar(i, -1, &x, &y);
159 far_n_table[i*2+0] = x;
160 far_n_table[i*2+1] = y;
163 lookup_initialized = 1;
166 static void copyFrame(ushort *pDest, ushort *pSrc)
170 for (i=0; i<8; i++) {
171 memcpy(pDest, pSrc, 16);
177 static void patternRow4Pixels(ushort *pFrame, unsigned char pat0, unsigned char pat1, ushort *p)
181 ushort pattern = (pat1 << 8) | pat0;
184 *pFrame++ = p[(mask & pattern) >> shift];
190 static void patternRow4Pixels2(ushort *pFrame, unsigned char pat0, ushort *p)
192 unsigned char mask=0x03;
193 unsigned char shift=0;
195 /* ORIGINAL VERSION IS BUGGY
199 pel = p[(mask & pat0) >> shift];
202 pFrame[g_width + 0] = pel;
203 pFrame[g_width + 2] = pel;
211 pel = p[(mask & pat0) >> shift];
214 pFrame[g_width + 0] = pel;
215 pFrame[g_width + 1] = pel;
222 static void patternRow4Pixels2x1(ushort *pFrame, unsigned char pat, ushort *p)
224 unsigned char mask=0x03;
225 unsigned char shift=0;
229 pel = p[(mask & pat) >> shift];
238 static void patternQuadrant4Pixels(ushort *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, unsigned char pat3, ushort *p)
240 unsigned long mask = 0x00000003UL;
243 unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0;
245 for (i=0; i<16; i++) {
246 pFrame[i&3] = p[(pat & mask) >> shift];
256 static void patternRow2Pixels(ushort *pFrame, unsigned char pat, ushort *p)
258 unsigned char mask=0x01;
261 *pFrame++ = p[(mask & pat) ? 1 : 0];
266 static void patternRow2Pixels2(ushort *pFrame, unsigned char pat, ushort *p)
269 unsigned char mask=0x1;
271 /* ORIGINAL VERSION IS BUGGY
273 while (mask != 0x10) {
274 pel = p[(mask & pat) ? 1 : 0];
277 pFrame[g_width + 0] = pel;
278 pFrame[g_width + 2] = pel;
284 while (mask != 0x10) {
285 pel = p[(mask & pat) ? 1 : 0];
289 pFrame[g_width + 0] = pel;
290 pFrame[g_width + 1] = pel;
297 static void patternQuadrant2Pixels(ushort *pFrame, unsigned char pat0, unsigned char pat1, ushort *p)
299 ushort mask = 0x0001;
301 ushort pat = (pat1 << 8) | pat0;
303 for (i=0; i<16; i++) {
304 pFrame[i&3] = p[(pat & mask) ? 1 : 0];
314 static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned char **pData, unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb)
317 unsigned char pat[16];
328 copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1));
335 /* relFar(*(*pOffData)++, 1, &x, &y); */
338 x = far_p_table[k*2+0];
339 y = far_p_table[k*2+1];
341 copyFrame(*pFrame, *pFrame + x + y*g_width);
346 /* relFar(*(*pOffData)++, -1, &x, &y); */
349 x = far_n_table[k*2+0];
350 y = far_n_table[k*2+1];
352 copyFrame(*pFrame, *pFrame + x + y*g_width);
357 /* relClose(*(*pOffData)++, &x, &y); */
360 x = close_table[k*2+0];
361 y = close_table[k*2+1];
363 copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width);
368 x = (char)*(*pData)++;
369 y = (char)*(*pData)++;
370 copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width);
375 nprintf(("MVE", "STUB: encoding 6 not tested\n"));
377 for (i=0; i<2; i++) {
380 if (++*curXb == (g_width >> 3)) {
381 *pFrame += 7*g_width;
384 if (++*curYb == (g_height >> 3))
391 p[0] = GETPIXELI(pData, 0);
392 p[1] = GETPIXELI(pData, 0);
394 if (!((p[0]/*|p[1]*/)&0x8000)) {
395 for (i=0; i<8; i++) {
396 patternRow2Pixels(*pFrame, *(*pData), p);
402 for (i=0; i<2; i++) {
403 patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p);
404 *pFrame += 2*g_width;
405 patternRow2Pixels2(*pFrame, *(*pData) >> 4, p);
408 *pFrame += 2*g_width;
414 p[0] = GETPIXEL(pData, 0);
416 if (!(p[0] & 0x8000)) {
417 for (i=0; i<4; i++) {
418 p[0] = GETPIXELI(pData, 0);
419 p[1] = GETPIXELI(pData, 0);
421 pat[0] = (*pData)[0];
422 pat[1] = (*pData)[1];
425 patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
428 *pFrame -= (4*g_width - 4);
430 *pFrame += 4*g_width;
434 p[2] = GETPIXEL(pData, 8);
436 if (!(p[2]&0x8000)) {
437 for (i=0; i<4; i++) {
439 p[0] = GETPIXELI(pData, 0);
440 p[1] = GETPIXELI(pData, 0);
442 pat[0] = *(*pData)++;
443 pat[1] = *(*pData)++;
444 patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
447 *pFrame -= (4*g_width - 4);
449 *pFrame += 4*g_width;
453 for (i=0; i<8; i++) {
455 p[0] = GETPIXELI(pData, 0);
456 p[1] = GETPIXELI(pData, 0);
458 patternRow2Pixels(*pFrame, *(*pData), p);
468 p[0] = GETPIXELI(pData, 0);
469 p[1] = GETPIXELI(pData, 0);
470 p[2] = GETPIXELI(pData, 0);
471 p[3] = GETPIXELI(pData, 0);
475 if (!(p[0] & 0x8000)) {
476 if (!(p[2] & 0x8000)) {
477 for (i=0; i<8; i++) {
478 pat[0] = (*pData)[0];
479 pat[1] = (*pData)[1];
481 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
486 patternRow4Pixels2(*pFrame, (*pData)[0], p);
487 *pFrame += 2*g_width;
488 patternRow4Pixels2(*pFrame, (*pData)[1], p);
489 *pFrame += 2*g_width;
490 patternRow4Pixels2(*pFrame, (*pData)[2], p);
491 *pFrame += 2*g_width;
492 patternRow4Pixels2(*pFrame, (*pData)[3], p);
498 if (!(p[2] & 0x8000)) {
499 for (i=0; i<8; i++) {
500 pat[0] = (*pData)[0];
502 patternRow4Pixels2x1(*pFrame, pat[0], p);
507 for (i=0; i<4; i++) {
508 pat[0] = (*pData)[0];
509 pat[1] = (*pData)[1];
513 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
515 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
524 p[0] = GETPIXEL(pData, 0);
526 if (!(p[0] & 0x8000)) {
527 for (i=0; i<4; i++) {
528 p[0] = GETPIXELI(pData, 0);
529 p[1] = GETPIXELI(pData, 0);
530 p[2] = GETPIXELI(pData, 0);
531 p[3] = GETPIXELI(pData, 0);
532 pat[0] = (*pData)[0];
533 pat[1] = (*pData)[1];
534 pat[2] = (*pData)[2];
535 pat[3] = (*pData)[3];
539 patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
542 *pFrame -= (4*g_width - 4);
544 *pFrame += 4*g_width;
548 p[0] = GETPIXEL(pData, 16);
550 if (!(p[0] & 0x8000)) {
551 for (i=0; i<4; i++) {
553 p[0] = GETPIXELI(pData, 0);
554 p[1] = GETPIXELI(pData, 0);
555 p[2] = GETPIXELI(pData, 0);
556 p[3] = GETPIXELI(pData, 0);
559 pat[0] = (*pData)[0];
560 pat[1] = (*pData)[1];
561 pat[2] = (*pData)[2];
562 pat[3] = (*pData)[3];
566 patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
569 *pFrame -= (4*g_width - 4);
571 *pFrame += 4*g_width;
575 for (i=0; i<8; i++) {
577 p[0] = GETPIXELI(pData, 0);
578 p[1] = GETPIXELI(pData, 0);
579 p[2] = GETPIXELI(pData, 0);
580 p[3] = GETPIXELI(pData, 0);
583 pat[0] = (*pData)[0];
584 pat[1] = (*pData)[1];
585 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
595 for (i=0; i<8; i++) {
597 memcpy(&frame_tmp, *pData, 16);
599 for (j = 0; j < 16; j += 2) {
600 swap_tmp = (ushort*)(frame_tmp + j);
601 *swap_tmp = INTEL_SHORT(*swap_tmp);
604 memcpy(*pFrame, &frame_tmp, 16);
613 for (i=0; i<4; i++) {
614 p[0] = GETPIXEL(pData, 0);
615 p[1] = GETPIXEL(pData, 2);
616 p[2] = GETPIXEL(pData, 4);
617 p[3] = GETPIXEL(pData, 6);
619 for (j=0; j<2; j++) {
620 for (k=0; k<4; k++) {
621 (*pFrame)[2*k] = p[k];
622 (*pFrame)[2*k+1] = p[k];
624 // this is the original code but it messes up FS1 movies
625 // (*pFrame)[j+2*k] = p[k];
626 // (*pFrame)[g_width+j+2*k] = p[k];
637 for (i=0; i<2; i++) {
638 p[0] = GETPIXEL(pData, 0);
639 p[1] = GETPIXEL(pData, 2);
641 for (j=0; j<4; j++) {
642 for (k=0; k<4; k++) {
643 (*pFrame)[k*g_width+j] = p[0];
644 (*pFrame)[k*g_width+j+4] = p[1];
648 *pFrame += 4*g_width;
656 p[0] = GETPIXEL(pData, 0);
658 for (i = 0; i < 8; i++) {
659 for (j = 0; j < 8; j++) {
672 p[0] = GETPIXEL(pData, 0);
673 p[1] = GETPIXEL(pData, 1);
675 for (i=0; i<8; i++) {
676 for (j=0; j<8; j++) {
677 (*pFrame)[j] = p[(i+j)&1];