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