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
#define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
62
#define LE_16(x) ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
63
#define LE_32(x) ((((uint8_t*)(x))[3] << 24) | \
64
(((uint8_t*)(x))[2] << 16) | \
65
(((uint8_t*)(x))[1] << 8) | \
68
/* RGB -> YUV conversion stuff */
69
#define SCALEFACTOR 65536
70
#define CENTERSAMPLE 128
72
#define COMPUTE_Y(r, g, b) \
74
((y_r_table[r] + y_g_table[g] + y_b_table[b]) / SCALEFACTOR)
75
#define COMPUTE_U(r, g, b) \
77
((u_r_table[r] + u_g_table[g] + u_b_table[b]) / SCALEFACTOR + CENTERSAMPLE)
78
#define COMPUTE_V(r, g, b) \
80
((v_r_table[r] + v_g_table[g] + v_b_table[b]) / SCALEFACTOR + CENTERSAMPLE)
82
#define Y_R (SCALEFACTOR * 0.29900)
83
#define Y_G (SCALEFACTOR * 0.58700)
84
#define Y_B (SCALEFACTOR * 0.11400)
86
#define U_R (SCALEFACTOR * -0.16874)
87
#define U_G (SCALEFACTOR * -0.33126)
88
#define U_B (SCALEFACTOR * 0.50000)
90
#define V_R (SCALEFACTOR * 0.50000)
91
#define V_G (SCALEFACTOR * -0.41869)
92
#define V_B (SCALEFACTOR * -0.08131)
95
* Precalculate all of the YUV tables since it requires fewer than
96
* 10 kilobytes to store them.
98
static int y_r_table[256];
99
static int y_g_table[256];
100
static int y_b_table[256];
102
static int u_r_table[256];
103
static int u_g_table[256];
104
static int u_b_table[256];
106
static int v_r_table[256];
107
static int v_g_table[256];
108
static int v_b_table[256];
110
static int xan_decode_init(AVCodecContext *avctx)
112
XanContext *s = avctx->priv_data;
117
if ((avctx->codec->id == CODEC_ID_XAN_WC3) &&
118
(s->avctx->extradata_size != sizeof(AVPaletteControl))) {
119
printf (" WC3 Xan video: expected extradata_size of %d\n",
120
sizeof(AVPaletteControl));
124
avctx->pix_fmt = PIX_FMT_PAL8;
125
avctx->has_b_frames = 0;
126
dsputil_init(&s->dsp, avctx);
128
/* initialize the RGB -> YUV tables */
129
for (i = 0; i < 256; i++) {
130
y_r_table[i] = Y_R * i;
131
y_g_table[i] = Y_G * i;
132
y_b_table[i] = Y_B * i;
134
u_r_table[i] = U_R * i;
135
u_g_table[i] = U_G * i;
136
u_b_table[i] = U_B * i;
138
v_r_table[i] = V_R * i;
139
v_g_table[i] = V_G * i;
140
v_b_table[i] = V_B * i;
143
s->buffer1 = av_malloc(avctx->width * avctx->height);
144
s->buffer2 = av_malloc(avctx->width * avctx->height);
145
if (!s->buffer1 || !s->buffer2)
151
/* This function is used in lieu of memcpy(). This decoder can not use
152
* memcpy because the memory locations often overlap and
153
* memcpy doesn't like that; it's not uncommon, for example, for
154
* dest = src+1, to turn byte A into pattern AAAAAAAA.
155
* This was originally repz movsb in Intel x86 ASM. */
156
static inline void bytecopy(unsigned char *dest, unsigned char *src, int count)
160
for (i = 0; i < count; i++)
164
static int xan_huffman_decode(unsigned char *dest, unsigned char *src)
166
unsigned char byte = *src++;
167
unsigned char ival = byte + 0x16;
168
unsigned char * ptr = src + byte*2;
169
unsigned char val = ival;
172
unsigned char bits = *ptr++;
174
while ( val != 0x16 ) {
175
if ( (1 << counter) & bits )
176
val = src[byte + val - 0x17];
178
val = src[val - 0x17];
185
if (counter++ == 7) {
194
static void xan_unpack(unsigned char *dest, unsigned char *src)
196
unsigned char opcode;
199
int byte1, byte2, byte3;
204
if ( (opcode & 0x80) == 0 ) {
209
bytecopy(dest, src, size); dest += size; src += size;
211
size = ((opcode & 0x1c) >> 2) + 3;
212
bytecopy (dest, dest - (((opcode & 0x60) << 3) + offset + 1), size);
215
} else if ( (opcode & 0x40) == 0 ) {
221
bytecopy (dest, src, size); dest += size; src += size;
223
size = (opcode & 0x3f) + 4;
224
bytecopy (dest, dest - (((byte1 & 0x3f) << 8) + byte2 + 1), size);
227
} else if ( (opcode & 0x20) == 0 ) {
234
bytecopy (dest, src, size); dest += size; src += size;
236
size = byte3 + 5 + ((opcode & 0xc) << 6);
238
dest - ((((opcode & 0x10) >> 4) << 0x10) + 1 + (byte1 << 8) + byte2),
242
size = ((opcode & 0x1f) << 2) + 4;
247
bytecopy (dest, src, size); dest += size; src += size;
252
bytecopy(dest, src, size); dest += size; src += size;
255
static void inline xan_wc3_build_palette(XanContext *s,
256
unsigned char *palette_data)
259
unsigned char r, g, b;
260
unsigned short *palette16;
261
unsigned int *palette32;
263
/* transform the palette passed through the palette control structure
264
* into the necessary internal format depending on colorspace */
266
switch (s->avctx->pix_fmt) {
269
palette16 = (unsigned short *)s->palette;
270
for (i = 0; i < PALETTE_COUNT; i++) {
282
palette16 = (unsigned short *)s->palette;
283
for (i = 0; i < PALETTE_COUNT; i++) {
295
for (i = 0; i < PALETTE_COUNT; i++) {
296
s->palette[i * 4 + 0] = *palette_data++;
297
s->palette[i * 4 + 1] = *palette_data++;
298
s->palette[i * 4 + 2] = *palette_data++;
303
for (i = 0; i < PALETTE_COUNT; i++) {
307
s->palette[i * 4 + 0] = b;
308
s->palette[i * 4 + 1] = g;
309
s->palette[i * 4 + 2] = r;
315
palette32 = (unsigned int *)s->palette;
316
for (i = 0; i < PALETTE_COUNT; i++) {
320
palette32[i] = (r << 16) | (g << 8) | (b);
324
case PIX_FMT_YUV444P:
325
for (i = 0; i < PALETTE_COUNT; i++) {
329
s->palette[i * 4 + 0] = COMPUTE_Y(r, g, b);
330
s->palette[i * 4 + 1] = COMPUTE_U(r, g, b);
331
s->palette[i * 4 + 2] = COMPUTE_V(r, g, b);
336
printf (" Xan WC3: Unhandled colorspace\n");
341
/* advance current_x variable; reset accounting variables if current_x
342
* moves beyond width */
343
#define ADVANCE_CURRENT_X() \
345
if (current_x >= width) { \
350
static void inline xan_wc3_output_pixel_run(XanContext *s,
351
unsigned char *pixel_buffer, int x, int y, int pixel_count)
357
int width = s->avctx->width;
359
unsigned char *palette_plane;
360
unsigned char *y_plane;
361
unsigned char *u_plane;
362
unsigned char *v_plane;
363
unsigned char *rgb_plane;
364
unsigned short *rgb16_plane;
365
unsigned short *palette16;
366
unsigned int *rgb32_plane;
367
unsigned int *palette32;
369
switch (s->avctx->pix_fmt) {
372
palette_plane = s->current_frame.data[0];
373
stride = s->current_frame.linesize[0];
374
line_inc = stride - width;
375
index = y * stride + x;
377
while(pixel_count--) {
379
/* don't do a memcpy() here; keyframes generally copy an entire
380
* frame of data and the stride needs to be accounted for */
381
palette_plane[index++] = *pixel_buffer++;
389
rgb16_plane = (unsigned short *)s->current_frame.data[0];
390
palette16 = (unsigned short *)s->palette;
391
stride = s->current_frame.linesize[0] / 2;
392
line_inc = stride - width;
393
index = y * stride + x;
395
while(pixel_count--) {
397
rgb16_plane[index++] = palette16[*pixel_buffer++];
405
rgb_plane = s->current_frame.data[0];
406
stride = s->current_frame.linesize[0];
407
line_inc = stride - width * 3;
408
index = y * stride + x * 3;
410
while(pixel_count--) {
411
pix = *pixel_buffer++;
413
rgb_plane[index++] = s->palette[pix * 4 + 0];
414
rgb_plane[index++] = s->palette[pix * 4 + 1];
415
rgb_plane[index++] = s->palette[pix * 4 + 2];
422
rgb32_plane = (unsigned int *)s->current_frame.data[0];
423
palette32 = (unsigned int *)s->palette;
424
stride = s->current_frame.linesize[0] / 4;
425
line_inc = stride - width;
426
index = y * stride + x;
428
while(pixel_count--) {
430
rgb32_plane[index++] = palette32[*pixel_buffer++];
436
case PIX_FMT_YUV444P:
437
y_plane = s->current_frame.data[0];
438
u_plane = s->current_frame.data[1];
439
v_plane = s->current_frame.data[2];
440
stride = s->current_frame.linesize[0];
441
line_inc = stride - width;
442
index = y * stride + x;
444
while(pixel_count--) {
445
pix = *pixel_buffer++;
447
y_plane[index] = s->palette[pix * 4 + 0];
448
u_plane[index] = s->palette[pix * 4 + 1];
449
v_plane[index] = s->palette[pix * 4 + 2];
457
printf (" Xan WC3: Unhandled colorspace\n");
462
#define ADVANCE_CURFRAME_X() \
464
if (curframe_x >= width) { \
465
curframe_index += line_inc; \
469
#define ADVANCE_PREVFRAME_X() \
471
if (prevframe_x >= width) { \
472
prevframe_index += line_inc; \
476
static void inline xan_wc3_copy_pixel_run(XanContext *s,
477
int x, int y, int pixel_count, int motion_x, int motion_y)
481
int curframe_index, prevframe_index;
482
int curframe_x, prevframe_x;
483
int width = s->avctx->width;
484
unsigned char *palette_plane, *prev_palette_plane;
485
unsigned char *y_plane, *u_plane, *v_plane;
486
unsigned char *prev_y_plane, *prev_u_plane, *prev_v_plane;
487
unsigned char *rgb_plane, *prev_rgb_plane;
488
unsigned short *rgb16_plane, *prev_rgb16_plane;
489
unsigned int *rgb32_plane, *prev_rgb32_plane;
491
switch (s->avctx->pix_fmt) {
494
palette_plane = s->current_frame.data[0];
495
prev_palette_plane = s->last_frame.data[0];
496
stride = s->current_frame.linesize[0];
497
line_inc = stride - width;
498
curframe_index = y * stride + x;
500
prevframe_index = (y + motion_y) * stride + x + motion_x;
501
prevframe_x = x + motion_x;
502
while(pixel_count--) {
504
palette_plane[curframe_index++] =
505
prev_palette_plane[prevframe_index++];
507
ADVANCE_CURFRAME_X();
508
ADVANCE_PREVFRAME_X();
514
rgb16_plane = (unsigned short *)s->current_frame.data[0];
515
prev_rgb16_plane = (unsigned short *)s->last_frame.data[0];
516
stride = s->current_frame.linesize[0] / 2;
517
line_inc = stride - width;
518
curframe_index = y * stride + x;
520
prevframe_index = (y + motion_y) * stride + x + motion_x;
521
prevframe_x = x + motion_x;
522
while(pixel_count--) {
524
rgb16_plane[curframe_index++] =
525
prev_rgb16_plane[prevframe_index++];
527
ADVANCE_CURFRAME_X();
528
ADVANCE_PREVFRAME_X();
534
rgb_plane = s->current_frame.data[0];
535
prev_rgb_plane = s->last_frame.data[0];
536
stride = s->current_frame.linesize[0];
537
line_inc = stride - width * 3;
538
curframe_index = y * stride + x * 3;
540
prevframe_index = (y + motion_y) * stride +
541
(3 * (x + motion_x));
542
prevframe_x = x + motion_x;
543
while(pixel_count--) {
545
rgb_plane[curframe_index++] = prev_rgb_plane[prevframe_index++];
546
rgb_plane[curframe_index++] = prev_rgb_plane[prevframe_index++];
547
rgb_plane[curframe_index++] = prev_rgb_plane[prevframe_index++];
549
ADVANCE_CURFRAME_X();
550
ADVANCE_PREVFRAME_X();
555
rgb32_plane = (unsigned int *)s->current_frame.data[0];
556
prev_rgb32_plane = (unsigned int *)s->last_frame.data[0];
557
stride = s->current_frame.linesize[0] / 4;
558
line_inc = stride - width;
559
curframe_index = y * stride + x;
561
prevframe_index = (y + motion_y) * stride + x + motion_x;
562
prevframe_x = x + motion_x;
563
while(pixel_count--) {
565
rgb32_plane[curframe_index++] =
566
prev_rgb32_plane[prevframe_index++];
568
ADVANCE_CURFRAME_X();
569
ADVANCE_PREVFRAME_X();
573
case PIX_FMT_YUV444P:
574
y_plane = s->current_frame.data[0];
575
u_plane = s->current_frame.data[1];
576
v_plane = s->current_frame.data[2];
577
prev_y_plane = s->last_frame.data[0];
578
prev_u_plane = s->last_frame.data[1];
579
prev_v_plane = s->last_frame.data[2];
580
stride = s->current_frame.linesize[0];
581
line_inc = stride - width;
582
curframe_index = y * stride + x;
584
prevframe_index = (y + motion_y) * stride + x + motion_x;
585
prevframe_x = x + motion_x;
586
while(pixel_count--) {
588
y_plane[curframe_index] = prev_y_plane[prevframe_index];
589
u_plane[curframe_index] = prev_u_plane[prevframe_index];
590
v_plane[curframe_index] = prev_v_plane[prevframe_index];
593
ADVANCE_CURFRAME_X();
595
ADVANCE_PREVFRAME_X();
600
printf (" Xan WC3: Unhandled colorspace\n");
605
static void xan_wc3_decode_frame(XanContext *s) {
607
int width = s->avctx->width;
608
int height = s->avctx->height;
609
int total_pixels = width * height;
610
unsigned char opcode;
611
unsigned char flag = 0;
613
int motion_x, motion_y;
616
unsigned char *opcode_buffer = s->buffer1;
617
unsigned char *imagedata_buffer = s->buffer2;
619
/* pointers to segments inside the compressed chunk */
620
unsigned char *huffman_segment;
621
unsigned char *size_segment;
622
unsigned char *vector_segment;
623
unsigned char *imagedata_segment;
625
huffman_segment = s->buf + LE_16(&s->buf[0]);
626
size_segment = s->buf + LE_16(&s->buf[2]);
627
vector_segment = s->buf + LE_16(&s->buf[4]);
628
imagedata_segment = s->buf + LE_16(&s->buf[6]);
630
xan_huffman_decode(opcode_buffer, huffman_segment);
632
if (imagedata_segment[0] == 2)
633
xan_unpack(imagedata_buffer, &imagedata_segment[1]);
635
imagedata_buffer = &imagedata_segment[1];
637
/* use the decoded data segments to build the frame */
639
while (total_pixels) {
641
opcode = *opcode_buffer++;
668
size += (opcode - 10);
673
size = *size_segment++;
678
size = BE_16(&size_segment[0]);
684
size = (size_segment[0] << 16) | (size_segment[1] << 8) |
693
/* run of (size) pixels is unchanged from last frame */
694
xan_wc3_copy_pixel_run(s, x, y, size, 0, 0);
696
/* output a run of pixels from imagedata_buffer */
697
xan_wc3_output_pixel_run(s, imagedata_buffer, x, y, size);
698
imagedata_buffer += size;
701
/* run-based motion compensation from last frame */
702
motion_x = (*vector_segment >> 4) & 0xF;
703
motion_y = *vector_segment & 0xF;
708
motion_x |= 0xFFFFFFF0;
710
motion_y |= 0xFFFFFFF0;
712
/* copy a run of pixels from the previous frame */
713
xan_wc3_copy_pixel_run(s, x, y, size, motion_x, motion_y);
718
/* coordinate accounting */
719
total_pixels -= size;
721
if (x + size >= width) {
732
/* for PAL8, make the palette available on the way out */
733
if (s->avctx->pix_fmt == PIX_FMT_PAL8)
734
memcpy(s->current_frame.data[1], s->palette, PALETTE_COUNT * 4);
737
static void xan_wc4_decode_frame(XanContext *s) {
740
static int xan_decode_frame(AVCodecContext *avctx,
741
void *data, int *data_size,
742
uint8_t *buf, int buf_size)
744
XanContext *s = avctx->priv_data;
745
AVPaletteControl *palette_control = (AVPaletteControl *)avctx->extradata;
748
if (palette_control->palette_changed) {
749
/* load the new palette and reset the palette control */
750
xan_wc3_build_palette(s, palette_control->palette);
751
palette_control->palette_changed = 0;
755
if (avctx->get_buffer(avctx, &s->current_frame)) {
756
printf (" Xan Video: get_buffer() failed\n");
759
s->current_frame.reference = 3;
764
if (avctx->codec->id == CODEC_ID_XAN_WC3)
765
xan_wc3_decode_frame(s);
766
else if (avctx->codec->id == CODEC_ID_XAN_WC4)
767
xan_wc4_decode_frame(s);
769
/* release the last frame if it is allocated */
770
if (s->last_frame.data[0])
771
avctx->release_buffer(avctx, &s->last_frame);
774
s->last_frame = s->current_frame;
776
*data_size = sizeof(AVFrame);
777
*(AVFrame*)data = s->current_frame;
779
/* always report that the buffer was completely consumed */
783
static int xan_decode_end(AVCodecContext *avctx)
785
XanContext *s = avctx->priv_data;
787
/* release the last frame */
788
avctx->release_buffer(avctx, &s->last_frame);
796
AVCodec xan_wc3_decoder = {
809
AVCodec xan_wc4_decoder = {