2 * Wing Commander/Xan 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
23 * Xan video decoder for Wing Commander III & IV computer games
24 * by Mario Brito (mbrito@student.dei.uc.pt)
25 * and Mike Melanson (melanson@pcisys.net)
27 * The xan_wc3 decoder outputs the following colorspaces natively:
28 * PAL8 (default), RGB555, RGB565, RGB24, BGR24, RGBA32, YUV444P
40 #define PALETTE_COUNT 256
41 #define PALETTE_CONTROL_SIZE ((256 * 3) + 1)
43 typedef struct XanContext
{
45 AVCodecContext
*avctx
;
48 AVFrame current_frame
;
53 unsigned char palette
[PALETTE_COUNT
* 4];
56 unsigned char *buffer1
;
57 unsigned char *buffer2
;
61 /* RGB -> YUV conversion stuff */
62 #define SCALEFACTOR 65536
63 #define CENTERSAMPLE 128
65 #define COMPUTE_Y(r, g, b) \
67 ((y_r_table[r] + y_g_table[g] + y_b_table[b]) / SCALEFACTOR)
68 #define COMPUTE_U(r, g, b) \
70 ((u_r_table[r] + u_g_table[g] + u_b_table[b]) / SCALEFACTOR + CENTERSAMPLE)
71 #define COMPUTE_V(r, g, b) \
73 ((v_r_table[r] + v_g_table[g] + v_b_table[b]) / SCALEFACTOR + CENTERSAMPLE)
75 #define Y_R (SCALEFACTOR * 0.29900)
76 #define Y_G (SCALEFACTOR * 0.58700)
77 #define Y_B (SCALEFACTOR * 0.11400)
79 #define U_R (SCALEFACTOR * -0.16874)
80 #define U_G (SCALEFACTOR * -0.33126)
81 #define U_B (SCALEFACTOR * 0.50000)
83 #define V_R (SCALEFACTOR * 0.50000)
84 #define V_G (SCALEFACTOR * -0.41869)
85 #define V_B (SCALEFACTOR * -0.08131)
88 * Precalculate all of the YUV tables since it requires fewer than
89 * 10 kilobytes to store them.
91 static int y_r_table
[256];
92 static int y_g_table
[256];
93 static int y_b_table
[256];
95 static int u_r_table
[256];
96 static int u_g_table
[256];
97 static int u_b_table
[256];
99 static int v_r_table
[256];
100 static int v_g_table
[256];
101 static int v_b_table
[256];
103 static int xan_decode_init(AVCodecContext
*avctx
)
105 XanContext
*s
= avctx
->priv_data
;
110 if ((avctx
->codec
->id
== CODEC_ID_XAN_WC3
) &&
111 (s
->avctx
->palctrl
== NULL
)) {
112 av_log(avctx
, AV_LOG_ERROR
, " WC3 Xan video: palette expected.\n");
116 avctx
->pix_fmt
= PIX_FMT_PAL8
;
117 avctx
->has_b_frames
= 0;
118 dsputil_init(&s
->dsp
, avctx
);
120 /* initialize the RGB -> YUV tables */
121 for (i
= 0; i
< 256; i
++) {
122 y_r_table
[i
] = Y_R
* i
;
123 y_g_table
[i
] = Y_G
* i
;
124 y_b_table
[i
] = Y_B
* i
;
126 u_r_table
[i
] = U_R
* i
;
127 u_g_table
[i
] = U_G
* i
;
128 u_b_table
[i
] = U_B
* i
;
130 v_r_table
[i
] = V_R
* i
;
131 v_g_table
[i
] = V_G
* i
;
132 v_b_table
[i
] = V_B
* i
;
135 if(avcodec_check_dimensions(avctx
, avctx
->width
, avctx
->height
))
138 s
->buffer1
= av_malloc(avctx
->width
* avctx
->height
);
139 s
->buffer2
= av_malloc(avctx
->width
* avctx
->height
);
140 if (!s
->buffer1
|| !s
->buffer2
)
146 /* This function is used in lieu of memcpy(). This decoder can not use
147 * memcpy because the memory locations often overlap and
148 * memcpy doesn't like that; it's not uncommon, for example, for
149 * dest = src+1, to turn byte A into pattern AAAAAAAA.
150 * This was originally repz movsb in Intel x86 ASM. */
151 static inline void bytecopy(unsigned char *dest
, unsigned char *src
, int count
)
155 for (i
= 0; i
< count
; i
++)
159 static int xan_huffman_decode(unsigned char *dest
, unsigned char *src
)
161 unsigned char byte
= *src
++;
162 unsigned char ival
= byte
+ 0x16;
163 unsigned char * ptr
= src
+ byte
*2;
164 unsigned char val
= ival
;
167 unsigned char bits
= *ptr
++;
169 while ( val
!= 0x16 ) {
170 if ( (1 << counter
) & bits
)
171 val
= src
[byte
+ val
- 0x17];
173 val
= src
[val
- 0x17];
180 if (counter
++ == 7) {
189 static void xan_unpack(unsigned char *dest
, unsigned char *src
)
191 unsigned char opcode
;
194 int byte1
, byte2
, byte3
;
199 if ( (opcode
& 0x80) == 0 ) {
204 bytecopy(dest
, src
, size
); dest
+= size
; src
+= size
;
206 size
= ((opcode
& 0x1c) >> 2) + 3;
207 bytecopy (dest
, dest
- (((opcode
& 0x60) << 3) + offset
+ 1), size
);
210 } else if ( (opcode
& 0x40) == 0 ) {
216 bytecopy (dest
, src
, size
); dest
+= size
; src
+= size
;
218 size
= (opcode
& 0x3f) + 4;
219 bytecopy (dest
, dest
- (((byte1
& 0x3f) << 8) + byte2
+ 1), size
);
222 } else if ( (opcode
& 0x20) == 0 ) {
229 bytecopy (dest
, src
, size
); dest
+= size
; src
+= size
;
231 size
= byte3
+ 5 + ((opcode
& 0xc) << 6);
233 dest
- ((((opcode
& 0x10) >> 4) << 0x10) + 1 + (byte1
<< 8) + byte2
),
237 size
= ((opcode
& 0x1f) << 2) + 4;
242 bytecopy (dest
, src
, size
); dest
+= size
; src
+= size
;
247 bytecopy(dest
, src
, size
); dest
+= size
; src
+= size
;
250 static void inline xan_wc3_build_palette(XanContext
*s
,
251 unsigned int *palette_data
)
254 unsigned char r
, g
, b
;
255 unsigned short *palette16
;
256 unsigned int *palette32
;
257 unsigned int pal_elem
;
259 /* transform the palette passed through the palette control structure
260 * into the necessary internal format depending on colorspace */
262 switch (s
->avctx
->pix_fmt
) {
265 palette16
= (unsigned short *)s
->palette
;
266 for (i
= 0; i
< PALETTE_COUNT
; i
++) {
267 pal_elem
= palette_data
[i
];
268 r
= (pal_elem
>> 16) & 0xff;
269 g
= (pal_elem
>> 8) & 0xff;
279 palette16
= (unsigned short *)s
->palette
;
280 for (i
= 0; i
< PALETTE_COUNT
; i
++) {
281 pal_elem
= palette_data
[i
];
282 r
= (pal_elem
>> 16) & 0xff;
283 g
= (pal_elem
>> 8) & 0xff;
293 for (i
= 0; i
< PALETTE_COUNT
; i
++) {
294 pal_elem
= palette_data
[i
];
295 r
= (pal_elem
>> 16) & 0xff;
296 g
= (pal_elem
>> 8) & 0xff;
298 s
->palette
[i
* 4 + 0] = r
;
299 s
->palette
[i
* 4 + 1] = g
;
300 s
->palette
[i
* 4 + 2] = b
;
305 for (i
= 0; i
< PALETTE_COUNT
; i
++) {
306 pal_elem
= palette_data
[i
];
307 r
= (pal_elem
>> 16) & 0xff;
308 g
= (pal_elem
>> 8) & 0xff;
310 s
->palette
[i
* 4 + 0] = b
;
311 s
->palette
[i
* 4 + 1] = g
;
312 s
->palette
[i
* 4 + 2] = r
;
318 palette32
= (unsigned int *)s
->palette
;
319 memcpy (palette32
, palette_data
, PALETTE_COUNT
* sizeof(unsigned int));
322 case PIX_FMT_YUV444P
:
323 for (i
= 0; i
< PALETTE_COUNT
; i
++) {
324 pal_elem
= palette_data
[i
];
325 r
= (pal_elem
>> 16) & 0xff;
326 g
= (pal_elem
>> 8) & 0xff;
328 s
->palette
[i
* 4 + 0] = COMPUTE_Y(r
, g
, b
);
329 s
->palette
[i
* 4 + 1] = COMPUTE_U(r
, g
, b
);
330 s
->palette
[i
* 4 + 2] = COMPUTE_V(r
, g
, b
);
335 av_log(s
->avctx
, AV_LOG_ERROR
, " Xan WC3: Unhandled colorspace\n");
340 /* advance current_x variable; reset accounting variables if current_x
341 * moves beyond width */
342 #define ADVANCE_CURRENT_X() \
344 if (current_x >= width) { \
349 static void inline xan_wc3_output_pixel_run(XanContext
*s
,
350 unsigned char *pixel_buffer
, int x
, int y
, int pixel_count
)
356 int width
= s
->avctx
->width
;
358 unsigned char *palette_plane
;
359 unsigned char *y_plane
;
360 unsigned char *u_plane
;
361 unsigned char *v_plane
;
362 unsigned char *rgb_plane
;
363 unsigned short *rgb16_plane
;
364 unsigned short *palette16
;
365 unsigned int *rgb32_plane
;
366 unsigned int *palette32
;
368 switch (s
->avctx
->pix_fmt
) {
371 palette_plane
= s
->current_frame
.data
[0];
372 stride
= s
->current_frame
.linesize
[0];
373 line_inc
= stride
- width
;
374 index
= y
* stride
+ x
;
376 while(pixel_count
--) {
378 /* don't do a memcpy() here; keyframes generally copy an entire
379 * frame of data and the stride needs to be accounted for */
380 palette_plane
[index
++] = *pixel_buffer
++;
388 rgb16_plane
= (unsigned short *)s
->current_frame
.data
[0];
389 palette16
= (unsigned short *)s
->palette
;
390 stride
= s
->current_frame
.linesize
[0] / 2;
391 line_inc
= stride
- width
;
392 index
= y
* stride
+ x
;
394 while(pixel_count
--) {
396 rgb16_plane
[index
++] = palette16
[*pixel_buffer
++];
404 rgb_plane
= s
->current_frame
.data
[0];
405 stride
= s
->current_frame
.linesize
[0];
406 line_inc
= stride
- width
* 3;
407 index
= y
* stride
+ x
* 3;
409 while(pixel_count
--) {
410 pix
= *pixel_buffer
++;
412 rgb_plane
[index
++] = s
->palette
[pix
* 4 + 0];
413 rgb_plane
[index
++] = s
->palette
[pix
* 4 + 1];
414 rgb_plane
[index
++] = s
->palette
[pix
* 4 + 2];
421 rgb32_plane
= (unsigned int *)s
->current_frame
.data
[0];
422 palette32
= (unsigned int *)s
->palette
;
423 stride
= s
->current_frame
.linesize
[0] / 4;
424 line_inc
= stride
- width
;
425 index
= y
* stride
+ x
;
427 while(pixel_count
--) {
429 rgb32_plane
[index
++] = palette32
[*pixel_buffer
++];
435 case PIX_FMT_YUV444P
:
436 y_plane
= s
->current_frame
.data
[0];
437 u_plane
= s
->current_frame
.data
[1];
438 v_plane
= s
->current_frame
.data
[2];
439 stride
= s
->current_frame
.linesize
[0];
440 line_inc
= stride
- width
;
441 index
= y
* stride
+ x
;
443 while(pixel_count
--) {
444 pix
= *pixel_buffer
++;
446 y_plane
[index
] = s
->palette
[pix
* 4 + 0];
447 u_plane
[index
] = s
->palette
[pix
* 4 + 1];
448 v_plane
[index
] = s
->palette
[pix
* 4 + 2];
456 av_log(s
->avctx
, AV_LOG_ERROR
, " Xan WC3: Unhandled colorspace\n");
461 #define ADVANCE_CURFRAME_X() \
463 if (curframe_x >= width) { \
464 curframe_index += line_inc; \
468 #define ADVANCE_PREVFRAME_X() \
470 if (prevframe_x >= width) { \
471 prevframe_index += line_inc; \
475 static void inline xan_wc3_copy_pixel_run(XanContext
*s
,
476 int x
, int y
, int pixel_count
, int motion_x
, int motion_y
)
480 int curframe_index
, prevframe_index
;
481 int curframe_x
, prevframe_x
;
482 int width
= s
->avctx
->width
;
483 unsigned char *palette_plane
, *prev_palette_plane
;
484 unsigned char *y_plane
, *u_plane
, *v_plane
;
485 unsigned char *prev_y_plane
, *prev_u_plane
, *prev_v_plane
;
486 unsigned char *rgb_plane
, *prev_rgb_plane
;
487 unsigned short *rgb16_plane
, *prev_rgb16_plane
;
488 unsigned int *rgb32_plane
, *prev_rgb32_plane
;
490 switch (s
->avctx
->pix_fmt
) {
493 palette_plane
= s
->current_frame
.data
[0];
494 prev_palette_plane
= s
->last_frame
.data
[0];
495 stride
= s
->current_frame
.linesize
[0];
496 line_inc
= stride
- width
;
497 curframe_index
= y
* stride
+ x
;
499 prevframe_index
= (y
+ motion_y
) * stride
+ x
+ motion_x
;
500 prevframe_x
= x
+ motion_x
;
501 while(pixel_count
--) {
503 palette_plane
[curframe_index
++] =
504 prev_palette_plane
[prevframe_index
++];
506 ADVANCE_CURFRAME_X();
507 ADVANCE_PREVFRAME_X();
513 rgb16_plane
= (unsigned short *)s
->current_frame
.data
[0];
514 prev_rgb16_plane
= (unsigned short *)s
->last_frame
.data
[0];
515 stride
= s
->current_frame
.linesize
[0] / 2;
516 line_inc
= stride
- width
;
517 curframe_index
= y
* stride
+ x
;
519 prevframe_index
= (y
+ motion_y
) * stride
+ x
+ motion_x
;
520 prevframe_x
= x
+ motion_x
;
521 while(pixel_count
--) {
523 rgb16_plane
[curframe_index
++] =
524 prev_rgb16_plane
[prevframe_index
++];
526 ADVANCE_CURFRAME_X();
527 ADVANCE_PREVFRAME_X();
533 rgb_plane
= s
->current_frame
.data
[0];
534 prev_rgb_plane
= s
->last_frame
.data
[0];
535 stride
= s
->current_frame
.linesize
[0];
536 line_inc
= stride
- width
* 3;
537 curframe_index
= y
* stride
+ x
* 3;
539 prevframe_index
= (y
+ motion_y
) * stride
+
540 (3 * (x
+ motion_x
));
541 prevframe_x
= x
+ motion_x
;
542 while(pixel_count
--) {
544 rgb_plane
[curframe_index
++] = prev_rgb_plane
[prevframe_index
++];
545 rgb_plane
[curframe_index
++] = prev_rgb_plane
[prevframe_index
++];
546 rgb_plane
[curframe_index
++] = prev_rgb_plane
[prevframe_index
++];
548 ADVANCE_CURFRAME_X();
549 ADVANCE_PREVFRAME_X();
554 rgb32_plane
= (unsigned int *)s
->current_frame
.data
[0];
555 prev_rgb32_plane
= (unsigned int *)s
->last_frame
.data
[0];
556 stride
= s
->current_frame
.linesize
[0] / 4;
557 line_inc
= stride
- width
;
558 curframe_index
= y
* stride
+ x
;
560 prevframe_index
= (y
+ motion_y
) * stride
+ x
+ motion_x
;
561 prevframe_x
= x
+ motion_x
;
562 while(pixel_count
--) {
564 rgb32_plane
[curframe_index
++] =
565 prev_rgb32_plane
[prevframe_index
++];
567 ADVANCE_CURFRAME_X();
568 ADVANCE_PREVFRAME_X();
572 case PIX_FMT_YUV444P
:
573 y_plane
= s
->current_frame
.data
[0];
574 u_plane
= s
->current_frame
.data
[1];
575 v_plane
= s
->current_frame
.data
[2];
576 prev_y_plane
= s
->last_frame
.data
[0];
577 prev_u_plane
= s
->last_frame
.data
[1];
578 prev_v_plane
= s
->last_frame
.data
[2];
579 stride
= s
->current_frame
.linesize
[0];
580 line_inc
= stride
- width
;
581 curframe_index
= y
* stride
+ x
;
583 prevframe_index
= (y
+ motion_y
) * stride
+ x
+ motion_x
;
584 prevframe_x
= x
+ motion_x
;
585 while(pixel_count
--) {
587 y_plane
[curframe_index
] = prev_y_plane
[prevframe_index
];
588 u_plane
[curframe_index
] = prev_u_plane
[prevframe_index
];
589 v_plane
[curframe_index
] = prev_v_plane
[prevframe_index
];
592 ADVANCE_CURFRAME_X();
594 ADVANCE_PREVFRAME_X();
599 av_log(s
->avctx
, AV_LOG_ERROR
, " Xan WC3: Unhandled colorspace\n");
604 static void xan_wc3_decode_frame(XanContext
*s
) {
606 int width
= s
->avctx
->width
;
607 int height
= s
->avctx
->height
;
608 int total_pixels
= width
* height
;
609 unsigned char opcode
;
610 unsigned char flag
= 0;
612 int motion_x
, motion_y
;
615 unsigned char *opcode_buffer
= s
->buffer1
;
616 unsigned char *imagedata_buffer
= s
->buffer2
;
618 /* pointers to segments inside the compressed chunk */
619 unsigned char *huffman_segment
;
620 unsigned char *size_segment
;
621 unsigned char *vector_segment
;
622 unsigned char *imagedata_segment
;
624 huffman_segment
= s
->buf
+ LE_16(&s
->buf
[0]);
625 size_segment
= s
->buf
+ LE_16(&s
->buf
[2]);
626 vector_segment
= s
->buf
+ LE_16(&s
->buf
[4]);
627 imagedata_segment
= s
->buf
+ LE_16(&s
->buf
[6]);
629 xan_huffman_decode(opcode_buffer
, huffman_segment
);
631 if (imagedata_segment
[0] == 2)
632 xan_unpack(imagedata_buffer
, &imagedata_segment
[1]);
634 imagedata_buffer
= &imagedata_segment
[1];
636 /* use the decoded data segments to build the frame */
638 while (total_pixels
) {
640 opcode
= *opcode_buffer
++;
667 size
+= (opcode
- 10);
672 size
= *size_segment
++;
677 size
= BE_16(&size_segment
[0]);
683 size
= (size_segment
[0] << 16) | (size_segment
[1] << 8) |
692 /* run of (size) pixels is unchanged from last frame */
693 xan_wc3_copy_pixel_run(s
, x
, y
, size
, 0, 0);
695 /* output a run of pixels from imagedata_buffer */
696 xan_wc3_output_pixel_run(s
, imagedata_buffer
, x
, y
, size
);
697 imagedata_buffer
+= size
;
700 /* run-based motion compensation from last frame */
701 motion_x
= (*vector_segment
>> 4) & 0xF;
702 motion_y
= *vector_segment
& 0xF;
707 motion_x
|= 0xFFFFFFF0;
709 motion_y
|= 0xFFFFFFF0;
711 /* copy a run of pixels from the previous frame */
712 xan_wc3_copy_pixel_run(s
, x
, y
, size
, motion_x
, motion_y
);
717 /* coordinate accounting */
718 total_pixels
-= size
;
720 if (x
+ size
>= width
) {
731 /* for PAL8, make the palette available on the way out */
732 if (s
->avctx
->pix_fmt
== PIX_FMT_PAL8
) {
733 memcpy(s
->current_frame
.data
[1], s
->palette
, PALETTE_COUNT
* 4);
734 s
->current_frame
.palette_has_changed
= 1;
735 s
->avctx
->palctrl
->palette_changed
= 0;
739 static void xan_wc4_decode_frame(XanContext
*s
) {
742 static int xan_decode_frame(AVCodecContext
*avctx
,
743 void *data
, int *data_size
,
744 uint8_t *buf
, int buf_size
)
746 XanContext
*s
= avctx
->priv_data
;
747 AVPaletteControl
*palette_control
= avctx
->palctrl
;
750 if (palette_control
->palette_changed
) {
751 /* load the new palette and reset the palette control */
752 xan_wc3_build_palette(s
, palette_control
->palette
);
753 /* If pal8 we clear flag when we copy palette */
754 if (s
->avctx
->pix_fmt
!= PIX_FMT_PAL8
)
755 palette_control
->palette_changed
= 0;
759 if (avctx
->get_buffer(avctx
, &s
->current_frame
)) {
760 av_log(s
->avctx
, AV_LOG_ERROR
, " Xan Video: get_buffer() failed\n");
763 s
->current_frame
.reference
= 3;
768 if (avctx
->codec
->id
== CODEC_ID_XAN_WC3
)
769 xan_wc3_decode_frame(s
);
770 else if (avctx
->codec
->id
== CODEC_ID_XAN_WC4
)
771 xan_wc4_decode_frame(s
);
773 /* release the last frame if it is allocated */
774 if (s
->last_frame
.data
[0])
775 avctx
->release_buffer(avctx
, &s
->last_frame
);
778 s
->last_frame
= s
->current_frame
;
780 *data_size
= sizeof(AVFrame
);
781 *(AVFrame
*)data
= s
->current_frame
;
783 /* always report that the buffer was completely consumed */
787 static int xan_decode_end(AVCodecContext
*avctx
)
789 XanContext
*s
= avctx
->priv_data
;
791 /* release the last frame */
792 avctx
->release_buffer(avctx
, &s
->last_frame
);
800 AVCodec xan_wc3_decoder
= {
813 AVCodec xan_wc4_decoder = {