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