2 * Interplay MVE Video Decoder
3 * Copyright (C) 2003 the ffmpeg project
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * @file interplayvideo.c
23 * Interplay MVE Video Decoder by Mike Melanson (melanson@pcisys.net)
24 * For more information about the Interplay MVE format, visit:
25 * http://www.pcisys.net/~melanson/codecs/interplay-mve.txt
26 * This code is written in such a way that the identifiers match up
27 * with the encoding descriptions in the document.
29 * This decoder presently only supports a PAL8 output colorspace.
31 * An Interplay video frame consists of 2 parts: The decoding map and
32 * the video data. A demuxer must load these 2 parts together in a single
33 * buffer before sending it through the stream to this decoder.
45 #define PALETTE_COUNT 256
47 /* debugging support */
48 #define DEBUG_INTERPLAY 0
50 #define debug_interplay printf
52 static inline void debug_interplay(const char *format
, ...) { }
55 typedef struct IpvideoContext
{
57 AVCodecContext
*avctx
;
60 AVFrame current_frame
;
62 unsigned char *decoding_map
;
63 int decoding_map_size
;
68 unsigned char palette
[PALETTE_COUNT
* 4];
72 #define CHECK_STREAM_PTR(n) \
73 if ((sg_stream_ptr + n) > sg_stream_end) { \
74 printf ("Interplay video warning: stream_ptr out of bounds (%p >= %p)\n", \
75 sg_stream_ptr + n, sg_stream_end); \
79 static void ipvideo_new_palette(IpvideoContext
*s
, unsigned char *palette
) {
82 unsigned char r
, g
, b
;
83 unsigned int *palette32
;
85 switch (s
->avctx
->pix_fmt
) {
88 palette32
= (unsigned int *)s
->palette
;
89 for (i
= 0; i
< PALETTE_COUNT
; i
++) {
93 palette32
[i
] = (r
<< 16) | (g
<< 8) | (b
);
98 printf ("Interplay video: Unhandled video format\n");
103 static unsigned char *sg_stream_ptr
;
104 static unsigned char *sg_stream_end
;
105 static unsigned char *sg_current_plane
;
106 static unsigned char *sg_output_plane
;
107 static unsigned char *sg_last_plane
;
108 static int sg_line_inc
;
109 static int sg_stride
;
110 static int sg_upper_motion_limit_offset
;
111 static DSPContext sg_dsp
;
113 static int ipvideo_decode_block_opcode_0x0_0x1(void)
116 unsigned char *src_block
;
118 /* skip block, which actually means to copy from previous frame */
119 src_block
= sg_last_plane
+ (sg_output_plane
- sg_current_plane
);
120 for (y
= 0; y
< 8; y
++) {
121 for (x
= 0; x
< 8; x
++) {
122 *sg_output_plane
++ = *src_block
++;
124 sg_output_plane
+= sg_line_inc
;
125 src_block
+= sg_line_inc
;
132 #define COPY_FROM_CURRENT() \
133 motion_offset = current_offset; \
134 motion_offset += y * sg_stride; \
135 motion_offset += x; \
136 if (motion_offset < 0) { \
137 printf (" Interplay video: motion offset < 0 (%d)\n", motion_offset); \
139 } else if (motion_offset > sg_upper_motion_limit_offset) { \
140 printf (" Interplay video: motion offset above limit (%d >= %d)\n", \
141 motion_offset, sg_upper_motion_limit_offset); \
144 sg_dsp.put_pixels_tab[0][0](sg_output_plane, \
145 sg_current_plane + motion_offset, sg_stride, 8);
147 #define COPY_FROM_PREVIOUS() \
148 motion_offset = current_offset; \
149 motion_offset += y * sg_stride; \
150 motion_offset += x; \
151 if (motion_offset < 0) { \
152 printf (" Interplay video: motion offset < 0 (%d)\n", motion_offset); \
154 } else if (motion_offset > sg_upper_motion_limit_offset) { \
155 printf (" Interplay video: motion offset above limit (%d >= %d)\n", \
156 motion_offset, sg_upper_motion_limit_offset); \
159 sg_dsp.put_pixels_tab[0][0](sg_output_plane, \
160 sg_last_plane + motion_offset, sg_stride, 8);
162 static int ipvideo_decode_block_opcode_0x2(void)
167 int current_offset
= sg_output_plane
- sg_current_plane
;
169 /* This is the opcode which claims to copy data from within the same
170 * frame at a coordinate which has not been rendered yet. Assume that
171 * it is supposed to be copied from the previous frame. */
173 /* need 1 more byte for motion */
175 B
= *sg_stream_ptr
++;
181 x
= -14 + ((B
- 56) % 29);
182 y
= 8 + ((B
- 56) / 29);
185 debug_interplay (" motion byte = %d, (x, y) = (%d, %d)\n", B
, x
, y
);
186 COPY_FROM_PREVIOUS();
192 static int ipvideo_decode_block_opcode_0x3(void)
197 int current_offset
= sg_output_plane
- sg_current_plane
;
199 /* copy 8x8 block from current frame from an up/left block */
201 /* need 1 more byte for motion */
203 B
= *sg_stream_ptr
++;
209 x
= -(-14 + ((B
- 56) % 29));
210 y
= -( 8 + ((B
- 56) / 29));
213 debug_interplay (" motion byte = %d, (x, y) = (%d, %d)\n", B
, x
, y
);
220 static int ipvideo_decode_block_opcode_0x4(void)
223 unsigned char B
, BL
, BH
;
225 int current_offset
= sg_output_plane
- sg_current_plane
;
227 /* copy a block from the previous frame; need 1 more byte */
230 B
= *sg_stream_ptr
++;
232 BH
= (B
>> 4) & 0x0F;
236 debug_interplay (" motion byte = %d, (x, y) = (%d, %d)\n", B
, x
, y
);
237 COPY_FROM_PREVIOUS();
243 static int ipvideo_decode_block_opcode_0x5(void)
247 int current_offset
= sg_output_plane
- sg_current_plane
;
249 /* copy a block from the previous frame using an expanded range;
250 * need 2 more bytes */
253 x
= *sg_stream_ptr
++;
254 y
= *sg_stream_ptr
++;
256 debug_interplay (" motion bytes = %d, %d\n", x
, y
);
257 COPY_FROM_PREVIOUS();
263 static int ipvideo_decode_block_opcode_0x6(void)
265 /* mystery opcode? skip multiple blocks? */
266 printf (" Interplay video: Help! Mystery opcode 0x6 seen\n");
272 static int ipvideo_decode_block_opcode_0x7(void)
275 unsigned char P0
, P1
;
280 /* 2-color encoding */
283 P0
= *sg_stream_ptr
++;
284 P1
= *sg_stream_ptr
++;
288 /* need 8 more bytes from the stream */
290 for (y
= 0; y
< 8; y
++)
291 B
[y
] = *sg_stream_ptr
++;
293 for (y
= 0; y
< 8; y
++) {
295 for (x
= 0x01; x
<= 0x80; x
<<= 1) {
297 *sg_output_plane
++ = P1
;
299 *sg_output_plane
++ = P0
;
301 sg_output_plane
+= sg_line_inc
;
306 /* need 2 more bytes from the stream */
308 B
[0] = *sg_stream_ptr
++;
309 B
[1] = *sg_stream_ptr
++;
311 flags
= (B
[1] << 8) | B
[0];
313 for (y
= 0; y
< 8; y
+= 2) {
314 for (x
= 0; x
< 8; x
+= 2, bitmask
<<= 1) {
315 if (flags
& bitmask
) {
316 *(sg_output_plane
+ x
) = P0
;
317 *(sg_output_plane
+ x
+ 1) = P0
;
318 *(sg_output_plane
+ sg_stride
+ x
) = P0
;
319 *(sg_output_plane
+ sg_stride
+ x
+ 1) = P0
;
321 *(sg_output_plane
+ x
) = P1
;
322 *(sg_output_plane
+ x
+ 1) = P1
;
323 *(sg_output_plane
+ sg_stride
+ x
) = P1
;
324 *(sg_output_plane
+ sg_stride
+ x
+ 1) = P1
;
327 sg_output_plane
+= sg_stride
* 2;
335 static int ipvideo_decode_block_opcode_0x8(void)
340 unsigned int flags
= 0;
341 unsigned int bitmask
= 0;
342 unsigned char P0
= 0, P1
= 0;
345 /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
346 * either top and bottom or left and right halves */
349 P
[0] = *sg_stream_ptr
++;
350 P
[1] = *sg_stream_ptr
++;
354 /* need 12 more bytes */
355 CHECK_STREAM_PTR(12);
356 B
[0] = *sg_stream_ptr
++; B
[1] = *sg_stream_ptr
++;
357 P
[2] = *sg_stream_ptr
++; P
[3] = *sg_stream_ptr
++;
358 B
[2] = *sg_stream_ptr
++; B
[3] = *sg_stream_ptr
++;
359 P
[4] = *sg_stream_ptr
++; P
[5] = *sg_stream_ptr
++;
360 B
[4] = *sg_stream_ptr
++; B
[5] = *sg_stream_ptr
++;
361 P
[6] = *sg_stream_ptr
++; P
[7] = *sg_stream_ptr
++;
362 B
[6] = *sg_stream_ptr
++; B
[7] = *sg_stream_ptr
++;
364 for (y
= 0; y
< 8; y
++) {
366 /* time to reload flags? */
369 ((B
[0] & 0xF0) << 4) | ((B
[4] & 0xF0) << 8) |
370 ((B
[0] & 0x0F) ) | ((B
[4] & 0x0F) << 4) |
371 ((B
[1] & 0xF0) << 20) | ((B
[5] & 0xF0) << 24) |
372 ((B
[1] & 0x0F) << 16) | ((B
[5] & 0x0F) << 20);
373 bitmask
= 0x00000001;
374 lower_half
= 0; /* still on top half */
377 ((B
[2] & 0xF0) << 4) | ((B
[6] & 0xF0) << 8) |
378 ((B
[2] & 0x0F) ) | ((B
[6] & 0x0F) << 4) |
379 ((B
[3] & 0xF0) << 20) | ((B
[7] & 0xF0) << 24) |
380 ((B
[3] & 0x0F) << 16) | ((B
[7] & 0x0F) << 20);
381 bitmask
= 0x00000001;
385 for (x
= 0; x
< 8; x
++, bitmask
<<= 1) {
386 /* get the pixel values ready for this quadrant */
388 P0
= P
[lower_half
+ 0];
389 P1
= P
[lower_half
+ 1];
391 P0
= P
[lower_half
+ 2];
392 P1
= P
[lower_half
+ 3];
396 *sg_output_plane
++ = P1
;
398 *sg_output_plane
++ = P0
;
400 sg_output_plane
+= sg_line_inc
;
405 /* need 10 more bytes */
406 CHECK_STREAM_PTR(10);
407 B
[0] = *sg_stream_ptr
++; B
[1] = *sg_stream_ptr
++;
408 B
[2] = *sg_stream_ptr
++; B
[3] = *sg_stream_ptr
++;
409 P
[2] = *sg_stream_ptr
++; P
[3] = *sg_stream_ptr
++;
410 B
[4] = *sg_stream_ptr
++; B
[5] = *sg_stream_ptr
++;
411 B
[6] = *sg_stream_ptr
++; B
[7] = *sg_stream_ptr
++;
415 /* vertical split; left & right halves are 2-color encoded */
417 for (y
= 0; y
< 8; y
++) {
419 /* time to reload flags? */
422 ((B
[0] & 0xF0) << 4) | ((B
[4] & 0xF0) << 8) |
423 ((B
[0] & 0x0F) ) | ((B
[4] & 0x0F) << 4) |
424 ((B
[1] & 0xF0) << 20) | ((B
[5] & 0xF0) << 24) |
425 ((B
[1] & 0x0F) << 16) | ((B
[5] & 0x0F) << 20);
426 bitmask
= 0x00000001;
429 ((B
[2] & 0xF0) << 4) | ((B
[6] & 0xF0) << 8) |
430 ((B
[2] & 0x0F) ) | ((B
[6] & 0x0F) << 4) |
431 ((B
[3] & 0xF0) << 20) | ((B
[7] & 0xF0) << 24) |
432 ((B
[3] & 0x0F) << 16) | ((B
[7] & 0x0F) << 20);
433 bitmask
= 0x00000001;
436 for (x
= 0; x
< 8; x
++, bitmask
<<= 1) {
437 /* get the pixel values ready for this half */
447 *sg_output_plane
++ = P0
;
449 *sg_output_plane
++ = P1
;
451 sg_output_plane
+= sg_line_inc
;
456 /* horizontal split; top & bottom halves are 2-color encoded */
458 for (y
= 0; y
< 8; y
++) {
469 for (bitmask
= 0x01; bitmask
<= 0x80; bitmask
<<= 1) {
472 *sg_output_plane
++ = P0
;
474 *sg_output_plane
++ = P1
;
476 sg_output_plane
+= sg_line_inc
;
485 static int ipvideo_decode_block_opcode_0x9(void)
490 unsigned int flags
= 0;
494 /* 4-color encoding */
497 for (y
= 0; y
< 4; y
++)
498 P
[y
] = *sg_stream_ptr
++;
500 if ((P
[0] <= P
[1]) && (P
[2] <= P
[3])) {
502 /* 1 of 4 colors for each pixel, need 16 more bytes */
503 CHECK_STREAM_PTR(16);
505 for (y
= 0; y
< 8; y
++) {
506 /* get the next set of 8 2-bit flags */
507 flags
= (sg_stream_ptr
[1] << 8) | sg_stream_ptr
[0];
509 for (x
= 0, shifter
= 0; x
< 8; x
++, shifter
+= 2) {
510 *sg_output_plane
++ = P
[(flags
>> shifter
) & 0x03];
512 sg_output_plane
+= sg_line_inc
;
515 } else if ((P
[0] <= P
[1]) && (P
[2] > P
[3])) {
517 /* 1 of 4 colors for each 2x2 block, need 4 more bytes */
520 B
[0] = *sg_stream_ptr
++;
521 B
[1] = *sg_stream_ptr
++;
522 B
[2] = *sg_stream_ptr
++;
523 B
[3] = *sg_stream_ptr
++;
524 flags
= (B
[3] << 24) | (B
[2] << 16) | (B
[1] << 8) | B
[0];
527 for (y
= 0; y
< 8; y
+= 2) {
528 for (x
= 0; x
< 8; x
+= 2, shifter
+= 2) {
529 pix
= P
[(flags
>> shifter
) & 0x03];
530 *(sg_output_plane
+ x
) = pix
;
531 *(sg_output_plane
+ x
+ 1) = pix
;
532 *(sg_output_plane
+ sg_stride
+ x
) = pix
;
533 *(sg_output_plane
+ sg_stride
+ x
+ 1) = pix
;
535 sg_output_plane
+= sg_stride
* 2;
538 } else if ((P
[0] > P
[1]) && (P
[2] <= P
[3])) {
540 /* 1 of 4 colors for each 2x1 block, need 8 more bytes */
543 for (y
= 0; y
< 8; y
++) {
544 /* time to reload flags? */
545 if ((y
== 0) || (y
== 4)) {
546 B
[0] = *sg_stream_ptr
++;
547 B
[1] = *sg_stream_ptr
++;
548 B
[2] = *sg_stream_ptr
++;
549 B
[3] = *sg_stream_ptr
++;
550 flags
= (B
[3] << 24) | (B
[2] << 16) | (B
[1] << 8) | B
[0];
553 for (x
= 0; x
< 8; x
+= 2, shifter
+= 2) {
554 pix
= P
[(flags
>> shifter
) & 0x03];
555 *(sg_output_plane
+ x
) = pix
;
556 *(sg_output_plane
+ x
+ 1) = pix
;
558 sg_output_plane
+= sg_stride
;
563 /* 1 of 4 colors for each 1x2 block, need 8 more bytes */
566 for (y
= 0; y
< 8; y
+= 2) {
567 /* time to reload flags? */
568 if ((y
== 0) || (y
== 4)) {
569 B
[0] = *sg_stream_ptr
++;
570 B
[1] = *sg_stream_ptr
++;
571 B
[2] = *sg_stream_ptr
++;
572 B
[3] = *sg_stream_ptr
++;
573 flags
= (B
[3] << 24) | (B
[2] << 16) | (B
[1] << 8) | B
[0];
576 for (x
= 0; x
< 8; x
++, shifter
+= 2) {
577 pix
= P
[(flags
>> shifter
) & 0x03];
578 *(sg_output_plane
+ x
) = pix
;
579 *(sg_output_plane
+ sg_stride
+ x
) = pix
;
581 sg_output_plane
+= sg_stride
* 2;
589 static int ipvideo_decode_block_opcode_0xA(void)
600 /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
601 * either top and bottom or left and right halves */
604 for (y
= 0; y
< 4; y
++)
605 P
[y
] = *sg_stream_ptr
++;
609 /* 4-color encoding for each quadrant; need 28 more bytes */
610 CHECK_STREAM_PTR(28);
612 for (y
= 0; y
< 4; y
++)
613 B
[y
] = *sg_stream_ptr
++;
614 for (y
= 4; y
< 16; y
+= 4) {
615 for (x
= y
; x
< y
+ 4; x
++)
616 P
[x
] = *sg_stream_ptr
++;
617 for (x
= y
; x
< y
+ 4; x
++)
618 B
[x
] = *sg_stream_ptr
++;
621 for (y
= 0; y
< 8; y
++) {
623 lower_half
= (y
>= 4) ?
4 : 0;
624 flags
= (B
[y
+ 8] << 8) | B
[y
];
626 for (x
= 0, shifter
= 0; x
< 8; x
++, shifter
+= 2) {
627 split
= (x
>= 4) ?
8 : 0;
628 index
= split
+ lower_half
+ ((flags
>> shifter
) & 0x03);
629 *sg_output_plane
++ = P
[index
];
632 sg_output_plane
+= sg_line_inc
;
637 /* 4-color encoding for either left and right or top and bottom
638 * halves; need 20 more bytes */
639 CHECK_STREAM_PTR(20);
641 for (y
= 0; y
< 8; y
++)
642 B
[y
] = *sg_stream_ptr
++;
643 for (y
= 4; y
< 8; y
++)
644 P
[y
] = *sg_stream_ptr
++;
645 for (y
= 8; y
< 16; y
++)
646 B
[y
] = *sg_stream_ptr
++;
650 /* block is divided into left and right halves */
651 for (y
= 0; y
< 8; y
++) {
653 flags
= (B
[y
+ 8] << 8) | B
[y
];
656 for (x
= 0, shifter
= 0; x
< 8; x
++, shifter
+= 2) {
659 *sg_output_plane
++ = P
[split
+ ((flags
>> shifter
) & 0x03)];
662 sg_output_plane
+= sg_line_inc
;
667 /* block is divided into top and bottom halves */
669 for (y
= 0; y
< 8; y
++) {
671 flags
= (B
[y
* 2 + 1] << 8) | B
[y
* 2];
675 for (x
= 0, shifter
= 0; x
< 8; x
++, shifter
+= 2)
676 *sg_output_plane
++ = P
[split
+ ((flags
>> shifter
) & 0x03)];
678 sg_output_plane
+= sg_line_inc
;
687 static int ipvideo_decode_block_opcode_0xB(void)
691 /* 64-color encoding (each pixel in block is a different color) */
692 CHECK_STREAM_PTR(64);
694 for (y
= 0; y
< 8; y
++) {
695 for (x
= 0; x
< 8; x
++) {
696 *sg_output_plane
++ = *sg_stream_ptr
++;
698 sg_output_plane
+= sg_line_inc
;
705 static int ipvideo_decode_block_opcode_0xC(void)
710 /* 16-color block encoding: each 2x2 block is a different color */
711 CHECK_STREAM_PTR(16);
713 for (y
= 0; y
< 8; y
+= 2) {
714 for (x
= 0; x
< 8; x
+= 2) {
715 pix
= *sg_stream_ptr
++;
716 *(sg_output_plane
+ x
) = pix
;
717 *(sg_output_plane
+ x
+ 1) = pix
;
718 *(sg_output_plane
+ sg_stride
+ x
) = pix
;
719 *(sg_output_plane
+ sg_stride
+ x
+ 1) = pix
;
721 sg_output_plane
+= sg_stride
* 2;
728 static int ipvideo_decode_block_opcode_0xD(void)
732 unsigned char index
= 0;
734 /* 4-color block encoding: each 4x4 block is a different color */
737 for (y
= 0; y
< 4; y
++)
738 P
[y
] = *sg_stream_ptr
++;
740 for (y
= 0; y
< 8; y
++) {
746 for (x
= 0; x
< 8; x
++) {
749 *sg_output_plane
++ = P
[index
];
751 sg_output_plane
+= sg_line_inc
;
758 static int ipvideo_decode_block_opcode_0xE(void)
763 /* 1-color encoding: the whole block is 1 solid color */
765 pix
= *sg_stream_ptr
++;
767 for (y
= 0; y
< 8; y
++) {
768 for (x
= 0; x
< 8; x
++) {
769 *sg_output_plane
++ = pix
;
771 sg_output_plane
+= sg_line_inc
;
778 static int ipvideo_decode_block_opcode_0xF(void)
781 unsigned char sample0
, sample1
;
783 /* dithered encoding */
785 sample0
= *sg_stream_ptr
++;
786 sample1
= *sg_stream_ptr
++;
788 for (y
= 0; y
< 8; y
++) {
789 for (x
= 0; x
< 8; x
+= 2) {
791 *sg_output_plane
++ = sample1
;
792 *sg_output_plane
++ = sample0
;
794 *sg_output_plane
++ = sample0
;
795 *sg_output_plane
++ = sample1
;
798 sg_output_plane
+= sg_line_inc
;
805 static int (*ipvideo_decode_block
[16])(void);
807 static void ipvideo_decode_opcodes(IpvideoContext
*s
)
811 unsigned char opcode
;
814 static int frame
= 0;
816 debug_interplay("------------------ frame %d\n", frame
);
819 for (x
= 0; x
< 16; x
++)
822 /* this is PAL8, so make the palette available */
823 if (s
->avctx
->pix_fmt
== PIX_FMT_PAL8
)
824 memcpy(s
->current_frame
.data
[1], s
->palette
, PALETTE_COUNT
* 4);
826 switch (s
->avctx
->pix_fmt
) {
829 sg_stride
= s
->current_frame
.linesize
[0];
830 sg_stream_ptr
= s
->buf
+ 14; /* data starts 14 bytes in */
831 sg_stream_end
= s
->buf
+ s
->size
;
832 sg_line_inc
= sg_stride
- 8;
833 sg_current_plane
= s
->current_frame
.data
[0];
834 sg_last_plane
= s
->last_frame
.data
[0];
835 sg_upper_motion_limit_offset
= (s
->avctx
->height
- 8) * sg_stride
836 + s
->avctx
->width
- 8;
839 for (y
= 0; y
< (sg_stride
* s
->avctx
->height
); y
+= sg_stride
* 8) {
840 for (x
= y
; x
< y
+ s
->avctx
->width
; x
+= 8) {
841 /* bottom nibble first, then top nibble (which makes it
842 * hard to use a GetBitcontext) */
844 opcode
= s
->decoding_map
[index
>> 1] >> 4;
846 opcode
= s
->decoding_map
[index
>> 1] & 0xF;
849 debug_interplay(" block @ (%3d, %3d): encoding 0x%X, data ptr @ %p\n",
850 x
- y
, y
/ sg_stride
, opcode
, sg_stream_ptr
);
851 code_counts
[opcode
]++;
853 sg_output_plane
= sg_current_plane
+ x
;
854 ret
= ipvideo_decode_block
[opcode
]();
856 printf(" Interplay video: decode problem on frame %d, @ block (%d, %d)\n",
857 frame
, x
- y
, y
/ sg_stride
);
862 if ((sg_stream_ptr
!= sg_stream_end
) &&
863 (sg_stream_ptr
+ 1 != sg_stream_end
)) {
864 printf (" Interplay video: decode finished with %d bytes left over\n",
865 sg_stream_end
- sg_stream_ptr
);
870 printf ("Interplay video: Unhandled video format\n");
876 static int ipvideo_decode_init(AVCodecContext
*avctx
)
878 IpvideoContext
*s
= avctx
->priv_data
;
882 if (s
->avctx
->extradata_size
!= sizeof(AVPaletteControl
)) {
883 printf (" Interplay video: expected extradata_size of %d\n",
884 sizeof(AVPaletteControl
));
888 avctx
->pix_fmt
= PIX_FMT_PAL8
;
889 avctx
->has_b_frames
= 0;
890 dsputil_init(&s
->dsp
, avctx
);
894 /* decoding map contains 4 bits of information per 8x8 block */
895 s
->decoding_map_size
= avctx
->width
* avctx
->height
/ (8 * 8 * 2);
897 /* assign block decode functions */
898 ipvideo_decode_block
[0x0] = ipvideo_decode_block_opcode_0x0_0x1
;
899 ipvideo_decode_block
[0x1] = ipvideo_decode_block_opcode_0x0_0x1
;
900 ipvideo_decode_block
[0x2] = ipvideo_decode_block_opcode_0x2
;
901 ipvideo_decode_block
[0x3] = ipvideo_decode_block_opcode_0x3
;
902 ipvideo_decode_block
[0x4] = ipvideo_decode_block_opcode_0x4
;
903 ipvideo_decode_block
[0x5] = ipvideo_decode_block_opcode_0x5
;
904 ipvideo_decode_block
[0x6] = ipvideo_decode_block_opcode_0x6
;
905 ipvideo_decode_block
[0x7] = ipvideo_decode_block_opcode_0x7
;
906 ipvideo_decode_block
[0x8] = ipvideo_decode_block_opcode_0x8
;
907 ipvideo_decode_block
[0x9] = ipvideo_decode_block_opcode_0x9
;
908 ipvideo_decode_block
[0xA] = ipvideo_decode_block_opcode_0xA
;
909 ipvideo_decode_block
[0xB] = ipvideo_decode_block_opcode_0xB
;
910 ipvideo_decode_block
[0xC] = ipvideo_decode_block_opcode_0xC
;
911 ipvideo_decode_block
[0xD] = ipvideo_decode_block_opcode_0xD
;
912 ipvideo_decode_block
[0xE] = ipvideo_decode_block_opcode_0xE
;
913 ipvideo_decode_block
[0xF] = ipvideo_decode_block_opcode_0xF
;
918 static int ipvideo_decode_frame(AVCodecContext
*avctx
,
919 void *data
, int *data_size
,
920 uint8_t *buf
, int buf_size
)
922 IpvideoContext
*s
= avctx
->priv_data
;
923 AVPaletteControl
*palette_control
= (AVPaletteControl
*)avctx
->extradata
;
925 if (palette_control
->palette_changed
) {
926 /* load the new palette and reset the palette control */
927 ipvideo_new_palette(s
, palette_control
->palette
);
928 palette_control
->palette_changed
= 0;
931 s
->decoding_map
= buf
;
932 s
->buf
= buf
+ s
->decoding_map_size
;
933 s
->size
= buf_size
- s
->decoding_map_size
;
935 if (avctx
->get_buffer(avctx
, &s
->current_frame
)) {
936 printf (" Interplay Video: get_buffer() failed\n");
940 ipvideo_decode_opcodes(s
);
942 /* release the last frame if it is allocated */
946 avctx
->release_buffer(avctx
, &s
->last_frame
);
949 s
->last_frame
= s
->current_frame
;
951 *data_size
= sizeof(AVFrame
);
952 *(AVFrame
*)data
= s
->current_frame
;
954 /* report that the buffer was completely consumed */
958 static int ipvideo_decode_end(AVCodecContext
*avctx
)
960 IpvideoContext
*s
= avctx
->priv_data
;
962 /* release the last frame */
963 avctx
->release_buffer(avctx
, &s
->last_frame
);
968 AVCodec interplay_video_decoder
= {
971 CODEC_ID_INTERPLAY_VIDEO
,
972 sizeof(IpvideoContext
),
976 ipvideo_decode_frame
,