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