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;
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); \
89 static int copy_from(IpvideoContext *s, AVFrame *src, int delta_x, int delta_y)
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);
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);
102 if (src->data[0] == NULL) {
103 av_log(s->avctx, AV_LOG_ERROR, "Invalid decode type, corrupted header?\n");
104 return AVERROR(EINVAL);
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);
111 static int ipvideo_decode_block_opcode_0x0(IpvideoContext *s)
113 return copy_from(s, &s->last_frame, 0, 0);
116 static int ipvideo_decode_block_opcode_0x1(IpvideoContext *s)
118 return copy_from(s, &s->second_last_frame, 0, 0);
121 static int ipvideo_decode_block_opcode_0x2(IpvideoContext *s)
126 /* copy block from 2 frames ago using a motion vector; need 1 more byte */
128 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
129 B = *s->stream_ptr++;
131 CHECK_STREAM_PTR(s->mv_ptr, s->mv_end, 1);
139 x = -14 + ((B - 56) % 29);
140 y = 8 + ((B - 56) / 29);
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);
147 static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s)
152 /* copy 8x8 block from current frame from an up/left block */
154 /* need 1 more byte for motion */
156 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
157 B = *s->stream_ptr++;
159 CHECK_STREAM_PTR(s->mv_ptr, s->mv_end, 1);
167 x = -(-14 + ((B - 56) % 29));
168 y = -( 8 + ((B - 56) / 29));
171 debug_interplay (" motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
172 return copy_from(s, &s->current_frame, x, y);
175 static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s)
178 unsigned char B, BL, BH;
180 /* copy a block from the previous frame; need 1 more byte */
182 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
183 B = *s->stream_ptr++;
185 CHECK_STREAM_PTR(s->mv_ptr, s->mv_end, 1);
190 BH = (B >> 4) & 0x0F;
194 debug_interplay (" motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
195 return copy_from(s, &s->last_frame, x, y);
198 static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s)
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);
206 x = *s->stream_ptr++;
207 y = *s->stream_ptr++;
209 debug_interplay (" motion bytes = %d, %d\n", x, y);
210 return copy_from(s, &s->last_frame, x, y);
213 static int ipvideo_decode_block_opcode_0x6(IpvideoContext *s)
215 /* mystery opcode? skip multiple blocks? */
216 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: Help! Mystery opcode 0x6 seen\n");
222 static int ipvideo_decode_block_opcode_0x7(IpvideoContext *s)
228 /* 2-color encoding */
229 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
231 P[0] = *s->stream_ptr++;
232 P[1] = *s->stream_ptr++;
236 /* need 8 more bytes from the stream */
237 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
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;
248 /* need 2 more bytes from the stream */
249 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
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) {
255 s->pixel_ptr[x + 1 ] =
256 s->pixel_ptr[x + s->stride] =
257 s->pixel_ptr[x + 1 + s->stride] = P[flags & 1];
259 s->pixel_ptr += s->stride * 2;
267 static int ipvideo_decode_block_opcode_0x8(IpvideoContext *s)
271 unsigned int flags = 0;
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);
277 P[0] = *s->stream_ptr++;
278 P[1] = *s->stream_ptr++;
282 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 14);
285 for (y = 0; y < 16; y++) {
286 // new values for each 4x4 block
288 P[0] = *s->stream_ptr++; P[1] = *s->stream_ptr++;
289 flags = bytestream_get_le16(&s->stream_ptr);
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;
301 /* need 10 more bytes */
302 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 10);
304 if (s->stream_ptr[4] <= s->stream_ptr[5]) {
306 flags = bytestream_get_le32(&s->stream_ptr);
308 /* vertical split; left & right halves are 2-color encoded */
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
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);
324 /* horizontal split; top & bottom halves are 2-color encoded */
326 for (y = 0; y < 8; y++) {
328 P[0] = *s->stream_ptr++;
329 P[1] = *s->stream_ptr++;
331 flags = *s->stream_ptr++ | 0x100;
333 for (; flags != 1; flags >>= 1)
334 *s->pixel_ptr++ = P[flags & 1];
335 s->pixel_ptr += s->line_inc;
344 static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s)
349 /* 4-color encoding */
350 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
352 memcpy(P, s->stream_ptr, 4);
358 /* 1 of 4 colors for each pixel, need 16 more bytes */
359 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 16);
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;
372 /* 1 of 4 colors for each 2x2 block, need 4 more bytes */
373 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
375 flags = bytestream_get_le32(&s->stream_ptr);
377 for (y = 0; y < 8; y += 2) {
378 for (x = 0; x < 8; x += 2, flags >>= 2) {
380 s->pixel_ptr[x + 1 ] =
381 s->pixel_ptr[x + s->stride] =
382 s->pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
384 s->pixel_ptr += s->stride * 2;
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);
394 flags = bytestream_get_le64(&s->stream_ptr);
396 for (y = 0; y < 8; y++) {
397 for (x = 0; x < 8; x += 2, flags >>= 2) {
399 s->pixel_ptr[x + 1] = P[flags & 0x03];
401 s->pixel_ptr += s->stride;
404 for (y = 0; y < 8; y += 2) {
405 for (x = 0; x < 8; x++, flags >>= 2) {
407 s->pixel_ptr[x + s->stride] = P[flags & 0x03];
409 s->pixel_ptr += s->stride * 2;
418 static int ipvideo_decode_block_opcode_0xA(IpvideoContext *s)
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);
428 if (s->stream_ptr[0] <= s->stream_ptr[1]) {
430 /* 4-color encoding for each quadrant; need 32 bytes */
431 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 32);
433 for (y = 0; y < 16; y++) {
434 // new values for each 4x4 block
436 memcpy(P, s->stream_ptr, 4);
438 flags = bytestream_get_le32(&s->stream_ptr);
441 for (x = 0; x < 4; x++, flags >>= 2)
442 *s->pixel_ptr++ = P[flags & 0x03];
444 s->pixel_ptr += s->stride - 4;
445 // switch to right half
446 if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
451 int vert = s->stream_ptr[12] <= s->stream_ptr[13];
454 /* 4-color encoding for either left and right or top and bottom
457 for (y = 0; y < 16; y++) {
458 // load values for each half
460 memcpy(P, s->stream_ptr, 4);
462 flags = bytestream_get_le64(&s->stream_ptr);
465 for (x = 0; x < 4; x++, flags >>= 2)
466 *s->pixel_ptr++ = P[flags & 0x03];
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;
480 static int ipvideo_decode_block_opcode_0xB(IpvideoContext *s)
484 /* 64-color encoding (each pixel in block is a different color) */
485 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 64);
487 for (y = 0; y < 8; y++) {
488 memcpy(s->pixel_ptr, s->stream_ptr, 8);
490 s->pixel_ptr += s->stride;
497 static int ipvideo_decode_block_opcode_0xC(IpvideoContext *s)
501 /* 16-color block encoding: each 2x2 block is a different color */
502 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 16);
504 for (y = 0; y < 8; y += 2) {
505 for (x = 0; x < 8; x += 2) {
507 s->pixel_ptr[x + 1 ] =
508 s->pixel_ptr[x + s->stride] =
509 s->pixel_ptr[x + 1 + s->stride] = *s->stream_ptr++;
511 s->pixel_ptr += s->stride * 2;
518 static int ipvideo_decode_block_opcode_0xD(IpvideoContext *s)
523 /* 4-color block encoding: each 4x4 block is a different color */
524 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
526 for (y = 0; y < 8; y++) {
528 P[0] = *s->stream_ptr++;
529 P[1] = *s->stream_ptr++;
531 memset(s->pixel_ptr, P[0], 4);
532 memset(s->pixel_ptr + 4, P[1], 4);
533 s->pixel_ptr += s->stride;
540 static int ipvideo_decode_block_opcode_0xE(IpvideoContext *s)
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++;
549 for (y = 0; y < 8; y++) {
550 memset(s->pixel_ptr, pix, 8);
551 s->pixel_ptr += s->stride;
558 static int ipvideo_decode_block_opcode_0xF(IpvideoContext *s)
561 unsigned char sample[2];
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++;
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)];
573 s->pixel_ptr += s->line_inc;
580 static int ipvideo_decode_block_opcode_0x6_16(IpvideoContext *s)
584 /* copy a block from the second last frame using an expanded range */
585 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
587 x = *s->stream_ptr++;
588 y = *s->stream_ptr++;
590 debug_interplay (" motion bytes = %d, %d\n", x, y);
591 return copy_from(s, &s->second_last_frame, x, y);
594 static int ipvideo_decode_block_opcode_0x7_16(IpvideoContext *s)
599 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
601 /* 2-color encoding */
602 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
604 P[0] = bytestream_get_le16(&s->stream_ptr);
605 P[1] = bytestream_get_le16(&s->stream_ptr);
607 if (!(P[0] & 0x8000)) {
609 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
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;
620 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
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) {
627 pixel_ptr[x + s->stride] =
628 pixel_ptr[x + 1 + s->stride] = P[flags & 1];
630 pixel_ptr += s->stride * 2;
637 static int ipvideo_decode_block_opcode_0x8_16(IpvideoContext *s)
641 unsigned int flags = 0;
642 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
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);
648 P[0] = bytestream_get_le16(&s->stream_ptr);
649 P[1] = bytestream_get_le16(&s->stream_ptr);
651 if (!(P[0] & 0x8000)) {
653 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 24);
656 for (y = 0; y < 16; y++) {
657 // new values for each 4x4 block
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);
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;
673 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 12);
675 if (!(AV_RL16(s->stream_ptr + 4) & 0x8000)) {
677 flags = bytestream_get_le32(&s->stream_ptr);
679 /* vertical split; left & right halves are 2-color encoded */
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
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);
696 /* horizontal split; top & bottom halves are 2-color encoded */
698 for (y = 0; y < 8; y++) {
700 P[0] = bytestream_get_le16(&s->stream_ptr);
701 P[1] = bytestream_get_le16(&s->stream_ptr);
703 flags = *s->stream_ptr++ | 0x100;
705 for (; flags != 1; flags >>= 1)
706 *pixel_ptr++ = P[flags & 1];
707 pixel_ptr += s->line_inc;
716 static int ipvideo_decode_block_opcode_0x9_16(IpvideoContext *s)
720 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
722 /* 4-color encoding */
723 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
725 for (x = 0; x < 4; x++)
726 P[x] = bytestream_get_le16(&s->stream_ptr);
728 if (!(P[0] & 0x8000)) {
729 if (!(P[2] & 0x8000)) {
731 /* 1 of 4 colors for each pixel */
732 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 16);
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;
745 /* 1 of 4 colors for each 2x2 block */
746 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
748 flags = bytestream_get_le32(&s->stream_ptr);
750 for (y = 0; y < 8; y += 2) {
751 for (x = 0; x < 8; x += 2, flags >>= 2) {
754 pixel_ptr[x + s->stride] =
755 pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
757 pixel_ptr += s->stride * 2;
764 /* 1 of 4 colors for each 2x1 or 1x2 block */
765 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
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) {
772 pixel_ptr[x + 1] = P[flags & 0x03];
774 pixel_ptr += s->stride;
777 for (y = 0; y < 8; y += 2) {
778 for (x = 0; x < 8; x++, flags >>= 2) {
780 pixel_ptr[x + s->stride] = P[flags & 0x03];
782 pixel_ptr += s->stride * 2;
791 static int ipvideo_decode_block_opcode_0xA_16(IpvideoContext *s)
796 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
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);
802 if (!(AV_RL16(s->stream_ptr) & 0x8000)) {
804 /* 4-color encoding for each quadrant */
805 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 48);
807 for (y = 0; y < 16; y++) {
808 // new values for each 4x4 block
810 for (x = 0; x < 4; x++)
811 P[x] = bytestream_get_le16(&s->stream_ptr);
812 flags = bytestream_get_le32(&s->stream_ptr);
815 for (x = 0; x < 4; x++, flags >>= 2)
816 *pixel_ptr++ = P[flags & 0x03];
818 pixel_ptr += s->stride - 4;
819 // switch to right half
820 if (y == 7) pixel_ptr -= 8 * s->stride - 4;
825 int vert = !(AV_RL16(s->stream_ptr + 16) & 0x8000);
828 /* 4-color encoding for either left and right or top and bottom
831 for (y = 0; y < 16; y++) {
832 // load values for each half
834 for (x = 0; x < 4; x++)
835 P[x] = bytestream_get_le16(&s->stream_ptr);
836 flags = bytestream_get_le64(&s->stream_ptr);
839 for (x = 0; x < 4; x++, flags >>= 2)
840 *pixel_ptr++ = P[flags & 0x03];
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;
854 static int ipvideo_decode_block_opcode_0xB_16(IpvideoContext *s)
857 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
859 /* 64-color encoding (each pixel in block is a different color) */
860 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 128);
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;
872 static int ipvideo_decode_block_opcode_0xC_16(IpvideoContext *s)
875 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
877 /* 16-color block encoding: each 2x2 block is a different color */
878 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 32);
880 for (y = 0; y < 8; y += 2) {
881 for (x = 0; x < 8; x += 2) {
884 pixel_ptr[x + s->stride] =
885 pixel_ptr[x + 1 + s->stride] = bytestream_get_le16(&s->stream_ptr);
887 pixel_ptr += s->stride * 2;
894 static int ipvideo_decode_block_opcode_0xD_16(IpvideoContext *s)
898 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
900 /* 4-color block encoding: each 4x4 block is a different color */
901 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
903 for (y = 0; y < 8; y++) {
905 P[0] = bytestream_get_le16(&s->stream_ptr);
906 P[1] = bytestream_get_le16(&s->stream_ptr);
908 for (x = 0; x < 8; x++)
909 pixel_ptr[x] = P[x >> 2];
910 pixel_ptr += s->stride;
917 static int ipvideo_decode_block_opcode_0xE_16(IpvideoContext *s)
921 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
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);
927 for (y = 0; y < 8; y++) {
928 for (x = 0; x < 8; x++)
930 pixel_ptr += s->stride;
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,
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,
959 static void ipvideo_decode_opcodes(IpvideoContext *s)
962 unsigned char opcode;
964 static int frame = 0;
967 debug_interplay("------------------ frame %d\n", frame);
971 /* this is PAL8, so make the palette available */
972 memcpy(s->current_frame.data[1], s->avctx->palctrl->palette, PALETTE_COUNT * 4);
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;
978 s->stride = s->current_frame.linesize[0] >> 1;
979 s->stream_ptr = s->buf + 16;
981 s->mv_ptr = s->buf + 14 + AV_RL16(s->buf+14);
982 s->mv_end = s->buf + s->size;
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);
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);
993 debug_interplay(" block @ (%3d, %3d): encoding 0x%X, data ptr @ %p\n",
994 x, y, opcode, s->stream_ptr);
997 s->pixel_ptr = s->current_frame.data[0] + x
998 + y*s->current_frame.linesize[0];
999 ret = ipvideo_decode_block[opcode](s);
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);
1006 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode problem on frame %d, @ block (%d, %d)\n",
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);
1018 static av_cold int ipvideo_decode_init(AVCodecContext *avctx)
1020 IpvideoContext *s = avctx->priv_data;
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");
1031 dsputil_init(&s->dsp, avctx);
1033 /* decoding map contains 4 bits of information per 8x8 block */
1034 s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2);
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;
1049 AVPaletteControl *palette_control = avctx->palctrl;
1051 /* compressed buffer needs to be large enough to at least hold an entire
1053 if (buf_size < s->decoding_map_size)
1056 s->decoding_map = buf;
1057 s->buf = buf + s->decoding_map_size;
1058 s->size = buf_size - s->decoding_map_size;
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");
1066 ipvideo_decode_opcodes(s);
1068 if (!s->is_16bpp && palette_control->palette_changed) {
1069 palette_control->palette_changed = 0;
1070 s->current_frame.palette_has_changed = 1;
1073 *data_size = sizeof(AVFrame);
1074 *(AVFrame*)data = s->current_frame;
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 */
1083 /* report that the buffer was completely consumed */
1087 static av_cold int ipvideo_decode_end(AVCodecContext *avctx)
1089 IpvideoContext *s = avctx->priv_data;
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);
1100 AVCodec ff_interplay_video_decoder = {
1103 CODEC_ID_INTERPLAY_VIDEO,
1104 sizeof(IpvideoContext),
1105 ipvideo_decode_init,
1108 ipvideo_decode_frame,
1110 .long_name = NULL_IF_CONFIG_SMALL("Interplay MVE video"),