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