Fix bugs in previous commit that caused FTBFS in synfig and ETL FTBFS with older...
[synfig.git] / synfig-core / tags / synfig_0_61_03 / synfig-core / src / modules / mod_libavcodec / libavcodec / interplayvideo.c
1 /*
2  * Interplay MVE Video Decoder
3  * Copyright (C) 2003 the ffmpeg project
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
20
21 /**
22  * @file interplayvideo.c
23  * Interplay MVE Video Decoder by Mike Melanson (melanson@pcisys.net)
24  * For more information about the Interplay MVE format, visit:
25  *   http://www.pcisys.net/~melanson/codecs/interplay-mve.txt
26  * This code is written in such a way that the identifiers match up
27  * with the encoding descriptions in the document.
28  *
29  * This decoder presently only supports a PAL8 output colorspace.
30  *
31  * An Interplay video frame consists of 2 parts: The decoding map and
32  * the video data. A demuxer must load these 2 parts together in a single
33  * buffer before sending it through the stream to this decoder.
34  */
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 #include "common.h"
42 #include "avcodec.h"
43 #include "dsputil.h"
44
45 #define PALETTE_COUNT 256
46
47 /* debugging support */
48 #define DEBUG_INTERPLAY 0
49 #if DEBUG_INTERPLAY
50 #define debug_interplay printf
51 #else
52 static inline void debug_interplay(const char *format, ...) { }
53 #endif
54
55 typedef struct IpvideoContext {
56
57     AVCodecContext *avctx;
58     DSPContext dsp;
59     AVFrame second_last_frame;
60     AVFrame last_frame;
61     AVFrame current_frame;
62     unsigned char *decoding_map;
63     int decoding_map_size;
64
65     unsigned char *buf;
66     int size;
67
68     unsigned char palette[PALETTE_COUNT * 4];
69
70     unsigned char *stream_ptr;
71     unsigned char *stream_end;
72     unsigned char *pixel_ptr;
73     int line_inc;
74     int stride;
75     int upper_motion_limit_offset;
76
77 } IpvideoContext;
78
79 #define CHECK_STREAM_PTR(n) \
80   if ((s->stream_ptr + n) > s->stream_end) { \
81     printf ("Interplay video warning: stream_ptr out of bounds (%p >= %p)\n", \
82       s->stream_ptr + n, s->stream_end); \
83     return -1; \
84   }
85
86 static void ipvideo_new_palette(IpvideoContext *s, unsigned char *palette) {
87
88     int i;
89     unsigned char r, g, b;
90     unsigned int *palette32;
91
92     palette32 = (unsigned int *)s->palette;
93     for (i = 0; i < PALETTE_COUNT; i++) {
94         r = *palette++;
95         g = *palette++;
96         b = *palette++;
97         palette32[i] = (r << 16) | (g << 8) | (b);
98     }
99 }
100
101 #define COPY_FROM_CURRENT() \
102     motion_offset = current_offset; \
103     motion_offset += y * s->stride; \
104     motion_offset += x; \
105     if (motion_offset < 0) { \
106         printf (" Interplay video: motion offset < 0 (%d)\n", motion_offset); \
107         return -1; \
108     } else if (motion_offset > s->upper_motion_limit_offset) { \
109         printf (" Interplay video: motion offset above limit (%d >= %d)\n", \
110             motion_offset, s->upper_motion_limit_offset); \
111         return -1; \
112     } \
113     s->dsp.put_pixels_tab[0][0](s->pixel_ptr, \
114         s->current_frame.data[0] + motion_offset, s->stride, 8);
115
116 #define COPY_FROM_PREVIOUS() \
117     motion_offset = current_offset; \
118     motion_offset += y * s->stride; \
119     motion_offset += x; \
120     if (motion_offset < 0) { \
121         printf (" Interplay video: motion offset < 0 (%d)\n", motion_offset); \
122         return -1; \
123     } else if (motion_offset > s->upper_motion_limit_offset) { \
124         printf (" Interplay video: motion offset above limit (%d >= %d)\n", \
125             motion_offset, s->upper_motion_limit_offset); \
126         return -1; \
127     } \
128     s->dsp.put_pixels_tab[0][0](s->pixel_ptr, \
129         s->last_frame.data[0] + motion_offset, s->stride, 8);
130
131 #define COPY_FROM_SECOND_LAST() \
132     motion_offset = current_offset; \
133     motion_offset += y * s->stride; \
134     motion_offset += x; \
135     if (motion_offset < 0) { \
136         printf (" Interplay video: motion offset < 0 (%d)\n", motion_offset); \
137         return -1; \
138     } else if (motion_offset > s->upper_motion_limit_offset) { \
139         printf (" Interplay video: motion offset above limit (%d >= %d)\n", \
140             motion_offset, s->upper_motion_limit_offset); \
141         return -1; \
142     } \
143     s->dsp.put_pixels_tab[0][0](s->pixel_ptr, \
144         s->second_last_frame.data[0] + motion_offset, s->stride, 8);
145
146 static int ipvideo_decode_block_opcode_0x0(IpvideoContext *s)
147 {
148     int x, y;
149     int motion_offset;
150     int current_offset = s->pixel_ptr - s->current_frame.data[0];
151
152     /* copy a block from the previous frame */
153     x = y = 0;
154     COPY_FROM_PREVIOUS();
155
156     /* report success */
157     return 0;
158 }
159
160 static int ipvideo_decode_block_opcode_0x1(IpvideoContext *s)
161 {
162     int x, y;
163     int motion_offset;
164     int current_offset = s->pixel_ptr - s->current_frame.data[0];
165
166     /* copy block from 2 frames ago */
167     x = y = 0;
168     COPY_FROM_SECOND_LAST();
169
170     /* report success */
171     return 0;
172 }
173
174 static int ipvideo_decode_block_opcode_0x2(IpvideoContext *s)
175 {
176     unsigned char B;
177     int x, y;
178     int motion_offset;
179     int current_offset = s->pixel_ptr - s->current_frame.data[0];
180
181     /* copy block from 2 frames ago using a motion vector; need 1 more byte */
182     CHECK_STREAM_PTR(1);
183     B = *s->stream_ptr++;
184
185     if (B < 56) {
186         x = 8 + (B % 7);
187         y = B / 7;
188     } else {
189         x = -14 + ((B - 56) % 29);
190         y =   8 + ((B - 56) / 29);
191     }
192
193     debug_interplay ("    motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
194     COPY_FROM_SECOND_LAST();
195
196     /* report success */
197     return 0;
198 }
199
200 static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s)
201 {
202     unsigned char B;
203     int x, y;
204     int motion_offset;
205     int current_offset = s->pixel_ptr - s->current_frame.data[0];
206
207     /* copy 8x8 block from current frame from an up/left block */
208
209     /* need 1 more byte for motion */
210     CHECK_STREAM_PTR(1);
211     B = *s->stream_ptr++;
212
213     if (B < 56) {
214         x = -(8 + (B % 7));
215         y = -(B / 7);
216     } else {
217         x = -(-14 + ((B - 56) % 29));
218         y = -(  8 + ((B - 56) / 29));
219     }
220
221     debug_interplay ("    motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
222     COPY_FROM_CURRENT();
223
224     /* report success */
225     return 0;
226 }
227
228 static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s)
229 {
230     int x, y;
231     unsigned char B, BL, BH;
232     int motion_offset;
233     int current_offset = s->pixel_ptr - s->current_frame.data[0];
234
235     /* copy a block from the previous frame; need 1 more byte */
236     CHECK_STREAM_PTR(1);
237
238     B = *s->stream_ptr++;
239     BL = B & 0x0F;
240     BH = (B >> 4) & 0x0F;
241     x = -8 + BL;
242     y = -8 + BH;
243
244     debug_interplay ("    motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
245     COPY_FROM_PREVIOUS();
246
247     /* report success */
248     return 0;
249 }
250
251 static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s)
252 {
253     signed char x, y;
254     int motion_offset;
255     int current_offset = s->pixel_ptr - s->current_frame.data[0];
256
257     /* copy a block from the previous frame using an expanded range;
258      * need 2 more bytes */
259     CHECK_STREAM_PTR(2);
260
261     x = *s->stream_ptr++;
262     y = *s->stream_ptr++;
263
264     debug_interplay ("    motion bytes = %d, %d\n", x, y);
265     COPY_FROM_PREVIOUS();
266
267     /* report success */
268     return 0;
269 }
270
271 static int ipvideo_decode_block_opcode_0x6(IpvideoContext *s)
272 {
273     /* mystery opcode? skip multiple blocks? */
274     printf ("  Interplay video: Help! Mystery opcode 0x6 seen\n");
275
276     /* report success */
277     return 0;
278 }
279
280 static int ipvideo_decode_block_opcode_0x7(IpvideoContext *s)
281 {
282     int x, y;
283     unsigned char P0, P1;
284     unsigned char B[8];
285     unsigned int flags;
286     int bitmask;
287
288     /* 2-color encoding */
289     CHECK_STREAM_PTR(2);
290
291     P0 = *s->stream_ptr++;
292     P1 = *s->stream_ptr++;
293
294     if (P0 <= P1) {
295
296         /* need 8 more bytes from the stream */
297         CHECK_STREAM_PTR(8);
298         for (y = 0; y < 8; y++)
299             B[y] = *s->stream_ptr++;
300
301         for (y = 0; y < 8; y++) {
302             flags = B[y];
303             for (x = 0x01; x <= 0x80; x <<= 1) {
304                 if (flags & x)
305                     *s->pixel_ptr++ = P1;
306                 else
307                     *s->pixel_ptr++ = P0;
308             }
309             s->pixel_ptr += s->line_inc;
310         }
311
312     } else {
313
314         /* need 2 more bytes from the stream */
315         CHECK_STREAM_PTR(2);
316         B[0] = *s->stream_ptr++;
317         B[1] = *s->stream_ptr++;
318
319         flags = (B[1] << 8) | B[0];
320         bitmask = 0x0001;
321         for (y = 0; y < 8; y += 2) {
322             for (x = 0; x < 8; x += 2, bitmask <<= 1) {
323                 if (flags & bitmask) {
324                     *(s->pixel_ptr + x) = P1;
325                     *(s->pixel_ptr + x + 1) = P1;
326                     *(s->pixel_ptr + s->stride + x) = P1;
327                     *(s->pixel_ptr + s->stride + x + 1) = P1;
328                 } else {
329                     *(s->pixel_ptr + x) = P0;
330                     *(s->pixel_ptr + x + 1) = P0;
331                     *(s->pixel_ptr + s->stride + x) = P0;
332                     *(s->pixel_ptr + s->stride + x + 1) = P0;
333                 }
334             }
335             s->pixel_ptr += s->stride * 2;
336         }
337     }
338
339     /* report success */
340     return 0;
341 }
342
343 static int ipvideo_decode_block_opcode_0x8(IpvideoContext *s)
344 {
345     int x, y;
346     unsigned char P[8];
347     unsigned char B[8];
348     unsigned int flags = 0;
349     unsigned int bitmask = 0;
350     unsigned char P0 = 0, P1 = 0;
351     int lower_half = 0;
352
353     /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
354      * either top and bottom or left and right halves */
355     CHECK_STREAM_PTR(2);
356
357     P[0] = *s->stream_ptr++;
358     P[1] = *s->stream_ptr++;
359
360     if (P[0] <= P[1]) {
361
362         /* need 12 more bytes */
363         CHECK_STREAM_PTR(12);
364         B[0] = *s->stream_ptr++;  B[1] = *s->stream_ptr++;
365         P[2] = *s->stream_ptr++;  P[3] = *s->stream_ptr++;
366         B[2] = *s->stream_ptr++;  B[3] = *s->stream_ptr++;
367         P[4] = *s->stream_ptr++;  P[5] = *s->stream_ptr++;
368         B[4] = *s->stream_ptr++;  B[5] = *s->stream_ptr++;
369         P[6] = *s->stream_ptr++;  P[7] = *s->stream_ptr++;
370         B[6] = *s->stream_ptr++;  B[7] = *s->stream_ptr++;
371
372         for (y = 0; y < 8; y++) {
373
374             /* time to reload flags? */
375             if (y == 0) {
376                 flags =
377                     ((B[0] & 0xF0) <<  4) | ((B[4] & 0xF0) <<  8) |
378                     ((B[0] & 0x0F)      ) | ((B[4] & 0x0F) <<  4) |
379                     ((B[1] & 0xF0) << 20) | ((B[5] & 0xF0) << 24) |
380                     ((B[1] & 0x0F) << 16) | ((B[5] & 0x0F) << 20);
381                 bitmask = 0x00000001;
382                 lower_half = 0;  /* still on top half */
383             } else if (y == 4) {
384                 flags =
385                     ((B[2] & 0xF0) <<  4) | ((B[6] & 0xF0) <<  8) |
386                     ((B[2] & 0x0F)      ) | ((B[6] & 0x0F) <<  4) |
387                     ((B[3] & 0xF0) << 20) | ((B[7] & 0xF0) << 24) |
388                     ((B[3] & 0x0F) << 16) | ((B[7] & 0x0F) << 20);
389                 bitmask = 0x00000001;
390                 lower_half = 2;
391             }
392
393             for (x = 0; x < 8; x++, bitmask <<= 1) {
394                 /* get the pixel values ready for this quadrant */
395                 if (x == 0) {
396                     P0 = P[lower_half + 0];
397                     P1 = P[lower_half + 1];
398                 } else if (x == 4) {
399                     P0 = P[lower_half + 4];
400                     P1 = P[lower_half + 5];
401                 }
402
403                 if (flags & bitmask)
404                     *s->pixel_ptr++ = P1;
405                 else
406                     *s->pixel_ptr++ = P0;
407             }
408             s->pixel_ptr += s->line_inc;
409         }
410
411     } else {
412
413         /* need 10 more bytes */
414         CHECK_STREAM_PTR(10);
415         B[0] = *s->stream_ptr++;  B[1] = *s->stream_ptr++;
416         B[2] = *s->stream_ptr++;  B[3] = *s->stream_ptr++;
417         P[2] = *s->stream_ptr++;  P[3] = *s->stream_ptr++;
418         B[4] = *s->stream_ptr++;  B[5] = *s->stream_ptr++;
419         B[6] = *s->stream_ptr++;  B[7] = *s->stream_ptr++;
420
421         if (P[2] <= P[3]) {
422
423             /* vertical split; left & right halves are 2-color encoded */
424
425             for (y = 0; y < 8; y++) {
426
427                 /* time to reload flags? */
428                 if (y == 0) {
429                     flags =
430                         ((B[0] & 0xF0) <<  4) | ((B[4] & 0xF0) <<  8) |
431                         ((B[0] & 0x0F)      ) | ((B[4] & 0x0F) <<  4) |
432                         ((B[1] & 0xF0) << 20) | ((B[5] & 0xF0) << 24) |
433                         ((B[1] & 0x0F) << 16) | ((B[5] & 0x0F) << 20);
434                     bitmask = 0x00000001;
435                 } else if (y == 4) {
436                     flags =
437                         ((B[2] & 0xF0) <<  4) | ((B[6] & 0xF0) <<  8) |
438                         ((B[2] & 0x0F)      ) | ((B[6] & 0x0F) <<  4) |
439                         ((B[3] & 0xF0) << 20) | ((B[7] & 0xF0) << 24) |
440                         ((B[3] & 0x0F) << 16) | ((B[7] & 0x0F) << 20);
441                     bitmask = 0x00000001;
442                 }
443
444                 for (x = 0; x < 8; x++, bitmask <<= 1) {
445                     /* get the pixel values ready for this half */
446                     if (x == 0) {
447                         P0 = P[0];
448                         P1 = P[1];
449                     } else if (x == 4) {
450                         P0 = P[2];
451                         P1 = P[3];
452                     }
453
454                     if (flags & bitmask)
455                         *s->pixel_ptr++ = P1;
456                     else
457                         *s->pixel_ptr++ = P0;
458                 }
459                 s->pixel_ptr += s->line_inc;
460             }
461
462         } else {
463
464             /* horizontal split; top & bottom halves are 2-color encoded */
465
466             for (y = 0; y < 8; y++) {
467
468                 flags = B[y];
469                 if (y == 0) {
470                     P0 = P[0];
471                     P1 = P[1];
472                 } else if (y == 4) {
473                     P0 = P[2];
474                     P1 = P[3];
475                 }
476
477                 for (bitmask = 0x01; bitmask <= 0x80; bitmask <<= 1) {
478
479                     if (flags & bitmask)
480                         *s->pixel_ptr++ = P1;
481                     else
482                         *s->pixel_ptr++ = P0;
483                 }
484                 s->pixel_ptr += s->line_inc;
485             }
486         }
487     }
488
489     /* report success */
490     return 0;
491 }
492
493 static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s)
494 {
495     int x, y;
496     unsigned char P[4];
497     unsigned char B[4];
498     unsigned int flags = 0;
499     int shifter = 0;
500     unsigned char pix;
501
502     /* 4-color encoding */
503     CHECK_STREAM_PTR(4);
504
505     for (y = 0; y < 4; y++)
506         P[y] = *s->stream_ptr++;
507
508     if ((P[0] <= P[1]) && (P[2] <= P[3])) {
509
510         /* 1 of 4 colors for each pixel, need 16 more bytes */
511         CHECK_STREAM_PTR(16);
512
513         for (y = 0; y < 8; y++) {
514             /* get the next set of 8 2-bit flags */
515             flags = (s->stream_ptr[1] << 8) | s->stream_ptr[0];
516             s->stream_ptr += 2;
517             for (x = 0, shifter = 0; x < 8; x++, shifter += 2) {
518                 *s->pixel_ptr++ = P[(flags >> shifter) & 0x03];
519             }
520             s->pixel_ptr += s->line_inc;
521         }
522
523     } else if ((P[0] <= P[1]) && (P[2] > P[3])) {
524
525         /* 1 of 4 colors for each 2x2 block, need 4 more bytes */
526         CHECK_STREAM_PTR(4);
527
528         B[0] = *s->stream_ptr++;
529         B[1] = *s->stream_ptr++;
530         B[2] = *s->stream_ptr++;
531         B[3] = *s->stream_ptr++;
532         flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
533         shifter = 0;
534
535         for (y = 0; y < 8; y += 2) {
536             for (x = 0; x < 8; x += 2, shifter += 2) {
537                 pix = P[(flags >> shifter) & 0x03];
538                 *(s->pixel_ptr + x) = pix;
539                 *(s->pixel_ptr + x + 1) = pix;
540                 *(s->pixel_ptr + s->stride + x) = pix;
541                 *(s->pixel_ptr + s->stride + x + 1) = pix;
542             }
543             s->pixel_ptr += s->stride * 2;
544         }
545
546     } else if ((P[0] > P[1]) && (P[2] <= P[3])) {
547
548         /* 1 of 4 colors for each 2x1 block, need 8 more bytes */
549         CHECK_STREAM_PTR(8);
550
551         for (y = 0; y < 8; y++) {
552             /* time to reload flags? */
553             if ((y == 0) || (y == 4)) {
554                 B[0] = *s->stream_ptr++;
555                 B[1] = *s->stream_ptr++;
556                 B[2] = *s->stream_ptr++;
557                 B[3] = *s->stream_ptr++;
558                 flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
559                 shifter = 0;
560             }
561             for (x = 0; x < 8; x += 2, shifter += 2) {
562                 pix = P[(flags >> shifter) & 0x03];
563                 *(s->pixel_ptr + x) = pix;
564                 *(s->pixel_ptr + x + 1) = pix;
565             }
566             s->pixel_ptr += s->stride;
567         }
568
569     } else {
570
571         /* 1 of 4 colors for each 1x2 block, need 8 more bytes */
572         CHECK_STREAM_PTR(8);
573
574         for (y = 0; y < 8; y += 2) {
575             /* time to reload flags? */
576             if ((y == 0) || (y == 4)) {
577                 B[0] = *s->stream_ptr++;
578                 B[1] = *s->stream_ptr++;
579                 B[2] = *s->stream_ptr++;
580                 B[3] = *s->stream_ptr++;
581                 flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
582                 shifter = 0;
583             }
584             for (x = 0; x < 8; x++, shifter += 2) {
585                 pix = P[(flags >> shifter) & 0x03];
586                 *(s->pixel_ptr + x) = pix;
587                 *(s->pixel_ptr + s->stride + x) = pix;
588             }
589             s->pixel_ptr += s->stride * 2;
590         }
591     }
592
593     /* report success */
594     return 0;
595 }
596
597 static int ipvideo_decode_block_opcode_0xA(IpvideoContext *s)
598 {
599     int x, y;
600     unsigned char P[16];
601     unsigned char B[16];
602     int flags = 0;
603     int shifter = 0;
604     int index;
605     int split;
606     int lower_half;
607
608     /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
609      * either top and bottom or left and right halves */
610     CHECK_STREAM_PTR(4);
611
612     for (y = 0; y < 4; y++)
613         P[y] = *s->stream_ptr++;
614
615     if (P[0] <= P[1]) {
616
617         /* 4-color encoding for each quadrant; need 28 more bytes */
618         CHECK_STREAM_PTR(28);
619
620         for (y = 0; y < 4; y++)
621             B[y] = *s->stream_ptr++;
622         for (y = 4; y < 16; y += 4) {
623             for (x = y; x < y + 4; x++)
624                 P[x] = *s->stream_ptr++;
625             for (x = y; x < y + 4; x++)
626                 B[x] = *s->stream_ptr++;
627         }
628
629         for (y = 0; y < 8; y++) {
630
631             lower_half = (y >= 4) ? 4 : 0;
632             flags = (B[y + 8] << 8) | B[y];
633
634             for (x = 0, shifter = 0; x < 8; x++, shifter += 2) {
635                 split = (x >= 4) ? 8 : 0;
636                 index = split + lower_half + ((flags >> shifter) & 0x03);
637                 *s->pixel_ptr++ = P[index];
638             }
639
640             s->pixel_ptr += s->line_inc;
641         }
642
643     } else {
644
645         /* 4-color encoding for either left and right or top and bottom
646          * halves; need 20 more bytes */
647         CHECK_STREAM_PTR(20);
648
649         for (y = 0; y < 8; y++)
650             B[y] = *s->stream_ptr++;
651         for (y = 4; y < 8; y++)
652             P[y] = *s->stream_ptr++;
653         for (y = 8; y < 16; y++)
654             B[y] = *s->stream_ptr++;
655
656         if (P[4] <= P[5]) {
657
658             /* block is divided into left and right halves */
659             for (y = 0; y < 8; y++) {
660
661                 flags = (B[y + 8] << 8) | B[y];
662                 split = 0;
663
664                 for (x = 0, shifter = 0; x < 8; x++, shifter += 2) {
665                     if (x == 4)
666                         split = 4;
667                     *s->pixel_ptr++ = P[split + ((flags >> shifter) & 0x03)];
668                 }
669
670                 s->pixel_ptr += s->line_inc;
671             }
672
673         } else {
674
675             /* block is divided into top and bottom halves */
676             split = 0;
677             for (y = 0; y < 8; y++) {
678
679                 flags = (B[y * 2 + 1] << 8) | B[y * 2];
680                 if (y == 4)
681                     split = 4;
682
683                 for (x = 0, shifter = 0; x < 8; x++, shifter += 2)
684                     *s->pixel_ptr++ = P[split + ((flags >> shifter) & 0x03)];
685
686                 s->pixel_ptr += s->line_inc;
687             }
688         }
689     }
690
691     /* report success */
692     return 0;
693 }
694
695 static int ipvideo_decode_block_opcode_0xB(IpvideoContext *s)
696 {
697     int x, y;
698
699     /* 64-color encoding (each pixel in block is a different color) */
700     CHECK_STREAM_PTR(64);
701
702     for (y = 0; y < 8; y++) {
703         for (x = 0; x < 8; x++) {
704             *s->pixel_ptr++ = *s->stream_ptr++;
705         }
706         s->pixel_ptr += s->line_inc;
707     }
708
709     /* report success */
710     return 0;
711 }
712
713 static int ipvideo_decode_block_opcode_0xC(IpvideoContext *s)
714 {
715     int x, y;
716     unsigned char pix;
717
718     /* 16-color block encoding: each 2x2 block is a different color */
719     CHECK_STREAM_PTR(16);
720
721     for (y = 0; y < 8; y += 2) {
722         for (x = 0; x < 8; x += 2) {
723             pix = *s->stream_ptr++;
724             *(s->pixel_ptr + x) = pix;
725             *(s->pixel_ptr + x + 1) = pix;
726             *(s->pixel_ptr + s->stride + x) = pix;
727             *(s->pixel_ptr + s->stride + x + 1) = pix;
728         }
729         s->pixel_ptr += s->stride * 2;
730     }
731
732     /* report success */
733     return 0;
734 }
735
736 static int ipvideo_decode_block_opcode_0xD(IpvideoContext *s)
737 {
738     int x, y;
739     unsigned char P[4];
740     unsigned char index = 0;
741
742     /* 4-color block encoding: each 4x4 block is a different color */
743     CHECK_STREAM_PTR(4);
744
745     for (y = 0; y < 4; y++)
746         P[y] = *s->stream_ptr++;
747
748     for (y = 0; y < 8; y++) {
749         if (y < 4)
750             index = 0;
751         else
752             index = 2;
753
754         for (x = 0; x < 8; x++) {
755             if (x == 4)
756                 index++;
757             *s->pixel_ptr++ = P[index];
758         }
759         s->pixel_ptr += s->line_inc;
760     }
761
762     /* report success */
763     return 0;
764 }
765
766 static int ipvideo_decode_block_opcode_0xE(IpvideoContext *s)
767 {
768     int x, y;
769     unsigned char pix;
770
771     /* 1-color encoding: the whole block is 1 solid color */
772     CHECK_STREAM_PTR(1);
773     pix = *s->stream_ptr++;
774
775     for (y = 0; y < 8; y++) {
776         for (x = 0; x < 8; x++) {
777             *s->pixel_ptr++ = pix;
778         }
779         s->pixel_ptr += s->line_inc;
780     }
781
782     /* report success */
783     return 0;
784 }
785
786 static int ipvideo_decode_block_opcode_0xF(IpvideoContext *s)
787 {
788     int x, y;
789     unsigned char sample0, sample1;
790
791     /* dithered encoding */
792     CHECK_STREAM_PTR(2);
793     sample0 = *s->stream_ptr++;
794     sample1 = *s->stream_ptr++;
795
796     for (y = 0; y < 8; y++) {
797         for (x = 0; x < 8; x += 2) {
798             if (y & 1) {
799                 *s->pixel_ptr++ = sample1;
800                 *s->pixel_ptr++ = sample0;
801             } else {
802                 *s->pixel_ptr++ = sample0;
803                 *s->pixel_ptr++ = sample1;
804             }
805         }
806         s->pixel_ptr += s->line_inc;
807     }
808
809     /* report success */
810     return 0;
811 }
812
813 static int (*ipvideo_decode_block[16])(IpvideoContext *s);
814
815 static void ipvideo_decode_opcodes(IpvideoContext *s)
816 {
817     int x, y;
818     int index = 0;
819     unsigned char opcode;
820     int ret;
821     int code_counts[16];
822     static int frame = 0;
823
824     debug_interplay("------------------ frame %d\n", frame);
825     frame++;
826
827     for (x = 0; x < 16; x++)
828         code_counts[x] = 0;
829
830     /* this is PAL8, so make the palette available */
831     memcpy(s->current_frame.data[1], s->palette, PALETTE_COUNT * 4);
832
833     s->stride = s->current_frame.linesize[0];
834     s->stream_ptr = s->buf + 14;  /* data starts 14 bytes in */
835     s->stream_end = s->buf + s->size;
836     s->line_inc = s->stride - 8;
837     s->upper_motion_limit_offset = (s->avctx->height - 8) * s->stride
838         + s->avctx->width - 8;
839     s->dsp = s->dsp;
840
841     for (y = 0; y < (s->stride * s->avctx->height); y += s->stride * 8) {
842         for (x = y; x < y + s->avctx->width; x += 8) {
843             /* bottom nibble first, then top nibble (which makes it
844              * hard to use a GetBitcontext) */
845             if (index & 1)
846                 opcode = s->decoding_map[index >> 1] >> 4;
847             else
848                 opcode = s->decoding_map[index >> 1] & 0xF;
849             index++;
850
851             debug_interplay("  block @ (%3d, %3d): encoding 0x%X, data ptr @ %p\n",
852                 x - y, y / s->stride, opcode, s->stream_ptr);
853             code_counts[opcode]++;
854
855             s->pixel_ptr = s->current_frame.data[0] + x;
856             ret = ipvideo_decode_block[opcode](s);
857             if (ret != 0) {
858                 printf(" Interplay video: decode problem on frame %d, @ block (%d, %d)\n",
859                     frame, x - y, y / s->stride);
860                 return;
861             }
862         }
863     }
864     if ((s->stream_ptr != s->stream_end) &&
865         (s->stream_ptr + 1 != s->stream_end)) {
866         printf (" Interplay video: decode finished with %d bytes left over\n",
867             s->stream_end - s->stream_ptr);
868     }
869 }
870
871 static int ipvideo_decode_init(AVCodecContext *avctx)
872 {
873     IpvideoContext *s = avctx->priv_data;
874
875     s->avctx = avctx;
876
877     if (s->avctx->extradata_size != sizeof(AVPaletteControl)) {
878         printf (" Interplay video: expected extradata_size of %d\n",
879             sizeof(AVPaletteControl));
880         return -1;
881     }
882
883     avctx->pix_fmt = PIX_FMT_PAL8;
884     avctx->has_b_frames = 0;
885     dsputil_init(&s->dsp, avctx);
886
887     /* decoding map contains 4 bits of information per 8x8 block */
888     s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2);
889
890     /* assign block decode functions */
891     ipvideo_decode_block[0x0] = ipvideo_decode_block_opcode_0x0;
892     ipvideo_decode_block[0x1] = ipvideo_decode_block_opcode_0x1;
893     ipvideo_decode_block[0x2] = ipvideo_decode_block_opcode_0x2;
894     ipvideo_decode_block[0x3] = ipvideo_decode_block_opcode_0x3;
895     ipvideo_decode_block[0x4] = ipvideo_decode_block_opcode_0x4;
896     ipvideo_decode_block[0x5] = ipvideo_decode_block_opcode_0x5;
897     ipvideo_decode_block[0x6] = ipvideo_decode_block_opcode_0x6;
898     ipvideo_decode_block[0x7] = ipvideo_decode_block_opcode_0x7;
899     ipvideo_decode_block[0x8] = ipvideo_decode_block_opcode_0x8;
900     ipvideo_decode_block[0x9] = ipvideo_decode_block_opcode_0x9;
901     ipvideo_decode_block[0xA] = ipvideo_decode_block_opcode_0xA;
902     ipvideo_decode_block[0xB] = ipvideo_decode_block_opcode_0xB;
903     ipvideo_decode_block[0xC] = ipvideo_decode_block_opcode_0xC;
904     ipvideo_decode_block[0xD] = ipvideo_decode_block_opcode_0xD;
905     ipvideo_decode_block[0xE] = ipvideo_decode_block_opcode_0xE;
906     ipvideo_decode_block[0xF] = ipvideo_decode_block_opcode_0xF;
907
908     s->current_frame.data[0] = s->last_frame.data[0] =
909     s->second_last_frame.data[0] = NULL;
910
911     return 0;
912 }
913
914 static int ipvideo_decode_frame(AVCodecContext *avctx,
915                                 void *data, int *data_size,
916                                 uint8_t *buf, int buf_size)
917 {
918     IpvideoContext *s = avctx->priv_data;
919     AVPaletteControl *palette_control = (AVPaletteControl *)avctx->extradata;
920
921     if (palette_control->palette_changed) {
922         /* load the new palette and reset the palette control */
923         ipvideo_new_palette(s, palette_control->palette);
924         palette_control->palette_changed = 0;
925     }
926
927     s->decoding_map = buf;
928     s->buf = buf + s->decoding_map_size;
929     s->size = buf_size - s->decoding_map_size;
930
931     s->current_frame.reference = 3;
932     if (avctx->get_buffer(avctx, &s->current_frame)) {
933         printf ("  Interplay Video: get_buffer() failed\n");
934         return -1;
935     }
936
937     ipvideo_decode_opcodes(s);
938
939     *data_size = sizeof(AVFrame);
940     *(AVFrame*)data = s->current_frame;
941
942     /* shuffle frames */
943     if (s->second_last_frame.data[0])
944         avctx->release_buffer(avctx, &s->second_last_frame);
945     s->second_last_frame = s->last_frame;
946     s->last_frame = s->current_frame;
947     s->current_frame.data[0] = NULL;  /* catch any access attempts */
948
949     /* report that the buffer was completely consumed */
950     return buf_size;
951 }
952
953 static int ipvideo_decode_end(AVCodecContext *avctx)
954 {
955     IpvideoContext *s = avctx->priv_data;
956
957     /* release the last frame */
958     if (s->last_frame.data[0])
959         avctx->release_buffer(avctx, &s->last_frame);
960     if (s->second_last_frame.data[0])
961         avctx->release_buffer(avctx, &s->second_last_frame);
962
963     return 0;
964 }
965
966 AVCodec interplay_video_decoder = {
967     "interplayvideo",
968     CODEC_TYPE_VIDEO,
969     CODEC_ID_INTERPLAY_VIDEO,
970     sizeof(IpvideoContext),
971     ipvideo_decode_init,
972     NULL,
973     ipvideo_decode_end,
974     ipvideo_decode_frame,
975     CODEC_CAP_DR1,
976 };