OSDN Git Service

Add AVX FFT implementation.
[coroid/libav_saccubus.git] / libavcodec / interplayvideo.c
1 /*
2  * Interplay MVE Video Decoder
3  * Copyright (C) 2003 the ffmpeg project
4  *
5  * This file is part of Libav.
6  *
7  * Libav 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  * Libav 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 Libav; 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
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
41 #include "avcodec.h"
42 #include "bytestream.h"
43 #include "dsputil.h"
44 #define ALT_BITSTREAM_READER_LE
45 #include "get_bits.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     const unsigned char *decoding_map;
65     int decoding_map_size;
66
67     const unsigned char *buf;
68     int size;
69
70     int is_16bpp;
71     const unsigned char *stream_ptr;
72     const unsigned char *stream_end;
73     const uint8_t *mv_ptr;
74     const uint8_t *mv_end;
75     unsigned char *pixel_ptr;
76     int line_inc;
77     int stride;
78     int upper_motion_limit_offset;
79
80     uint32_t pal[256];
81 } IpvideoContext;
82
83 #define CHECK_STREAM_PTR(stream_ptr, stream_end, n) \
84     if (stream_end - stream_ptr < n) { \
85         av_log(s->avctx, AV_LOG_ERROR, "Interplay video warning: stream_ptr out of bounds (%p >= %p)\n", \
86                stream_ptr + n, stream_end); \
87         return -1; \
88     }
89
90 static int copy_from(IpvideoContext *s, AVFrame *src, int delta_x, int delta_y)
91 {
92     int current_offset = s->pixel_ptr - s->current_frame.data[0];
93     int motion_offset = current_offset + delta_y * s->current_frame.linesize[0]
94                        + delta_x * (1 + s->is_16bpp);
95     if (motion_offset < 0) {
96         av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset < 0 (%d)\n", motion_offset);
97         return -1;
98     } else if (motion_offset > s->upper_motion_limit_offset) {
99         av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset above limit (%d >= %d)\n",
100             motion_offset, s->upper_motion_limit_offset);
101         return -1;
102     }
103     if (src->data[0] == NULL) {
104         av_log(s->avctx, AV_LOG_ERROR, "Invalid decode type, corrupted header?\n");
105         return AVERROR(EINVAL);
106     }
107     s->dsp.put_pixels_tab[!s->is_16bpp][0](s->pixel_ptr, src->data[0] + motion_offset,
108                                            s->current_frame.linesize[0], 8);
109     return 0;
110 }
111
112 static int ipvideo_decode_block_opcode_0x0(IpvideoContext *s)
113 {
114     return copy_from(s, &s->last_frame, 0, 0);
115 }
116
117 static int ipvideo_decode_block_opcode_0x1(IpvideoContext *s)
118 {
119     return copy_from(s, &s->second_last_frame, 0, 0);
120 }
121
122 static int ipvideo_decode_block_opcode_0x2(IpvideoContext *s)
123 {
124     unsigned char B;
125     int x, y;
126
127     /* copy block from 2 frames ago using a motion vector; need 1 more byte */
128     if (!s->is_16bpp) {
129         CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
130         B = *s->stream_ptr++;
131     } else {
132         CHECK_STREAM_PTR(s->mv_ptr, s->mv_end, 1);
133         B = *s->mv_ptr++;
134     }
135
136     if (B < 56) {
137         x = 8 + (B % 7);
138         y = B / 7;
139     } else {
140         x = -14 + ((B - 56) % 29);
141         y =   8 + ((B - 56) / 29);
142     }
143
144     debug_interplay ("    motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
145     return copy_from(s, &s->second_last_frame, x, y);
146 }
147
148 static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s)
149 {
150     unsigned char B;
151     int x, y;
152
153     /* copy 8x8 block from current frame from an up/left block */
154
155     /* need 1 more byte for motion */
156     if (!s->is_16bpp) {
157         CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
158         B = *s->stream_ptr++;
159     } else {
160         CHECK_STREAM_PTR(s->mv_ptr, s->mv_end, 1);
161         B = *s->mv_ptr++;
162     }
163
164     if (B < 56) {
165         x = -(8 + (B % 7));
166         y = -(B / 7);
167     } else {
168         x = -(-14 + ((B - 56) % 29));
169         y = -(  8 + ((B - 56) / 29));
170     }
171
172     debug_interplay ("    motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
173     return copy_from(s, &s->current_frame, x, y);
174 }
175
176 static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s)
177 {
178     int x, y;
179     unsigned char B, BL, BH;
180
181     /* copy a block from the previous frame; need 1 more byte */
182     if (!s->is_16bpp) {
183         CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
184         B = *s->stream_ptr++;
185     } else {
186         CHECK_STREAM_PTR(s->mv_ptr, s->mv_end, 1);
187         B = *s->mv_ptr++;
188     }
189
190     BL = B & 0x0F;
191     BH = (B >> 4) & 0x0F;
192     x = -8 + BL;
193     y = -8 + BH;
194
195     debug_interplay ("    motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
196     return copy_from(s, &s->last_frame, x, y);
197 }
198
199 static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s)
200 {
201     signed char x, y;
202
203     /* copy a block from the previous frame using an expanded range;
204      * need 2 more bytes */
205     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
206
207     x = *s->stream_ptr++;
208     y = *s->stream_ptr++;
209
210     debug_interplay ("    motion bytes = %d, %d\n", x, y);
211     return copy_from(s, &s->last_frame, x, y);
212 }
213
214 static int ipvideo_decode_block_opcode_0x6(IpvideoContext *s)
215 {
216     /* mystery opcode? skip multiple blocks? */
217     av_log(s->avctx, AV_LOG_ERROR, "  Interplay video: Help! Mystery opcode 0x6 seen\n");
218
219     /* report success */
220     return 0;
221 }
222
223 static int ipvideo_decode_block_opcode_0x7(IpvideoContext *s)
224 {
225     int x, y;
226     unsigned char P[2];
227     unsigned int flags;
228
229     /* 2-color encoding */
230     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
231
232     P[0] = *s->stream_ptr++;
233     P[1] = *s->stream_ptr++;
234
235     if (P[0] <= P[1]) {
236
237         /* need 8 more bytes from the stream */
238         CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
239
240         for (y = 0; y < 8; y++) {
241             flags = *s->stream_ptr++ | 0x100;
242             for (; flags != 1; flags >>= 1)
243                 *s->pixel_ptr++ = P[flags & 1];
244             s->pixel_ptr += s->line_inc;
245         }
246
247     } else {
248
249         /* need 2 more bytes from the stream */
250         CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
251
252         flags = bytestream_get_le16(&s->stream_ptr);
253         for (y = 0; y < 8; y += 2) {
254             for (x = 0; x < 8; x += 2, flags >>= 1) {
255                 s->pixel_ptr[x                ] =
256                 s->pixel_ptr[x + 1            ] =
257                 s->pixel_ptr[x +     s->stride] =
258                 s->pixel_ptr[x + 1 + s->stride] = P[flags & 1];
259             }
260             s->pixel_ptr += s->stride * 2;
261         }
262     }
263
264     /* report success */
265     return 0;
266 }
267
268 static int ipvideo_decode_block_opcode_0x8(IpvideoContext *s)
269 {
270     int x, y;
271     unsigned char P[2];
272     unsigned int flags = 0;
273
274     /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
275      * either top and bottom or left and right halves */
276     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
277
278     P[0] = *s->stream_ptr++;
279     P[1] = *s->stream_ptr++;
280
281     if (P[0] <= P[1]) {
282
283         CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 14);
284         s->stream_ptr -= 2;
285
286         for (y = 0; y < 16; y++) {
287             // new values for each 4x4 block
288             if (!(y & 3)) {
289                 P[0] = *s->stream_ptr++; P[1] = *s->stream_ptr++;
290                 flags = bytestream_get_le16(&s->stream_ptr);
291             }
292
293             for (x = 0; x < 4; x++, flags >>= 1)
294                 *s->pixel_ptr++ = P[flags & 1];
295             s->pixel_ptr += s->stride - 4;
296             // switch to right half
297             if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
298         }
299
300     } else {
301
302         /* need 10 more bytes */
303         CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 10);
304
305         if (s->stream_ptr[4] <= s->stream_ptr[5]) {
306
307             flags = bytestream_get_le32(&s->stream_ptr);
308
309             /* vertical split; left & right halves are 2-color encoded */
310
311             for (y = 0; y < 16; y++) {
312                 for (x = 0; x < 4; x++, flags >>= 1)
313                     *s->pixel_ptr++ = P[flags & 1];
314                 s->pixel_ptr += s->stride - 4;
315                 // switch to right half
316                 if (y == 7) {
317                     s->pixel_ptr -= 8 * s->stride - 4;
318                     P[0] = *s->stream_ptr++; P[1] = *s->stream_ptr++;
319                     flags = bytestream_get_le32(&s->stream_ptr);
320                 }
321             }
322
323         } else {
324
325             /* horizontal split; top & bottom halves are 2-color encoded */
326
327             for (y = 0; y < 8; y++) {
328                 if (y == 4) {
329                     P[0] = *s->stream_ptr++;
330                     P[1] = *s->stream_ptr++;
331                 }
332                 flags = *s->stream_ptr++ | 0x100;
333
334                 for (; flags != 1; flags >>= 1)
335                     *s->pixel_ptr++ = P[flags & 1];
336                 s->pixel_ptr += s->line_inc;
337             }
338         }
339     }
340
341     /* report success */
342     return 0;
343 }
344
345 static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s)
346 {
347     int x, y;
348     unsigned char P[4];
349
350     /* 4-color encoding */
351     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
352
353     memcpy(P, s->stream_ptr, 4);
354     s->stream_ptr += 4;
355
356     if (P[0] <= P[1]) {
357         if (P[2] <= P[3]) {
358
359             /* 1 of 4 colors for each pixel, need 16 more bytes */
360             CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 16);
361
362             for (y = 0; y < 8; y++) {
363                 /* get the next set of 8 2-bit flags */
364                 int flags = bytestream_get_le16(&s->stream_ptr);
365                 for (x = 0; x < 8; x++, flags >>= 2)
366                     *s->pixel_ptr++ = P[flags & 0x03];
367                 s->pixel_ptr += s->line_inc;
368             }
369
370         } else {
371             uint32_t flags;
372
373             /* 1 of 4 colors for each 2x2 block, need 4 more bytes */
374             CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
375
376             flags = bytestream_get_le32(&s->stream_ptr);
377
378             for (y = 0; y < 8; y += 2) {
379                 for (x = 0; x < 8; x += 2, flags >>= 2) {
380                     s->pixel_ptr[x                ] =
381                     s->pixel_ptr[x + 1            ] =
382                     s->pixel_ptr[x +     s->stride] =
383                     s->pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
384                 }
385                 s->pixel_ptr += s->stride * 2;
386             }
387
388         }
389     } else {
390         uint64_t flags;
391
392         /* 1 of 4 colors for each 2x1 or 1x2 block, need 8 more bytes */
393         CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
394
395         flags = bytestream_get_le64(&s->stream_ptr);
396         if (P[2] <= P[3]) {
397             for (y = 0; y < 8; y++) {
398                 for (x = 0; x < 8; x += 2, flags >>= 2) {
399                     s->pixel_ptr[x    ] =
400                     s->pixel_ptr[x + 1] = P[flags & 0x03];
401                 }
402                 s->pixel_ptr += s->stride;
403             }
404         } else {
405             for (y = 0; y < 8; y += 2) {
406                 for (x = 0; x < 8; x++, flags >>= 2) {
407                     s->pixel_ptr[x            ] =
408                     s->pixel_ptr[x + s->stride] = P[flags & 0x03];
409                 }
410                 s->pixel_ptr += s->stride * 2;
411             }
412         }
413     }
414
415     /* report success */
416     return 0;
417 }
418
419 static int ipvideo_decode_block_opcode_0xA(IpvideoContext *s)
420 {
421     int x, y;
422     unsigned char P[4];
423     int flags = 0;
424
425     /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
426      * either top and bottom or left and right halves */
427     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 24);
428
429     if (s->stream_ptr[0] <= s->stream_ptr[1]) {
430
431         /* 4-color encoding for each quadrant; need 32 bytes */
432         CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 32);
433
434         for (y = 0; y < 16; y++) {
435             // new values for each 4x4 block
436             if (!(y & 3)) {
437                 memcpy(P, s->stream_ptr, 4);
438                 s->stream_ptr += 4;
439                 flags = bytestream_get_le32(&s->stream_ptr);
440             }
441
442             for (x = 0; x < 4; x++, flags >>= 2)
443                 *s->pixel_ptr++ = P[flags & 0x03];
444
445             s->pixel_ptr += s->stride - 4;
446             // switch to right half
447             if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
448         }
449
450     } else {
451         // vertical split?
452         int vert = s->stream_ptr[12] <= s->stream_ptr[13];
453         uint64_t flags = 0;
454
455         /* 4-color encoding for either left and right or top and bottom
456          * halves */
457
458         for (y = 0; y < 16; y++) {
459             // load values for each half
460             if (!(y & 7)) {
461                 memcpy(P, s->stream_ptr, 4);
462                 s->stream_ptr += 4;
463                 flags = bytestream_get_le64(&s->stream_ptr);
464             }
465
466             for (x = 0; x < 4; x++, flags >>= 2)
467                 *s->pixel_ptr++ = P[flags & 0x03];
468
469             if (vert) {
470                 s->pixel_ptr += s->stride - 4;
471                 // switch to right half
472                 if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
473             } else if (y & 1) s->pixel_ptr += s->line_inc;
474         }
475     }
476
477     /* report success */
478     return 0;
479 }
480
481 static int ipvideo_decode_block_opcode_0xB(IpvideoContext *s)
482 {
483     int y;
484
485     /* 64-color encoding (each pixel in block is a different color) */
486     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 64);
487
488     for (y = 0; y < 8; y++) {
489         memcpy(s->pixel_ptr, s->stream_ptr, 8);
490         s->stream_ptr += 8;
491         s->pixel_ptr  += s->stride;
492     }
493
494     /* report success */
495     return 0;
496 }
497
498 static int ipvideo_decode_block_opcode_0xC(IpvideoContext *s)
499 {
500     int x, y;
501
502     /* 16-color block encoding: each 2x2 block is a different color */
503     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 16);
504
505     for (y = 0; y < 8; y += 2) {
506         for (x = 0; x < 8; x += 2) {
507             s->pixel_ptr[x                ] =
508             s->pixel_ptr[x + 1            ] =
509             s->pixel_ptr[x +     s->stride] =
510             s->pixel_ptr[x + 1 + s->stride] = *s->stream_ptr++;
511         }
512         s->pixel_ptr += s->stride * 2;
513     }
514
515     /* report success */
516     return 0;
517 }
518
519 static int ipvideo_decode_block_opcode_0xD(IpvideoContext *s)
520 {
521     int y;
522     unsigned char P[2];
523
524     /* 4-color block encoding: each 4x4 block is a different color */
525     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
526
527     for (y = 0; y < 8; y++) {
528         if (!(y & 3)) {
529             P[0] = *s->stream_ptr++;
530             P[1] = *s->stream_ptr++;
531         }
532         memset(s->pixel_ptr,     P[0], 4);
533         memset(s->pixel_ptr + 4, P[1], 4);
534         s->pixel_ptr += s->stride;
535     }
536
537     /* report success */
538     return 0;
539 }
540
541 static int ipvideo_decode_block_opcode_0xE(IpvideoContext *s)
542 {
543     int y;
544     unsigned char pix;
545
546     /* 1-color encoding: the whole block is 1 solid color */
547     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
548     pix = *s->stream_ptr++;
549
550     for (y = 0; y < 8; y++) {
551         memset(s->pixel_ptr, pix, 8);
552         s->pixel_ptr += s->stride;
553     }
554
555     /* report success */
556     return 0;
557 }
558
559 static int ipvideo_decode_block_opcode_0xF(IpvideoContext *s)
560 {
561     int x, y;
562     unsigned char sample[2];
563
564     /* dithered encoding */
565     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
566     sample[0] = *s->stream_ptr++;
567     sample[1] = *s->stream_ptr++;
568
569     for (y = 0; y < 8; y++) {
570         for (x = 0; x < 8; x += 2) {
571             *s->pixel_ptr++ = sample[  y & 1 ];
572             *s->pixel_ptr++ = sample[!(y & 1)];
573         }
574         s->pixel_ptr += s->line_inc;
575     }
576
577     /* report success */
578     return 0;
579 }
580
581 static int ipvideo_decode_block_opcode_0x6_16(IpvideoContext *s)
582 {
583     signed char x, y;
584
585     /* copy a block from the second last frame using an expanded range */
586     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
587
588     x = *s->stream_ptr++;
589     y = *s->stream_ptr++;
590
591     debug_interplay ("    motion bytes = %d, %d\n", x, y);
592     return copy_from(s, &s->second_last_frame, x, y);
593 }
594
595 static int ipvideo_decode_block_opcode_0x7_16(IpvideoContext *s)
596 {
597     int x, y;
598     uint16_t P[2];
599     unsigned int flags;
600     uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
601
602     /* 2-color encoding */
603     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
604
605     P[0] = bytestream_get_le16(&s->stream_ptr);
606     P[1] = bytestream_get_le16(&s->stream_ptr);
607
608     if (!(P[0] & 0x8000)) {
609
610         CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
611
612         for (y = 0; y < 8; y++) {
613             flags = *s->stream_ptr++ | 0x100;
614             for (; flags != 1; flags >>= 1)
615                 *pixel_ptr++ = P[flags & 1];
616             pixel_ptr += s->line_inc;
617         }
618
619     } else {
620
621         CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
622
623         flags = bytestream_get_le16(&s->stream_ptr);
624         for (y = 0; y < 8; y += 2) {
625             for (x = 0; x < 8; x += 2, flags >>= 1) {
626                 pixel_ptr[x                ] =
627                 pixel_ptr[x + 1            ] =
628                 pixel_ptr[x +     s->stride] =
629                 pixel_ptr[x + 1 + s->stride] = P[flags & 1];
630             }
631             pixel_ptr += s->stride * 2;
632         }
633     }
634
635     return 0;
636 }
637
638 static int ipvideo_decode_block_opcode_0x8_16(IpvideoContext *s)
639 {
640     int x, y;
641     uint16_t P[2];
642     unsigned int flags = 0;
643     uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
644
645     /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
646      * either top and bottom or left and right halves */
647     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
648
649     P[0] = bytestream_get_le16(&s->stream_ptr);
650     P[1] = bytestream_get_le16(&s->stream_ptr);
651
652     if (!(P[0] & 0x8000)) {
653
654         CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 24);
655         s->stream_ptr -= 4;
656
657         for (y = 0; y < 16; y++) {
658             // new values for each 4x4 block
659             if (!(y & 3)) {
660                 P[0] = bytestream_get_le16(&s->stream_ptr);
661                 P[1] = bytestream_get_le16(&s->stream_ptr);
662                 flags = bytestream_get_le16(&s->stream_ptr);
663             }
664
665             for (x = 0; x < 4; x++, flags >>= 1)
666                 *pixel_ptr++ = P[flags & 1];
667             pixel_ptr += s->stride - 4;
668             // switch to right half
669             if (y == 7) pixel_ptr -= 8 * s->stride - 4;
670         }
671
672     } else {
673
674         CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 12);
675
676         if (!(AV_RL16(s->stream_ptr + 4) & 0x8000)) {
677
678             flags = bytestream_get_le32(&s->stream_ptr);
679
680             /* vertical split; left & right halves are 2-color encoded */
681
682             for (y = 0; y < 16; y++) {
683                 for (x = 0; x < 4; x++, flags >>= 1)
684                     *pixel_ptr++ = P[flags & 1];
685                 pixel_ptr += s->stride - 4;
686                 // switch to right half
687                 if (y == 7) {
688                     pixel_ptr -= 8 * s->stride - 4;
689                     P[0] = bytestream_get_le16(&s->stream_ptr);
690                     P[1] = bytestream_get_le16(&s->stream_ptr);
691                     flags = bytestream_get_le32(&s->stream_ptr);
692                 }
693             }
694
695         } else {
696
697             /* horizontal split; top & bottom halves are 2-color encoded */
698
699             for (y = 0; y < 8; y++) {
700                 if (y == 4) {
701                     P[0] = bytestream_get_le16(&s->stream_ptr);
702                     P[1] = bytestream_get_le16(&s->stream_ptr);
703                 }
704                 flags = *s->stream_ptr++ | 0x100;
705
706                 for (; flags != 1; flags >>= 1)
707                     *pixel_ptr++ = P[flags & 1];
708                 pixel_ptr += s->line_inc;
709             }
710         }
711     }
712
713     /* report success */
714     return 0;
715 }
716
717 static int ipvideo_decode_block_opcode_0x9_16(IpvideoContext *s)
718 {
719     int x, y;
720     uint16_t P[4];
721     uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
722
723     /* 4-color encoding */
724     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
725
726     for (x = 0; x < 4; x++)
727         P[x] = bytestream_get_le16(&s->stream_ptr);
728
729     if (!(P[0] & 0x8000)) {
730         if (!(P[2] & 0x8000)) {
731
732             /* 1 of 4 colors for each pixel */
733             CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 16);
734
735             for (y = 0; y < 8; y++) {
736                 /* get the next set of 8 2-bit flags */
737                 int flags = bytestream_get_le16(&s->stream_ptr);
738                 for (x = 0; x < 8; x++, flags >>= 2)
739                     *pixel_ptr++ = P[flags & 0x03];
740                 pixel_ptr += s->line_inc;
741             }
742
743         } else {
744             uint32_t flags;
745
746             /* 1 of 4 colors for each 2x2 block */
747             CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
748
749             flags = bytestream_get_le32(&s->stream_ptr);
750
751             for (y = 0; y < 8; y += 2) {
752                 for (x = 0; x < 8; x += 2, flags >>= 2) {
753                     pixel_ptr[x                ] =
754                     pixel_ptr[x + 1            ] =
755                     pixel_ptr[x +     s->stride] =
756                     pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
757                 }
758                 pixel_ptr += s->stride * 2;
759             }
760
761         }
762     } else {
763         uint64_t flags;
764
765         /* 1 of 4 colors for each 2x1 or 1x2 block */
766         CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
767
768         flags = bytestream_get_le64(&s->stream_ptr);
769         if (!(P[2] & 0x8000)) {
770             for (y = 0; y < 8; y++) {
771                 for (x = 0; x < 8; x += 2, flags >>= 2) {
772                     pixel_ptr[x    ] =
773                     pixel_ptr[x + 1] = P[flags & 0x03];
774                 }
775                 pixel_ptr += s->stride;
776             }
777         } else {
778             for (y = 0; y < 8; y += 2) {
779                 for (x = 0; x < 8; x++, flags >>= 2) {
780                     pixel_ptr[x            ] =
781                     pixel_ptr[x + s->stride] = P[flags & 0x03];
782                 }
783                 pixel_ptr += s->stride * 2;
784             }
785         }
786     }
787
788     /* report success */
789     return 0;
790 }
791
792 static int ipvideo_decode_block_opcode_0xA_16(IpvideoContext *s)
793 {
794     int x, y;
795     uint16_t P[4];
796     int flags = 0;
797     uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
798
799     /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
800      * either top and bottom or left and right halves */
801     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 24);
802
803     if (!(AV_RL16(s->stream_ptr) & 0x8000)) {
804
805         /* 4-color encoding for each quadrant */
806         CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 48);
807
808         for (y = 0; y < 16; y++) {
809             // new values for each 4x4 block
810             if (!(y & 3)) {
811                 for (x = 0; x < 4; x++)
812                     P[x] = bytestream_get_le16(&s->stream_ptr);
813                 flags = bytestream_get_le32(&s->stream_ptr);
814             }
815
816             for (x = 0; x < 4; x++, flags >>= 2)
817                 *pixel_ptr++ = P[flags & 0x03];
818
819             pixel_ptr += s->stride - 4;
820             // switch to right half
821             if (y == 7) pixel_ptr -= 8 * s->stride - 4;
822         }
823
824     } else {
825         // vertical split?
826         int vert = !(AV_RL16(s->stream_ptr + 16) & 0x8000);
827         uint64_t flags = 0;
828
829         /* 4-color encoding for either left and right or top and bottom
830          * halves */
831
832         for (y = 0; y < 16; y++) {
833             // load values for each half
834             if (!(y & 7)) {
835                 for (x = 0; x < 4; x++)
836                     P[x] = bytestream_get_le16(&s->stream_ptr);
837                 flags = bytestream_get_le64(&s->stream_ptr);
838             }
839
840             for (x = 0; x < 4; x++, flags >>= 2)
841                 *pixel_ptr++ = P[flags & 0x03];
842
843             if (vert) {
844                 pixel_ptr += s->stride - 4;
845                 // switch to right half
846                 if (y == 7) pixel_ptr -= 8 * s->stride - 4;
847             } else if (y & 1) pixel_ptr += s->line_inc;
848         }
849     }
850
851     /* report success */
852     return 0;
853 }
854
855 static int ipvideo_decode_block_opcode_0xB_16(IpvideoContext *s)
856 {
857     int x, y;
858     uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
859
860     /* 64-color encoding (each pixel in block is a different color) */
861     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 128);
862
863     for (y = 0; y < 8; y++) {
864         for (x = 0; x < 8; x++)
865             pixel_ptr[x] = bytestream_get_le16(&s->stream_ptr);
866         pixel_ptr  += s->stride;
867     }
868
869     /* report success */
870     return 0;
871 }
872
873 static int ipvideo_decode_block_opcode_0xC_16(IpvideoContext *s)
874 {
875     int x, y;
876     uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
877
878     /* 16-color block encoding: each 2x2 block is a different color */
879     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 32);
880
881     for (y = 0; y < 8; y += 2) {
882         for (x = 0; x < 8; x += 2) {
883             pixel_ptr[x                ] =
884             pixel_ptr[x + 1            ] =
885             pixel_ptr[x +     s->stride] =
886             pixel_ptr[x + 1 + s->stride] = bytestream_get_le16(&s->stream_ptr);
887         }
888         pixel_ptr += s->stride * 2;
889     }
890
891     /* report success */
892     return 0;
893 }
894
895 static int ipvideo_decode_block_opcode_0xD_16(IpvideoContext *s)
896 {
897     int x, y;
898     uint16_t P[2];
899     uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
900
901     /* 4-color block encoding: each 4x4 block is a different color */
902     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
903
904     for (y = 0; y < 8; y++) {
905         if (!(y & 3)) {
906             P[0] = bytestream_get_le16(&s->stream_ptr);
907             P[1] = bytestream_get_le16(&s->stream_ptr);
908         }
909         for (x = 0; x < 8; x++)
910             pixel_ptr[x] = P[x >> 2];
911         pixel_ptr += s->stride;
912     }
913
914     /* report success */
915     return 0;
916 }
917
918 static int ipvideo_decode_block_opcode_0xE_16(IpvideoContext *s)
919 {
920     int x, y;
921     uint16_t pix;
922     uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
923
924     /* 1-color encoding: the whole block is 1 solid color */
925     CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
926     pix = bytestream_get_le16(&s->stream_ptr);
927
928     for (y = 0; y < 8; y++) {
929         for (x = 0; x < 8; x++)
930             pixel_ptr[x] = pix;
931         pixel_ptr += s->stride;
932     }
933
934     /* report success */
935     return 0;
936 }
937
938 static int (* const ipvideo_decode_block[])(IpvideoContext *s) = {
939     ipvideo_decode_block_opcode_0x0, ipvideo_decode_block_opcode_0x1,
940     ipvideo_decode_block_opcode_0x2, ipvideo_decode_block_opcode_0x3,
941     ipvideo_decode_block_opcode_0x4, ipvideo_decode_block_opcode_0x5,
942     ipvideo_decode_block_opcode_0x6, ipvideo_decode_block_opcode_0x7,
943     ipvideo_decode_block_opcode_0x8, ipvideo_decode_block_opcode_0x9,
944     ipvideo_decode_block_opcode_0xA, ipvideo_decode_block_opcode_0xB,
945     ipvideo_decode_block_opcode_0xC, ipvideo_decode_block_opcode_0xD,
946     ipvideo_decode_block_opcode_0xE, ipvideo_decode_block_opcode_0xF,
947 };
948
949 static int (* const ipvideo_decode_block16[])(IpvideoContext *s) = {
950     ipvideo_decode_block_opcode_0x0,    ipvideo_decode_block_opcode_0x1,
951     ipvideo_decode_block_opcode_0x2,    ipvideo_decode_block_opcode_0x3,
952     ipvideo_decode_block_opcode_0x4,    ipvideo_decode_block_opcode_0x5,
953     ipvideo_decode_block_opcode_0x6_16, ipvideo_decode_block_opcode_0x7_16,
954     ipvideo_decode_block_opcode_0x8_16, ipvideo_decode_block_opcode_0x9_16,
955     ipvideo_decode_block_opcode_0xA_16, ipvideo_decode_block_opcode_0xB_16,
956     ipvideo_decode_block_opcode_0xC_16, ipvideo_decode_block_opcode_0xD_16,
957     ipvideo_decode_block_opcode_0xE_16, ipvideo_decode_block_opcode_0x1,
958 };
959
960 static void ipvideo_decode_opcodes(IpvideoContext *s)
961 {
962     int x, y;
963     unsigned char opcode;
964     int ret;
965     static int frame = 0;
966     GetBitContext gb;
967
968     debug_interplay("------------------ frame %d\n", frame);
969     frame++;
970
971     if (!s->is_16bpp) {
972         /* this is PAL8, so make the palette available */
973         memcpy(s->current_frame.data[1], s->pal, AVPALETTE_SIZE);
974
975         s->stride = s->current_frame.linesize[0];
976         s->stream_ptr = s->buf + 14;  /* data starts 14 bytes in */
977         s->stream_end = s->buf + s->size;
978     } else {
979         s->stride = s->current_frame.linesize[0] >> 1;
980         s->stream_ptr = s->buf + 16;
981         s->stream_end =
982         s->mv_ptr = s->buf + 14 + AV_RL16(s->buf+14);
983         s->mv_end = s->buf + s->size;
984     }
985     s->line_inc = s->stride - 8;
986     s->upper_motion_limit_offset = (s->avctx->height - 8) * s->current_frame.linesize[0]
987                                   + (s->avctx->width - 8) * (1 + s->is_16bpp);
988
989     init_get_bits(&gb, s->decoding_map, s->decoding_map_size * 8);
990     for (y = 0; y < s->avctx->height; y += 8) {
991         for (x = 0; x < s->avctx->width; x += 8) {
992             opcode = get_bits(&gb, 4);
993
994             debug_interplay("  block @ (%3d, %3d): encoding 0x%X, data ptr @ %p\n",
995                             x, y, opcode, s->stream_ptr);
996
997             if (!s->is_16bpp) {
998                 s->pixel_ptr = s->current_frame.data[0] + x
999                               + y*s->current_frame.linesize[0];
1000                 ret = ipvideo_decode_block[opcode](s);
1001             } else {
1002                 s->pixel_ptr = s->current_frame.data[0] + x*2
1003                               + y*s->current_frame.linesize[0];
1004                 ret = ipvideo_decode_block16[opcode](s);
1005             }
1006             if (ret != 0) {
1007                 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode problem on frame %d, @ block (%d, %d)\n",
1008                        frame, x, y);
1009                 return;
1010             }
1011         }
1012     }
1013     if (s->stream_end - s->stream_ptr > 1) {
1014         av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode finished with %td bytes left over\n",
1015                s->stream_end - s->stream_ptr);
1016     }
1017 }
1018
1019 static av_cold int ipvideo_decode_init(AVCodecContext *avctx)
1020 {
1021     IpvideoContext *s = avctx->priv_data;
1022
1023     s->avctx = avctx;
1024
1025     s->is_16bpp = avctx->bits_per_coded_sample == 16;
1026     avctx->pix_fmt = s->is_16bpp ? PIX_FMT_RGB555 : PIX_FMT_PAL8;
1027
1028     dsputil_init(&s->dsp, avctx);
1029
1030     /* decoding map contains 4 bits of information per 8x8 block */
1031     s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2);
1032
1033     s->current_frame.data[0] = s->last_frame.data[0] =
1034     s->second_last_frame.data[0] = NULL;
1035
1036     return 0;
1037 }
1038
1039 static int ipvideo_decode_frame(AVCodecContext *avctx,
1040                                 void *data, int *data_size,
1041                                 AVPacket *avpkt)
1042 {
1043     const uint8_t *buf = avpkt->data;
1044     int buf_size = avpkt->size;
1045     IpvideoContext *s = avctx->priv_data;
1046
1047     /* compressed buffer needs to be large enough to at least hold an entire
1048      * decoding map */
1049     if (buf_size < s->decoding_map_size)
1050         return buf_size;
1051
1052     s->decoding_map = buf;
1053     s->buf = buf + s->decoding_map_size;
1054     s->size = buf_size - s->decoding_map_size;
1055
1056     s->current_frame.reference = 3;
1057     if (avctx->get_buffer(avctx, &s->current_frame)) {
1058         av_log(avctx, AV_LOG_ERROR, "  Interplay Video: get_buffer() failed\n");
1059         return -1;
1060     }
1061
1062     if (!s->is_16bpp) {
1063         const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
1064         if (pal) {
1065             s->current_frame.palette_has_changed = 1;
1066             memcpy(s->pal, pal, AVPALETTE_SIZE);
1067         }
1068     }
1069
1070     ipvideo_decode_opcodes(s);
1071
1072     *data_size = sizeof(AVFrame);
1073     *(AVFrame*)data = s->current_frame;
1074
1075     /* shuffle frames */
1076     if (s->second_last_frame.data[0])
1077         avctx->release_buffer(avctx, &s->second_last_frame);
1078     s->second_last_frame = s->last_frame;
1079     s->last_frame = s->current_frame;
1080     s->current_frame.data[0] = NULL;  /* catch any access attempts */
1081
1082     /* report that the buffer was completely consumed */
1083     return buf_size;
1084 }
1085
1086 static av_cold int ipvideo_decode_end(AVCodecContext *avctx)
1087 {
1088     IpvideoContext *s = avctx->priv_data;
1089
1090     /* release the last frame */
1091     if (s->last_frame.data[0])
1092         avctx->release_buffer(avctx, &s->last_frame);
1093     if (s->second_last_frame.data[0])
1094         avctx->release_buffer(avctx, &s->second_last_frame);
1095
1096     return 0;
1097 }
1098
1099 AVCodec ff_interplay_video_decoder = {
1100     "interplayvideo",
1101     AVMEDIA_TYPE_VIDEO,
1102     CODEC_ID_INTERPLAY_VIDEO,
1103     sizeof(IpvideoContext),
1104     ipvideo_decode_init,
1105     NULL,
1106     ipvideo_decode_end,
1107     ipvideo_decode_frame,
1108     CODEC_CAP_DR1,
1109     .long_name = NULL_IF_CONFIG_SMALL("Interplay MVE video"),
1110 };