2 * Interplay MVE Video Decoder
3 * Copyright (C) 2003 the ffmpeg project
5 * This file is part of FFmpeg.
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.
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.
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
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.
30 * This decoder presently only supports a PAL8 output colorspace.
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.
42 #include "bytestream.h"
44 #define ALT_BITSTREAM_READER_LE
47 #define PALETTE_COUNT 256
49 /* debugging support */
50 #define DEBUG_INTERPLAY 0
52 #define debug_interplay(x,...) av_log(NULL, AV_LOG_DEBUG, x, __VA_ARGS__)
54 static inline void debug_interplay(const char *format, ...) { }
57 typedef struct IpvideoContext {
59 AVCodecContext *avctx;
61 AVFrame second_last_frame;
63 AVFrame current_frame;
64 const unsigned char *decoding_map;
65 int decoding_map_size;
67 const unsigned char *buf;
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;
78 int upper_motion_limit_offset;
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); \
90 static int copy_from(IpvideoContext *s, AVFrame *src, int delta_x, int delta_y)
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);
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);
103 if (src->data[0] == NULL) {
104 av_log(s->avctx, AV_LOG_ERROR, "Invalid decode type, corrupted header?\n");
105 return AVERROR(EINVAL);
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);
112 static int ipvideo_decode_block_opcode_0x0(IpvideoContext *s)
114 return copy_from(s, &s->last_frame, 0, 0);
117 static int ipvideo_decode_block_opcode_0x1(IpvideoContext *s)
119 return copy_from(s, &s->second_last_frame, 0, 0);
122 static int ipvideo_decode_block_opcode_0x2(IpvideoContext *s)
127 /* copy block from 2 frames ago using a motion vector; need 1 more byte */
129 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
130 B = *s->stream_ptr++;
132 CHECK_STREAM_PTR(s->mv_ptr, s->mv_end, 1);
140 x = -14 + ((B - 56) % 29);
141 y = 8 + ((B - 56) / 29);
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);
148 static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s)
153 /* copy 8x8 block from current frame from an up/left block */
155 /* need 1 more byte for motion */
157 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
158 B = *s->stream_ptr++;
160 CHECK_STREAM_PTR(s->mv_ptr, s->mv_end, 1);
168 x = -(-14 + ((B - 56) % 29));
169 y = -( 8 + ((B - 56) / 29));
172 debug_interplay (" motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
173 return copy_from(s, &s->current_frame, x, y);
176 static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s)
179 unsigned char B, BL, BH;
181 /* copy a block from the previous frame; need 1 more byte */
183 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
184 B = *s->stream_ptr++;
186 CHECK_STREAM_PTR(s->mv_ptr, s->mv_end, 1);
191 BH = (B >> 4) & 0x0F;
195 debug_interplay (" motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
196 return copy_from(s, &s->last_frame, x, y);
199 static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s)
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);
207 x = *s->stream_ptr++;
208 y = *s->stream_ptr++;
210 debug_interplay (" motion bytes = %d, %d\n", x, y);
211 return copy_from(s, &s->last_frame, x, y);
214 static int ipvideo_decode_block_opcode_0x6(IpvideoContext *s)
216 /* mystery opcode? skip multiple blocks? */
217 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: Help! Mystery opcode 0x6 seen\n");
223 static int ipvideo_decode_block_opcode_0x7(IpvideoContext *s)
229 /* 2-color encoding */
230 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
232 P[0] = *s->stream_ptr++;
233 P[1] = *s->stream_ptr++;
237 /* need 8 more bytes from the stream */
238 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
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;
249 /* need 2 more bytes from the stream */
250 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
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) {
256 s->pixel_ptr[x + 1 ] =
257 s->pixel_ptr[x + s->stride] =
258 s->pixel_ptr[x + 1 + s->stride] = P[flags & 1];
260 s->pixel_ptr += s->stride * 2;
268 static int ipvideo_decode_block_opcode_0x8(IpvideoContext *s)
272 unsigned int flags = 0;
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);
278 P[0] = *s->stream_ptr++;
279 P[1] = *s->stream_ptr++;
283 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 14);
286 for (y = 0; y < 16; y++) {
287 // new values for each 4x4 block
289 P[0] = *s->stream_ptr++; P[1] = *s->stream_ptr++;
290 flags = bytestream_get_le16(&s->stream_ptr);
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;
302 /* need 10 more bytes */
303 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 10);
305 if (s->stream_ptr[4] <= s->stream_ptr[5]) {
307 flags = bytestream_get_le32(&s->stream_ptr);
309 /* vertical split; left & right halves are 2-color encoded */
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
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);
325 /* horizontal split; top & bottom halves are 2-color encoded */
327 for (y = 0; y < 8; y++) {
329 P[0] = *s->stream_ptr++;
330 P[1] = *s->stream_ptr++;
332 flags = *s->stream_ptr++ | 0x100;
334 for (; flags != 1; flags >>= 1)
335 *s->pixel_ptr++ = P[flags & 1];
336 s->pixel_ptr += s->line_inc;
345 static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s)
350 /* 4-color encoding */
351 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
353 memcpy(P, s->stream_ptr, 4);
359 /* 1 of 4 colors for each pixel, need 16 more bytes */
360 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 16);
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;
373 /* 1 of 4 colors for each 2x2 block, need 4 more bytes */
374 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
376 flags = bytestream_get_le32(&s->stream_ptr);
378 for (y = 0; y < 8; y += 2) {
379 for (x = 0; x < 8; x += 2, flags >>= 2) {
381 s->pixel_ptr[x + 1 ] =
382 s->pixel_ptr[x + s->stride] =
383 s->pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
385 s->pixel_ptr += s->stride * 2;
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);
395 flags = bytestream_get_le64(&s->stream_ptr);
397 for (y = 0; y < 8; y++) {
398 for (x = 0; x < 8; x += 2, flags >>= 2) {
400 s->pixel_ptr[x + 1] = P[flags & 0x03];
402 s->pixel_ptr += s->stride;
405 for (y = 0; y < 8; y += 2) {
406 for (x = 0; x < 8; x++, flags >>= 2) {
408 s->pixel_ptr[x + s->stride] = P[flags & 0x03];
410 s->pixel_ptr += s->stride * 2;
419 static int ipvideo_decode_block_opcode_0xA(IpvideoContext *s)
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);
429 if (s->stream_ptr[0] <= s->stream_ptr[1]) {
431 /* 4-color encoding for each quadrant; need 32 bytes */
432 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 32);
434 for (y = 0; y < 16; y++) {
435 // new values for each 4x4 block
437 memcpy(P, s->stream_ptr, 4);
439 flags = bytestream_get_le32(&s->stream_ptr);
442 for (x = 0; x < 4; x++, flags >>= 2)
443 *s->pixel_ptr++ = P[flags & 0x03];
445 s->pixel_ptr += s->stride - 4;
446 // switch to right half
447 if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
452 int vert = s->stream_ptr[12] <= s->stream_ptr[13];
455 /* 4-color encoding for either left and right or top and bottom
458 for (y = 0; y < 16; y++) {
459 // load values for each half
461 memcpy(P, s->stream_ptr, 4);
463 flags = bytestream_get_le64(&s->stream_ptr);
466 for (x = 0; x < 4; x++, flags >>= 2)
467 *s->pixel_ptr++ = P[flags & 0x03];
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;
481 static int ipvideo_decode_block_opcode_0xB(IpvideoContext *s)
485 /* 64-color encoding (each pixel in block is a different color) */
486 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 64);
488 for (y = 0; y < 8; y++) {
489 memcpy(s->pixel_ptr, s->stream_ptr, 8);
491 s->pixel_ptr += s->stride;
498 static int ipvideo_decode_block_opcode_0xC(IpvideoContext *s)
502 /* 16-color block encoding: each 2x2 block is a different color */
503 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 16);
505 for (y = 0; y < 8; y += 2) {
506 for (x = 0; x < 8; x += 2) {
508 s->pixel_ptr[x + 1 ] =
509 s->pixel_ptr[x + s->stride] =
510 s->pixel_ptr[x + 1 + s->stride] = *s->stream_ptr++;
512 s->pixel_ptr += s->stride * 2;
519 static int ipvideo_decode_block_opcode_0xD(IpvideoContext *s)
524 /* 4-color block encoding: each 4x4 block is a different color */
525 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
527 for (y = 0; y < 8; y++) {
529 P[0] = *s->stream_ptr++;
530 P[1] = *s->stream_ptr++;
532 memset(s->pixel_ptr, P[0], 4);
533 memset(s->pixel_ptr + 4, P[1], 4);
534 s->pixel_ptr += s->stride;
541 static int ipvideo_decode_block_opcode_0xE(IpvideoContext *s)
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++;
550 for (y = 0; y < 8; y++) {
551 memset(s->pixel_ptr, pix, 8);
552 s->pixel_ptr += s->stride;
559 static int ipvideo_decode_block_opcode_0xF(IpvideoContext *s)
562 unsigned char sample[2];
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++;
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)];
574 s->pixel_ptr += s->line_inc;
581 static int ipvideo_decode_block_opcode_0x6_16(IpvideoContext *s)
585 /* copy a block from the second last frame using an expanded range */
586 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
588 x = *s->stream_ptr++;
589 y = *s->stream_ptr++;
591 debug_interplay (" motion bytes = %d, %d\n", x, y);
592 return copy_from(s, &s->second_last_frame, x, y);
595 static int ipvideo_decode_block_opcode_0x7_16(IpvideoContext *s)
600 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
602 /* 2-color encoding */
603 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
605 P[0] = bytestream_get_le16(&s->stream_ptr);
606 P[1] = bytestream_get_le16(&s->stream_ptr);
608 if (!(P[0] & 0x8000)) {
610 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
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;
621 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
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) {
628 pixel_ptr[x + s->stride] =
629 pixel_ptr[x + 1 + s->stride] = P[flags & 1];
631 pixel_ptr += s->stride * 2;
638 static int ipvideo_decode_block_opcode_0x8_16(IpvideoContext *s)
642 unsigned int flags = 0;
643 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
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);
649 P[0] = bytestream_get_le16(&s->stream_ptr);
650 P[1] = bytestream_get_le16(&s->stream_ptr);
652 if (!(P[0] & 0x8000)) {
654 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 24);
657 for (y = 0; y < 16; y++) {
658 // new values for each 4x4 block
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);
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;
674 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 12);
676 if (!(AV_RL16(s->stream_ptr + 4) & 0x8000)) {
678 flags = bytestream_get_le32(&s->stream_ptr);
680 /* vertical split; left & right halves are 2-color encoded */
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
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);
697 /* horizontal split; top & bottom halves are 2-color encoded */
699 for (y = 0; y < 8; y++) {
701 P[0] = bytestream_get_le16(&s->stream_ptr);
702 P[1] = bytestream_get_le16(&s->stream_ptr);
704 flags = *s->stream_ptr++ | 0x100;
706 for (; flags != 1; flags >>= 1)
707 *pixel_ptr++ = P[flags & 1];
708 pixel_ptr += s->line_inc;
717 static int ipvideo_decode_block_opcode_0x9_16(IpvideoContext *s)
721 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
723 /* 4-color encoding */
724 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
726 for (x = 0; x < 4; x++)
727 P[x] = bytestream_get_le16(&s->stream_ptr);
729 if (!(P[0] & 0x8000)) {
730 if (!(P[2] & 0x8000)) {
732 /* 1 of 4 colors for each pixel */
733 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 16);
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;
746 /* 1 of 4 colors for each 2x2 block */
747 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
749 flags = bytestream_get_le32(&s->stream_ptr);
751 for (y = 0; y < 8; y += 2) {
752 for (x = 0; x < 8; x += 2, flags >>= 2) {
755 pixel_ptr[x + s->stride] =
756 pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
758 pixel_ptr += s->stride * 2;
765 /* 1 of 4 colors for each 2x1 or 1x2 block */
766 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
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) {
773 pixel_ptr[x + 1] = P[flags & 0x03];
775 pixel_ptr += s->stride;
778 for (y = 0; y < 8; y += 2) {
779 for (x = 0; x < 8; x++, flags >>= 2) {
781 pixel_ptr[x + s->stride] = P[flags & 0x03];
783 pixel_ptr += s->stride * 2;
792 static int ipvideo_decode_block_opcode_0xA_16(IpvideoContext *s)
797 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
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);
803 if (!(AV_RL16(s->stream_ptr) & 0x8000)) {
805 /* 4-color encoding for each quadrant */
806 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 48);
808 for (y = 0; y < 16; y++) {
809 // new values for each 4x4 block
811 for (x = 0; x < 4; x++)
812 P[x] = bytestream_get_le16(&s->stream_ptr);
813 flags = bytestream_get_le32(&s->stream_ptr);
816 for (x = 0; x < 4; x++, flags >>= 2)
817 *pixel_ptr++ = P[flags & 0x03];
819 pixel_ptr += s->stride - 4;
820 // switch to right half
821 if (y == 7) pixel_ptr -= 8 * s->stride - 4;
826 int vert = !(AV_RL16(s->stream_ptr + 16) & 0x8000);
829 /* 4-color encoding for either left and right or top and bottom
832 for (y = 0; y < 16; y++) {
833 // load values for each half
835 for (x = 0; x < 4; x++)
836 P[x] = bytestream_get_le16(&s->stream_ptr);
837 flags = bytestream_get_le64(&s->stream_ptr);
840 for (x = 0; x < 4; x++, flags >>= 2)
841 *pixel_ptr++ = P[flags & 0x03];
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;
855 static int ipvideo_decode_block_opcode_0xB_16(IpvideoContext *s)
858 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
860 /* 64-color encoding (each pixel in block is a different color) */
861 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 128);
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;
873 static int ipvideo_decode_block_opcode_0xC_16(IpvideoContext *s)
876 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
878 /* 16-color block encoding: each 2x2 block is a different color */
879 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 32);
881 for (y = 0; y < 8; y += 2) {
882 for (x = 0; x < 8; x += 2) {
885 pixel_ptr[x + s->stride] =
886 pixel_ptr[x + 1 + s->stride] = bytestream_get_le16(&s->stream_ptr);
888 pixel_ptr += s->stride * 2;
895 static int ipvideo_decode_block_opcode_0xD_16(IpvideoContext *s)
899 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
901 /* 4-color block encoding: each 4x4 block is a different color */
902 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
904 for (y = 0; y < 8; y++) {
906 P[0] = bytestream_get_le16(&s->stream_ptr);
907 P[1] = bytestream_get_le16(&s->stream_ptr);
909 for (x = 0; x < 8; x++)
910 pixel_ptr[x] = P[x >> 2];
911 pixel_ptr += s->stride;
918 static int ipvideo_decode_block_opcode_0xE_16(IpvideoContext *s)
922 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
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);
928 for (y = 0; y < 8; y++) {
929 for (x = 0; x < 8; x++)
931 pixel_ptr += s->stride;
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,
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,
960 static void ipvideo_decode_opcodes(IpvideoContext *s)
963 unsigned char opcode;
965 static int frame = 0;
968 debug_interplay("------------------ frame %d\n", frame);
972 /* this is PAL8, so make the palette available */
973 memcpy(s->current_frame.data[1], s->pal, AVPALETTE_SIZE);
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;
979 s->stride = s->current_frame.linesize[0] >> 1;
980 s->stream_ptr = s->buf + 16;
982 s->mv_ptr = s->buf + 14 + AV_RL16(s->buf+14);
983 s->mv_end = s->buf + s->size;
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);
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);
994 debug_interplay(" block @ (%3d, %3d): encoding 0x%X, data ptr @ %p\n",
995 x, y, opcode, s->stream_ptr);
998 s->pixel_ptr = s->current_frame.data[0] + x
999 + y*s->current_frame.linesize[0];
1000 ret = ipvideo_decode_block[opcode](s);
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);
1007 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode problem on frame %d, @ block (%d, %d)\n",
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);
1019 static av_cold int ipvideo_decode_init(AVCodecContext *avctx)
1021 IpvideoContext *s = avctx->priv_data;
1025 s->is_16bpp = avctx->bits_per_coded_sample == 16;
1026 avctx->pix_fmt = s->is_16bpp ? PIX_FMT_RGB555 : PIX_FMT_PAL8;
1028 dsputil_init(&s->dsp, avctx);
1030 /* decoding map contains 4 bits of information per 8x8 block */
1031 s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2);
1033 avcodec_get_frame_defaults(&s->second_last_frame);
1034 avcodec_get_frame_defaults(&s->last_frame);
1035 avcodec_get_frame_defaults(&s->current_frame);
1036 s->current_frame.data[0] = s->last_frame.data[0] =
1037 s->second_last_frame.data[0] = NULL;
1042 static int ipvideo_decode_frame(AVCodecContext *avctx,
1043 void *data, int *data_size,
1046 const uint8_t *buf = avpkt->data;
1047 int buf_size = avpkt->size;
1048 IpvideoContext *s = avctx->priv_data;
1050 /* compressed buffer needs to be large enough to at least hold an entire
1052 if (buf_size < s->decoding_map_size)
1055 s->decoding_map = buf;
1056 s->buf = buf + s->decoding_map_size;
1057 s->size = buf_size - s->decoding_map_size;
1059 s->current_frame.reference = 3;
1060 if (avctx->get_buffer(avctx, &s->current_frame)) {
1061 av_log(avctx, AV_LOG_ERROR, " Interplay Video: get_buffer() failed\n");
1066 const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
1068 s->current_frame.palette_has_changed = 1;
1069 memcpy(s->pal, pal, AVPALETTE_SIZE);
1073 ipvideo_decode_opcodes(s);
1075 *data_size = sizeof(AVFrame);
1076 *(AVFrame*)data = s->current_frame;
1078 /* shuffle frames */
1079 if (s->second_last_frame.data[0])
1080 avctx->release_buffer(avctx, &s->second_last_frame);
1081 s->second_last_frame = s->last_frame;
1082 s->last_frame = s->current_frame;
1083 s->current_frame.data[0] = NULL; /* catch any access attempts */
1085 /* report that the buffer was completely consumed */
1089 static av_cold int ipvideo_decode_end(AVCodecContext *avctx)
1091 IpvideoContext *s = avctx->priv_data;
1093 /* release the last frame */
1094 if (s->last_frame.data[0])
1095 avctx->release_buffer(avctx, &s->last_frame);
1096 if (s->second_last_frame.data[0])
1097 avctx->release_buffer(avctx, &s->second_last_frame);
1102 AVCodec ff_interplay_video_decoder = {
1105 CODEC_ID_INTERPLAY_VIDEO,
1106 sizeof(IpvideoContext),
1107 ipvideo_decode_init,
1110 ipvideo_decode_frame,
1112 .long_name = NULL_IF_CONFIG_SMALL("Interplay MVE video"),