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