]> git.sesse.net Git - ffmpeg/blob - libavcodec/xan.c
e2e3e56e4143007ce81a26f739709c9f6e45a705
[ffmpeg] / libavcodec / xan.c
1 /*
2  * Wing Commander/Xan Video Decoder
3  * Copyright (C) 2003 the ffmpeg project
4  *
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.
9  *
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.
14  *
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
18  *
19  */
20
21 /**
22  * @file xan.c
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)
26  *
27  * The xan_wc3 decoder outputs the following colorspaces natively:
28  *   PAL8 (default), RGB555, RGB565, RGB24, BGR24, RGBA32, YUV444P
29  */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35
36 #include "common.h"
37 #include "avcodec.h"
38 #include "dsputil.h"
39
40 #define PALETTE_COUNT 256
41 #define PALETTE_CONTROL_SIZE ((256 * 3) + 1)
42
43 typedef struct XanContext {
44
45     AVCodecContext *avctx;
46     DSPContext dsp;
47     AVFrame last_frame;
48     AVFrame current_frame;
49
50     unsigned char *buf;
51     int size;
52
53     unsigned char palette[PALETTE_COUNT * 4];
54
55     /* scratch space */
56     unsigned char *buffer1;
57     unsigned char *buffer2;
58
59 } XanContext;
60
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) | \
66                     ((uint8_t*)(x))[0])
67
68 /* RGB -> YUV conversion stuff */
69 #define SCALEFACTOR 65536
70 #define CENTERSAMPLE 128
71
72 #define COMPUTE_Y(r, g, b) \
73   (unsigned char) \
74   ((y_r_table[r] + y_g_table[g] + y_b_table[b]) / SCALEFACTOR)
75 #define COMPUTE_U(r, g, b) \
76   (unsigned char) \
77   ((u_r_table[r] + u_g_table[g] + u_b_table[b]) / SCALEFACTOR + CENTERSAMPLE)
78 #define COMPUTE_V(r, g, b) \
79   (unsigned char) \
80   ((v_r_table[r] + v_g_table[g] + v_b_table[b]) / SCALEFACTOR + CENTERSAMPLE)
81
82 #define Y_R (SCALEFACTOR *  0.29900)
83 #define Y_G (SCALEFACTOR *  0.58700)
84 #define Y_B (SCALEFACTOR *  0.11400)
85
86 #define U_R (SCALEFACTOR * -0.16874)
87 #define U_G (SCALEFACTOR * -0.33126)
88 #define U_B (SCALEFACTOR *  0.50000)
89
90 #define V_R (SCALEFACTOR *  0.50000)
91 #define V_G (SCALEFACTOR * -0.41869)
92 #define V_B (SCALEFACTOR * -0.08131)
93
94 /*
95  * Precalculate all of the YUV tables since it requires fewer than
96  * 10 kilobytes to store them.
97  */
98 static int y_r_table[256];
99 static int y_g_table[256];
100 static int y_b_table[256];
101
102 static int u_r_table[256];
103 static int u_g_table[256];
104 static int u_b_table[256];
105
106 static int v_r_table[256];
107 static int v_g_table[256];
108 static int v_b_table[256];
109
110 static int xan_decode_init(AVCodecContext *avctx)
111 {
112     XanContext *s = avctx->priv_data;
113     int i;
114
115     s->avctx = avctx;
116
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));
121         return -1;
122     }
123
124     avctx->pix_fmt = PIX_FMT_PAL8;
125     avctx->has_b_frames = 0;
126     dsputil_init(&s->dsp, avctx);
127
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;
133
134         u_r_table[i] = U_R * i;
135         u_g_table[i] = U_G * i;
136         u_b_table[i] = U_B * i;
137
138         v_r_table[i] = V_R * i;
139         v_g_table[i] = V_G * i;
140         v_b_table[i] = V_B * i;
141     }
142
143     s->buffer1 = av_malloc(avctx->width * avctx->height);
144     s->buffer2 = av_malloc(avctx->width * avctx->height);
145     if (!s->buffer1 || !s->buffer2)
146         return -1;
147
148     return 0;
149 }
150
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)
157 {
158     int i;
159
160     for (i = 0; i < count; i++)
161         dest[i] = src[i];
162 }
163
164 static int xan_huffman_decode(unsigned char *dest, unsigned char *src)
165 {
166     unsigned char byte = *src++;
167     unsigned char ival = byte + 0x16;
168     unsigned char * ptr = src + byte*2;
169     unsigned char val = ival;
170     int counter = 0;
171
172     unsigned char bits = *ptr++;
173
174     while ( val != 0x16 ) {
175         if ( (1 << counter) & bits )
176             val = src[byte + val - 0x17];
177         else
178             val = src[val - 0x17];
179
180         if ( val < 0x16 ) {
181             *dest++ = val;
182             val = ival;
183         }
184
185         if (counter++ == 7) {
186             counter = 0;
187             bits = *ptr++;
188         }
189     }
190
191     return 0;
192 }
193
194 static void xan_unpack(unsigned char *dest, unsigned char *src)
195 {
196     unsigned char opcode;
197     int size;
198     int offset;
199     int byte1, byte2, byte3;
200
201     for (;;) {
202         opcode = *src++;
203
204         if ( (opcode & 0x80) == 0 ) {
205
206             offset = *src++;
207
208             size = opcode & 3;
209             bytecopy(dest, src, size);  dest += size;  src += size;
210
211             size = ((opcode & 0x1c) >> 2) + 3;
212             bytecopy (dest, dest - (((opcode & 0x60) << 3) + offset + 1), size);
213             dest += size;
214
215         } else if ( (opcode & 0x40) == 0 ) {
216
217             byte1 = *src++;
218             byte2 = *src++;
219
220             size = byte1 >> 6;
221             bytecopy (dest, src, size);  dest += size;  src += size;
222
223             size = (opcode & 0x3f) + 4;
224             bytecopy (dest, dest - (((byte1 & 0x3f) << 8) + byte2 + 1), size);
225             dest += size;
226
227         } else if ( (opcode & 0x20) == 0 ) {
228
229             byte1 = *src++;
230             byte2 = *src++;
231             byte3 = *src++;
232
233             size = opcode & 3;
234             bytecopy (dest, src, size);  dest += size;  src += size;
235
236             size = byte3 + 5 + ((opcode & 0xc) << 6);
237             bytecopy (dest,
238                 dest - ((((opcode & 0x10) >> 4) << 0x10) + 1 + (byte1 << 8) + byte2),
239                 size);
240             dest += size;
241         } else {
242             size = ((opcode & 0x1f) << 2) + 4;
243
244             if (size > 0x70)
245                 break;
246
247             bytecopy (dest, src, size);  dest += size;  src += size;
248         }
249     }
250
251     size = opcode & 3;
252     bytecopy(dest, src, size);  dest += size;  src += size;
253 }
254
255 static void inline xan_wc3_build_palette(XanContext *s, 
256     unsigned char *palette_data)
257 {
258     int i;
259     unsigned char r, g, b;
260     unsigned short *palette16;
261     unsigned int *palette32;
262
263     /* transform the palette passed through the palette control structure
264      * into the necessary internal format depending on colorspace */
265
266     switch (s->avctx->pix_fmt) {
267
268     case PIX_FMT_RGB555:
269         palette16 = (unsigned short *)s->palette;
270         for (i = 0; i < PALETTE_COUNT; i++) {
271             r = *palette_data++;
272             g = *palette_data++;
273             b = *palette_data++;
274             palette16[i] = 
275                 ((r >> 3) << 10) |
276                 ((g >> 3) <<  5) |
277                 ((g >> 3) <<  0);
278         }
279         break;
280
281     case PIX_FMT_RGB565:
282         palette16 = (unsigned short *)s->palette;
283         for (i = 0; i < PALETTE_COUNT; i++) {
284             r = *palette_data++;
285             g = *palette_data++;
286             b = *palette_data++;
287             palette16[i] = 
288                 ((r >> 3) << 11) |
289                 ((g >> 2) <<  5) |
290                 ((g >> 3) <<  0);
291         }
292         break;
293
294     case PIX_FMT_RGB24:
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++;
299         }
300         break;
301
302     case PIX_FMT_BGR24:
303         for (i = 0; i < PALETTE_COUNT; i++) {
304             r = *palette_data++;
305             g = *palette_data++;
306             b = *palette_data++;
307             s->palette[i * 4 + 0] = b;
308             s->palette[i * 4 + 1] = g;
309             s->palette[i * 4 + 2] = r;
310         }
311         break;
312
313     case PIX_FMT_PAL8:
314     case PIX_FMT_RGBA32:
315         palette32 = (unsigned int *)s->palette;
316         for (i = 0; i < PALETTE_COUNT; i++) {
317             r = *palette_data++;
318             g = *palette_data++;
319             b = *palette_data++;
320             palette32[i] = (r << 16) | (g << 8) | (b);
321         }
322         break;
323
324     case PIX_FMT_YUV444P:
325         for (i = 0; i < PALETTE_COUNT; i++) {
326             r = *palette_data++;
327             g = *palette_data++;
328             b = *palette_data++;
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);
332         }
333         break;
334
335     default:
336         printf (" Xan WC3: Unhandled colorspace\n");
337         break;
338     }
339 }
340
341 static void inline xan_wc3_output_pixel_run(XanContext *s, 
342     unsigned char *pixel_buffer, int x, int y, int pixel_count)
343 {
344     int stride;
345     int line_inc;
346     int index;
347     int current_x;
348     int width = s->avctx->width;
349     unsigned char pixel;
350     unsigned char *palette_plane;
351     unsigned char *y_plane;
352     unsigned char *u_plane;
353     unsigned char *v_plane;
354     unsigned char *rgb_plane;
355     unsigned short *rgb16_plane;
356     unsigned short *palette16;
357     unsigned int *rgb32_plane;
358     unsigned int *palette32;
359
360     switch (s->avctx->pix_fmt) {
361
362     case PIX_FMT_PAL8:
363         palette_plane = s->current_frame.data[0];
364         stride = s->current_frame.linesize[0];
365         line_inc = stride - width;
366         index = y * stride + x;
367         current_x = x;
368         while(pixel_count--) {
369
370             /* don't do a memcpy() here; keyframes generally copy an entire
371              * frame of data and the stride needs to be accounted for */
372             palette_plane[index++] = *pixel_buffer++;
373
374             current_x++;
375             if (current_x >= width) {
376                 /* reset accounting variables */
377                 index += line_inc;
378                 current_x = 0;
379             }
380         }
381         break;
382
383     case PIX_FMT_RGB555:
384     case PIX_FMT_RGB565:
385         rgb16_plane = (unsigned short *)s->current_frame.data[0];
386         palette16 = (unsigned short *)s->palette;
387         stride = s->current_frame.linesize[0] / 2;
388         line_inc = stride - width;
389         index = y * stride + x;
390         current_x = x;
391         while(pixel_count--) {
392
393             rgb16_plane[index++] = palette16[*pixel_buffer++];
394
395             current_x++;
396             if (current_x >= width) {
397                 /* reset accounting variables */
398                 index += line_inc;
399                 current_x = 0;
400             }
401         }
402         break;
403
404     case PIX_FMT_RGB24:
405     case PIX_FMT_BGR24:
406         rgb_plane = s->current_frame.data[0];
407         stride = s->current_frame.linesize[0];
408         line_inc = stride - width * 3;
409         index = y * stride + x * 3;
410         current_x = x;
411         while(pixel_count--) {
412             pixel = *pixel_buffer++;
413
414             rgb_plane[index++] = s->palette[pixel * 4 + 0];
415             rgb_plane[index++] = s->palette[pixel * 4 + 1];
416             rgb_plane[index++] = s->palette[pixel * 4 + 2];
417
418             current_x++;
419             if (current_x >= width) {
420                 /* reset accounting variables */
421                 index += line_inc;
422                 current_x = 0;
423             }
424         }
425         break;
426
427     case PIX_FMT_RGBA32:
428         rgb32_plane = (unsigned int *)s->current_frame.data[0];
429         palette32 = (unsigned int *)s->palette;
430         stride = s->current_frame.linesize[0] / 4;
431         line_inc = stride - width;
432         index = y * stride + x;
433         current_x = x;
434         while(pixel_count--) {
435
436             rgb32_plane[index++] = palette32[*pixel_buffer++];
437
438             current_x++;
439             if (current_x >= width) {
440                 /* reset accounting variables */
441                 index += line_inc;
442                 current_x = 0;
443             }
444         }
445         break;
446
447     case PIX_FMT_YUV444P:
448         y_plane = s->current_frame.data[0];
449         u_plane = s->current_frame.data[1];
450         v_plane = s->current_frame.data[2];
451         stride = s->current_frame.linesize[0];
452         line_inc = stride - width;
453         index = y * stride + x;
454         current_x = x;
455         while(pixel_count--) {
456             pixel = *pixel_buffer++;
457
458             y_plane[index] = s->palette[pixel * 4 + 0];
459             u_plane[index] = s->palette[pixel * 4 + 1];
460             v_plane[index] = s->palette[pixel * 4 + 2];
461
462             index++;
463             current_x++;
464             if (current_x >= width) {
465                 /* reset accounting variables */
466                 index += line_inc;
467                 current_x = 0;
468             }
469         }
470         break;
471
472     default:
473         printf (" Xan WC3: Unhandled colorspace\n");
474         break;
475     }
476 }
477
478 static void inline xan_wc3_copy_pixel_run(XanContext *s, 
479     int x, int y, int pixel_count, int motion_x, int motion_y)
480 {
481     int stride;
482     int line_inc;
483     int curframe_index, prevframe_index;
484     int curframe_x, prevframe_x;
485     int width = s->avctx->width;
486     unsigned char *palette_plane, *prev_palette_plane;
487     unsigned char *y_plane, *u_plane, *v_plane;
488     unsigned char *prev_y_plane, *prev_u_plane, *prev_v_plane;
489     unsigned char *rgb_plane, *prev_rgb_plane;
490     unsigned short *rgb16_plane, *prev_rgb16_plane;
491     unsigned int *rgb32_plane, *prev_rgb32_plane;
492
493     switch (s->avctx->pix_fmt) {
494
495     case PIX_FMT_PAL8:
496         palette_plane = s->current_frame.data[0];
497         prev_palette_plane = s->last_frame.data[0];
498         stride = s->current_frame.linesize[0];
499         line_inc = stride - width;
500         curframe_index = y * stride + x;
501         curframe_x = x;
502         prevframe_index = (y + motion_y) * stride + x + motion_x;
503         prevframe_x = x + motion_x;
504         while(pixel_count--) {
505
506             palette_plane[curframe_index++] = 
507                 prev_palette_plane[prevframe_index++];
508
509             curframe_x++;
510             if (curframe_x >= width) {
511                 /* reset accounting variables */
512                 curframe_index += line_inc;
513                 curframe_x = 0;
514             }
515
516             prevframe_x++;
517             if (prevframe_x >= width) {
518                 /* reset accounting variables */
519                 prevframe_index += line_inc;
520                 prevframe_x = 0;
521             }
522         }
523         break;
524
525     case PIX_FMT_RGB555:
526     case PIX_FMT_RGB565:
527         rgb16_plane = (unsigned short *)s->current_frame.data[0];
528         prev_rgb16_plane = (unsigned short *)s->last_frame.data[0];
529         stride = s->current_frame.linesize[0] / 2;
530         line_inc = stride - width;
531         curframe_index = y * stride + x;
532         curframe_x = x;
533         prevframe_index = (y + motion_y) * stride + x + motion_x;
534         prevframe_x = x + motion_x;
535         while(pixel_count--) {
536
537             rgb16_plane[curframe_index++] = 
538                 prev_rgb16_plane[prevframe_index++];
539
540             curframe_x++;
541             if (curframe_x >= width) {
542                 /* reset accounting variables */
543                 curframe_index += line_inc;
544                 curframe_x = 0;
545             }
546
547             prevframe_x++;
548             if (prevframe_x >= width) {
549                 /* reset accounting variables */
550                 prevframe_index += line_inc;
551                 prevframe_x = 0;
552             }
553         }
554         break;
555
556     case PIX_FMT_RGB24:
557     case PIX_FMT_BGR24:
558         rgb_plane = s->current_frame.data[0];
559         prev_rgb_plane = s->last_frame.data[0];
560         stride = s->current_frame.linesize[0];
561         line_inc = stride - width * 3;
562         curframe_index = y * stride + x * 3;
563         curframe_x = x;
564         prevframe_index = (y + motion_y) * stride + 
565             (3 * (x + motion_x));
566         prevframe_x = x + motion_x;
567         while(pixel_count--) {
568
569             rgb_plane[curframe_index++] = prev_rgb_plane[prevframe_index++];
570             rgb_plane[curframe_index++] = prev_rgb_plane[prevframe_index++];
571             rgb_plane[curframe_index++] = prev_rgb_plane[prevframe_index++];
572
573             curframe_x++;
574             if (curframe_x >= width) {
575                 /* reset accounting variables */
576                 curframe_index += line_inc;
577                 curframe_x = 0;
578             }
579
580             prevframe_x++;
581             if (prevframe_x >= width) {
582                 /* reset accounting variables */
583                 prevframe_index += line_inc;
584                 prevframe_x = 0;
585             }
586         }
587         break;
588
589     case PIX_FMT_RGBA32:
590         rgb32_plane = (unsigned int *)s->current_frame.data[0];
591         prev_rgb32_plane = (unsigned int *)s->last_frame.data[0];
592         stride = s->current_frame.linesize[0] / 4;
593         line_inc = stride - width;
594         curframe_index = y * stride + x;
595         curframe_x = x;
596         prevframe_index = (y + motion_y) * stride + x + motion_x;
597         prevframe_x = x + motion_x;
598         while(pixel_count--) {
599
600             rgb32_plane[curframe_index++] = 
601                 prev_rgb32_plane[prevframe_index++];
602
603             curframe_x++;
604             if (curframe_x >= width) {
605                 /* reset accounting variables */
606                 curframe_index += line_inc;
607                 curframe_x = 0;
608             }
609
610             prevframe_x++;
611             if (prevframe_x >= width) {
612                 /* reset accounting variables */
613                 prevframe_index += line_inc;
614                 prevframe_x = 0;
615             }
616         }
617         break;
618
619     case PIX_FMT_YUV444P:
620         y_plane = s->current_frame.data[0];
621         u_plane = s->current_frame.data[1];
622         v_plane = s->current_frame.data[2];
623         prev_y_plane = s->last_frame.data[0];
624         prev_u_plane = s->last_frame.data[1];
625         prev_v_plane = s->last_frame.data[2];
626         stride = s->current_frame.linesize[0];
627         line_inc = stride - width;
628         curframe_index = y * stride + x;
629         curframe_x = x;
630         prevframe_index = (y + motion_y) * stride + x + motion_x;
631         prevframe_x = x + motion_x;
632         while(pixel_count--) {
633
634             y_plane[curframe_index] = prev_y_plane[prevframe_index];
635             u_plane[curframe_index] = prev_u_plane[prevframe_index];
636             v_plane[curframe_index] = prev_v_plane[prevframe_index];
637
638             curframe_index++;
639             curframe_x++;
640             if (curframe_x >= width) {
641                 /* reset accounting variables */
642                 curframe_index += line_inc;
643                 curframe_x = 0;
644             }
645
646             prevframe_index++;
647             prevframe_x++;
648             if (prevframe_x >= width) {
649                 /* reset accounting variables */
650                 prevframe_index += line_inc;
651                 prevframe_x = 0;
652             }
653         }
654         break;
655
656     default:
657         printf (" Xan WC3: Unhandled colorspace\n");
658         break;
659     }
660 }
661
662 static void xan_wc3_decode_frame(XanContext *s) {
663
664     int width = s->avctx->width;
665     int height = s->avctx->height;
666     int total_pixels = width * height;
667     unsigned char opcode;
668     unsigned char flag = 0;
669     int size = 0;
670     int motion_x, motion_y;
671     int x, y;
672
673     unsigned char *opcode_buffer = s->buffer1;
674     unsigned char *imagedata_buffer = s->buffer2;
675
676     /* pointers to segments inside the compressed chunk */
677     unsigned char *huffman_segment;
678     unsigned char *size_segment;
679     unsigned char *vector_segment;
680     unsigned char *imagedata_segment;
681
682     huffman_segment =   s->buf + LE_16(&s->buf[0]);
683     size_segment =      s->buf + LE_16(&s->buf[2]);
684     vector_segment =    s->buf + LE_16(&s->buf[4]);
685     imagedata_segment = s->buf + LE_16(&s->buf[6]);
686
687     xan_huffman_decode(opcode_buffer, huffman_segment);
688
689     if (imagedata_segment[0] == 2)
690         xan_unpack(imagedata_buffer, &imagedata_segment[1]);
691     else
692         imagedata_buffer = &imagedata_segment[1];
693
694     /* use the decoded data segments to build the frame */
695     x = y = 0;
696     while (total_pixels) {
697
698         opcode = *opcode_buffer++;
699         size = 0;
700
701         switch (opcode) {
702
703         case 0:
704             flag ^= 1;
705             continue;
706
707         case 1:
708         case 2:
709         case 3:
710         case 4:
711         case 5:
712         case 6:
713         case 7:
714         case 8:
715             size = opcode;
716             break;
717
718         case 12:
719         case 13:
720         case 14:
721         case 15:
722         case 16:
723         case 17:
724         case 18:
725             size += (opcode - 10);
726             break;
727
728         case 9:
729         case 19:
730             size = *size_segment++;
731             break;
732
733         case 10:
734         case 20:
735             size = BE_16(&size_segment[0]);
736             size_segment += 2;
737             break;
738
739         case 11:
740         case 21:
741             size = (size_segment[0] << 16) | (size_segment[1] << 8) |
742                 size_segment[2];
743             size_segment += 3;
744             break;
745         }
746
747         if (opcode < 12) {
748             flag ^= 1;
749             if (flag) {
750                 /* run of (size) pixels is unchanged from last frame */
751                 xan_wc3_copy_pixel_run(s, x, y, size, 0, 0);
752             } else {
753                 /* output a run of pixels from imagedata_buffer */
754                 xan_wc3_output_pixel_run(s, imagedata_buffer, x, y, size);
755                 imagedata_buffer += size;
756             }
757         } else {
758             /* run-based motion compensation from last frame */
759             motion_x = (*vector_segment >> 4) & 0xF;
760             motion_y = *vector_segment & 0xF;
761             vector_segment++;
762
763             /* sign extension */
764             if (motion_x & 0x8)
765                 motion_x |= 0xFFFFFFF0;
766             if (motion_y & 0x8)
767                 motion_y |= 0xFFFFFFF0;
768
769             /* copy a run of pixels from the previous frame */
770             xan_wc3_copy_pixel_run(s, x, y, size, motion_x, motion_y);
771
772             flag = 0;
773         }
774
775         /* coordinate accounting */
776         total_pixels -= size;
777         while (size) {
778             if (x + size >= width) {
779                 y++;
780                 size -= (width - x);
781                 x = 0;
782             } else {
783                 x += size;
784                 size = 0;
785             }
786         }
787     }
788
789     /* for PAL8, make the palette available on the way out */
790     if (s->avctx->pix_fmt == PIX_FMT_PAL8)
791         memcpy(s->current_frame.data[1], s->palette, PALETTE_COUNT * 4);
792 }
793
794 static void xan_wc4_decode_frame(XanContext *s) {
795 }
796
797 static int xan_decode_frame(AVCodecContext *avctx,
798                             void *data, int *data_size,
799                             uint8_t *buf, int buf_size)
800 {
801     XanContext *s = avctx->priv_data;
802     AVPaletteControl *palette_control = (AVPaletteControl *)avctx->extradata;
803     int keyframe = 0;
804
805     if (palette_control->palette_changed) {
806         /* load the new palette and reset the palette control */
807         xan_wc3_build_palette(s, palette_control->palette);
808         palette_control->palette_changed = 0;
809         keyframe = 1;
810     }
811
812     if (avctx->get_buffer(avctx, &s->current_frame)) {
813         printf ("  Xan Video: get_buffer() failed\n");
814         return -1;
815     }
816     s->current_frame.reference = 3;
817
818     s->buf = buf;
819     s->size = buf_size;
820
821     if (avctx->codec->id == CODEC_ID_XAN_WC3)
822         xan_wc3_decode_frame(s);
823     else if (avctx->codec->id == CODEC_ID_XAN_WC4)
824         xan_wc4_decode_frame(s);
825
826     /* release the last frame if it is allocated */
827     if (s->last_frame.data[0])
828         avctx->release_buffer(avctx, &s->last_frame);
829
830     /* shuffle frames */
831     s->last_frame = s->current_frame;
832
833     *data_size = sizeof(AVFrame);
834     *(AVFrame*)data = s->current_frame;
835
836     /* always report that the buffer was completely consumed */
837     return buf_size;
838 }
839
840 static int xan_decode_end(AVCodecContext *avctx)
841 {
842     XanContext *s = avctx->priv_data;
843
844     /* release the last frame */
845     avctx->release_buffer(avctx, &s->last_frame);
846
847     av_free(s->buffer1);
848     av_free(s->buffer2);
849
850     return 0;
851 }
852
853 AVCodec xan_wc3_decoder = {
854     "xan_wc3",
855     CODEC_TYPE_VIDEO,
856     CODEC_ID_XAN_WC3,
857     sizeof(XanContext),
858     xan_decode_init,
859     NULL,
860     xan_decode_end,
861     xan_decode_frame,
862     CODEC_CAP_DR1,
863 };
864
865 /*
866 AVCodec xan_wc4_decoder = {
867     "xan_wc4",
868     CODEC_TYPE_VIDEO,
869     CODEC_ID_XAN_WC4,
870     sizeof(XanContext),
871     xan_decode_init,
872     NULL,
873     xan_decode_end,
874     xan_decode_frame,
875     CODEC_CAP_DR1,
876 };
877 */