Added Italian resources.
[wine] / dlls / iccvid / iccvid.c
1 /*
2  * Radius Cinepak Video Decoder
3  *
4  * Copyright 2001 Dr. Tim Ferguson (see below)
5  * Portions Copyright 2003 Mike McCormack for CodeWeavers
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 /* Copyright notice from original source:
23  * ------------------------------------------------------------------------
24  * Radius Cinepak Video Decoder
25  *
26  * Dr. Tim Ferguson, 2001.
27  * For more details on the algorithm:
28  *         http://www.csse.monash.edu.au/~timf/videocodec.html
29  *
30  * This is basically a vector quantiser with adaptive vector density.  The
31  * frame is segmented into 4x4 pixel blocks, and each block is coded using
32  * either 1 or 4 vectors.
33  *
34  * There are still some issues with this code yet to be resolved.  In
35  * particular with decoding in the strip boundaries.  However, I have not
36  * yet found a sequence it doesn't work on.  Ill keep trying :)
37  *
38  * You may freely use this source code.  I only ask that you reference its
39  * source in your projects documentation:
40  *       Tim Ferguson: http://www.csse.monash.edu.au/~timf/
41  * ------------------------------------------------------------------------ */
42
43 #include <stdarg.h>
44 #include "windef.h"
45 #include "winbase.h"
46 #include "wingdi.h"
47 #include "winuser.h"
48 #include "commdlg.h"
49 #include "vfw.h"
50
51 #include "mmsystem.h"
52
53 #include "wine/debug.h"
54
55 WINE_DEFAULT_DEBUG_CHANNEL(iccvid);
56
57 #define ICCVID_MAGIC mmioFOURCC('c', 'v', 'i', 'd')
58
59 #define DBUG    0
60 #define MAX_STRIPS 32
61
62 /* ------------------------------------------------------------------------ */
63 typedef struct
64 {
65     unsigned char y0, y1, y2, y3;
66     char u, v;
67     unsigned char r[4], g[4], b[4];
68 } cvid_codebook;
69
70 typedef struct {
71     cvid_codebook *v4_codebook[MAX_STRIPS];
72     cvid_codebook *v1_codebook[MAX_STRIPS];
73     int strip_num;
74 } cinepak_info;
75
76 typedef struct _ICCVID_Info
77 {
78     DWORD         dwMagic;
79     int           bits_per_pixel;
80     cinepak_info *cvinfo;
81 } ICCVID_Info;
82
83 static inline LPVOID ICCVID_Alloc( size_t size, size_t count )
84 {
85     return HeapAlloc( GetProcessHeap(), 0, size*count );
86 }
87
88 static inline BOOL ICCVID_Free( LPVOID ptr )
89 {
90     return HeapFree( GetProcessHeap(), 0, ptr );
91 }
92
93
94 /* ------------------------------------------------------------------------ */
95 static unsigned char *in_buffer, uiclip[1024], *uiclp = NULL;
96
97 #define get_byte() *(in_buffer++)
98 #define skip_byte() in_buffer++
99 #define get_word() ((unsigned short)(in_buffer += 2, \
100     (in_buffer[-2] << 8 | in_buffer[-1])))
101 #define get_long() ((unsigned long)(in_buffer += 4, \
102     (in_buffer[-4] << 24 | in_buffer[-3] << 16 | in_buffer[-2] << 8 | in_buffer[-1])))
103
104
105 /* ---------------------------------------------------------------------- */
106 static inline void read_codebook(cvid_codebook *c, int mode)
107 {
108 int uvr, uvg, uvb;
109
110     if(mode)        /* black and white */
111         {
112         c->y0 = get_byte();
113         c->y1 = get_byte();
114         c->y2 = get_byte();
115         c->y3 = get_byte();
116         c->u = c->v = 0;
117
118         c->r[0] = c->g[0] = c->b[0] = c->y0;
119         c->r[1] = c->g[1] = c->b[1] = c->y1;
120         c->r[2] = c->g[2] = c->b[2] = c->y2;
121         c->r[3] = c->g[3] = c->b[3] = c->y3;
122         }
123     else            /* colour */
124         {
125         c->y0 = get_byte();  /* luma */
126         c->y1 = get_byte();
127         c->y2 = get_byte();
128         c->y3 = get_byte();
129         c->u = get_byte(); /* chroma */
130         c->v = get_byte();
131
132         uvr = c->v << 1;
133         uvg = -((c->u+1) >> 1) - c->v;
134         uvb = c->u << 1;
135
136         c->r[0] = uiclp[c->y0 + uvr]; c->g[0] = uiclp[c->y0 + uvg]; c->b[0] = uiclp[c->y0 + uvb];
137         c->r[1] = uiclp[c->y1 + uvr]; c->g[1] = uiclp[c->y1 + uvg]; c->b[1] = uiclp[c->y1 + uvb];
138         c->r[2] = uiclp[c->y2 + uvr]; c->g[2] = uiclp[c->y2 + uvg]; c->b[2] = uiclp[c->y2 + uvb];
139         c->r[3] = uiclp[c->y3 + uvr]; c->g[3] = uiclp[c->y3 + uvg]; c->b[3] = uiclp[c->y3 + uvb];
140         }
141 }
142
143
144 #define MAKECOLOUR32(r,g,b) (((r) << 16) | ((g) << 8) | (b))
145 /*#define MAKECOLOUR24(r,g,b) (((r) << 16) | ((g) << 8) | (b))*/
146 #define MAKECOLOUR16(r,g,b) (((r) >> 3) << 11)| (((g) >> 2) << 5)| (((b) >> 3) << 0)
147 #define MAKECOLOUR15(r,g,b) (((r) >> 3) << 10)| (((g) >> 3) << 5)| (((b) >> 3) << 0)
148
149 /* ------------------------------------------------------------------------ */
150 static void cvid_v1_32(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb)
151 {
152 unsigned long *vptr = (unsigned long *)frm;
153 #ifndef ORIGINAL
154 int row_inc = -stride/4;
155 #else
156 int row_inc = stride/4;
157 #endif
158 int x, y;
159
160     /* fill 4x4 block of pixels with colour values from codebook */
161     for (y = 0; y < 4; y++)
162     {
163         if (&vptr[y*row_inc] < (unsigned long *)limit) return;
164         for (x = 0; x < 4; x++)
165             vptr[y*row_inc + x] = MAKECOLOUR32(cb->r[x/2+(y/2)*2], cb->g[x/2+(y/2)*2], cb->b[x/2+(y/2)*2]);
166     }
167 }
168
169
170 /* ------------------------------------------------------------------------ */
171 static void cvid_v4_32(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0,
172     cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
173 {
174 unsigned long *vptr = (unsigned long *)frm;
175 #ifndef ORIGINAL
176 int row_inc = -stride/4;
177 #else
178 int row_inc = stride/4;
179 #endif
180 int x, y;
181 cvid_codebook * cb[] = {cb0,cb1,cb2,cb3};
182
183     /* fill 4x4 block of pixels with colour values from codebooks */
184     for (y = 0; y < 4; y++)
185     {
186         if (&vptr[y*row_inc] < (unsigned long *)limit) return;
187         for (x = 0; x < 4; x++)
188             vptr[y*row_inc + x] = MAKECOLOUR32(cb[x/2+(y/2)*2]->r[x%2+(y%2)*2], cb[x/2+(y/2)*2]->g[x%2+(y%2)*2], cb[x/2+(y/2)*2]->b[x%2+(y%2)*2]);
189     }
190 }
191
192
193 /* ------------------------------------------------------------------------ */
194 static void cvid_v1_24(unsigned char *vptr, unsigned char *limit, int stride, cvid_codebook *cb)
195 {
196 #ifndef ORIGINAL
197 int row_inc = -stride;
198 #else
199 int row_inc = stride;
200 #endif
201 int x, y;
202
203     /* fill 4x4 block of pixels with colour values from codebook */
204     for (y = 0; y < 4; y++)
205     {
206         if (&vptr[y*row_inc] < limit) return;
207         for (x = 0; x < 4; x++)
208         {
209             vptr[y*row_inc + x*3 + 0] = cb->b[x/2+(y/2)*2];
210             vptr[y*row_inc + x*3 + 1] = cb->g[x/2+(y/2)*2];
211             vptr[y*row_inc + x*3 + 2] = cb->r[x/2+(y/2)*2];
212         }
213     }
214 }
215
216
217 /* ------------------------------------------------------------------------ */
218 static void cvid_v4_24(unsigned char *vptr, unsigned char *limit, int stride, cvid_codebook *cb0,
219     cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
220 {
221 #ifndef ORIGINAL
222 int row_inc = -stride;
223 #else
224 int row_inc = stride;
225 #endif
226 cvid_codebook * cb[] = {cb0,cb1,cb2,cb3};
227 int x, y;
228
229     /* fill 4x4 block of pixels with colour values from codebooks */
230     for (y = 0; y < 4; y++)
231     {
232         if (&vptr[y*row_inc] < limit) return;
233         for (x = 0; x < 4; x++)
234         {
235             vptr[y*row_inc + x*3 + 0] = cb[x/2+(y/2)*2]->b[x%2+(y%2)*2];
236             vptr[y*row_inc + x*3 + 1] = cb[x/2+(y/2)*2]->g[x%2+(y%2)*2];
237             vptr[y*row_inc + x*3 + 2] = cb[x/2+(y/2)*2]->r[x%2+(y%2)*2];
238         }
239     }
240 }
241
242
243 /* ------------------------------------------------------------------------ */
244 static void cvid_v1_16(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb)
245 {
246 unsigned short *vptr = (unsigned short *)frm;
247 #ifndef ORIGINAL
248 int row_inc = -stride/2;
249 #else
250 int row_inc = stride/2;
251 #endif
252 int x, y;
253
254     /* fill 4x4 block of pixels with colour values from codebook */
255     for (y = 0; y < 4; y++)
256     {
257         if (&vptr[y*row_inc] < (unsigned short *)limit) return;
258         for (x = 0; x < 4; x++)
259             vptr[y*row_inc + x] = MAKECOLOUR16(cb->r[x/2+(y/2)*2], cb->g[x/2+(y/2)*2], cb->b[x/2+(y/2)*2]);
260     }
261 }
262
263
264 /* ------------------------------------------------------------------------ */
265 static void cvid_v4_16(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0,
266     cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
267 {
268 unsigned short *vptr = (unsigned short *)frm;
269 #ifndef ORIGINAL
270 int row_inc = -stride/2;
271 #else
272 int row_inc = stride/2;
273 #endif
274 cvid_codebook * cb[] = {cb0,cb1,cb2,cb3};
275 int x, y;
276
277     /* fill 4x4 block of pixels with colour values from codebooks */
278     for (y = 0; y < 4; y++)
279     {
280         if (&vptr[y*row_inc] < (unsigned short *)limit) return;
281         for (x = 0; x < 4; x++)
282             vptr[y*row_inc + x] = MAKECOLOUR16(cb[x/2+(y/2)*2]->r[x%2+(y%2)*2], cb[x/2+(y/2)*2]->g[x%2+(y%2)*2], cb[x/2+(y/2)*2]->b[x%2+(y%2)*2]);
283     }
284 }
285
286 /* ------------------------------------------------------------------------ */
287 static void cvid_v1_15(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb)
288 {
289 unsigned short *vptr = (unsigned short *)frm;
290 #ifndef ORIGINAL
291 int row_inc = -stride/2;
292 #else
293 int row_inc = stride/2;
294 #endif
295 int x, y;
296
297     /* fill 4x4 block of pixels with colour values from codebook */
298     for (y = 0; y < 4; y++)
299     {
300         if (&vptr[y*row_inc] < (unsigned short *)limit) return;
301         for (x = 0; x < 4; x++)
302             vptr[y*row_inc + x] = MAKECOLOUR15(cb->r[x/2+(y/2)*2], cb->g[x/2+(y/2)*2], cb->b[x/2+(y/2)*2]);
303     }
304 }
305
306
307 /* ------------------------------------------------------------------------ */
308 static void cvid_v4_15(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0,
309     cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
310 {
311 unsigned short *vptr = (unsigned short *)frm;
312 #ifndef ORIGINAL
313 int row_inc = -stride/2;
314 #else
315 int row_inc = stride/2;
316 #endif
317 cvid_codebook * cb[] = {cb0,cb1,cb2,cb3};
318 int x, y;
319
320     /* fill 4x4 block of pixels with colour values from codebooks */
321     for (y = 0; y < 4; y++)
322     {
323         if (&vptr[y*row_inc] < (unsigned short *)limit) return;
324         for (x = 0; x < 4; x++)
325             vptr[y*row_inc + x] = MAKECOLOUR15(cb[x/2+(y/2)*2]->r[x%2+(y%2)*2], cb[x/2+(y/2)*2]->g[x%2+(y%2)*2], cb[x/2+(y/2)*2]->b[x%2+(y%2)*2]);
326     }
327 }
328
329
330 /* ------------------------------------------------------------------------
331  * Call this function once at the start of the sequence and save the
332  * returned context for calls to decode_cinepak().
333  */
334 cinepak_info *decode_cinepak_init(void)
335 {
336     cinepak_info *cvinfo;
337     int i;
338
339     cvinfo = ICCVID_Alloc( sizeof (cinepak_info), 1 );
340     if( !cvinfo )
341         return NULL;
342     cvinfo->strip_num = 0;
343
344     if(uiclp == NULL)
345     {
346         uiclp = uiclip+512;
347         for(i = -512; i < 512; i++)
348             uiclp[i] = (i < 0 ? 0 : (i > 255 ? 255 : i));
349     }
350
351     return cvinfo;
352 }
353
354 void free_cvinfo( cinepak_info *cvinfo )
355 {
356     int i;
357
358     for( i=0; i<cvinfo->strip_num; i++ )
359     {
360         ICCVID_Free(cvinfo->v4_codebook[i]);
361         ICCVID_Free(cvinfo->v1_codebook[i]);
362     }
363     ICCVID_Free( cvinfo );
364 }
365
366 typedef void (*fn_cvid_v1)(unsigned char *frm, unsigned char *limit,
367                            int stride, cvid_codebook *cb);
368 typedef void (*fn_cvid_v4)(unsigned char *frm, unsigned char *limit, int stride,
369                            cvid_codebook *cb0, cvid_codebook *cb1,
370                            cvid_codebook *cb2, cvid_codebook *cb3);
371
372 /* ------------------------------------------------------------------------
373  * This function decodes a buffer containing a Cinepak encoded frame.
374  *
375  * context - the context created by decode_cinepak_init().
376  * buf - the input buffer to be decoded
377  * size - the size of the input buffer
378  * frame - the output frame buffer (24 or 32 bit per pixel)
379  * width - the width of the output frame
380  * height - the height of the output frame
381  * bit_per_pixel - the number of bits per pixel allocated to the output
382  *   frame (only 24 or 32 bpp are supported)
383  */
384 void decode_cinepak(cinepak_info *cvinfo, unsigned char *buf, int size,
385            unsigned char *frame, int width, int height, int bit_per_pixel)
386 {
387     cvid_codebook *v4_codebook, *v1_codebook, *codebook = NULL;
388     unsigned long x, y, y_bottom, frame_flags, strips, cv_width, cv_height,
389                   cnum, strip_id, chunk_id, x0, y0, x1, y1, ci, flag, mask;
390     long len, top_size, chunk_size;
391     unsigned char *frm_ptr, *frm_end;
392     int i, cur_strip, d0, d1, d2, d3, frm_stride, bpp = 3;
393     fn_cvid_v1 cvid_v1 = cvid_v1_24;
394     fn_cvid_v4 cvid_v4 = cvid_v4_24;
395
396     x = y = 0;
397     y_bottom = 0;
398     in_buffer = buf;
399
400     frame_flags = get_byte();
401     len = get_byte() << 16;
402     len |= get_byte() << 8;
403     len |= get_byte();
404
405     switch(bit_per_pixel)
406         {
407         case 15:
408             bpp = 2;
409             cvid_v1 = cvid_v1_15;
410             cvid_v4 = cvid_v4_15;
411             break;
412         case 16:
413             bpp = 2;
414             cvid_v1 = cvid_v1_16;
415             cvid_v4 = cvid_v4_16;
416             break;
417         case 24:
418             bpp = 3;
419             cvid_v1 = cvid_v1_24;
420             cvid_v4 = cvid_v4_24;
421             break;
422         case 32:
423             bpp = 4;
424             cvid_v1 = cvid_v1_32;
425             cvid_v4 = cvid_v4_32;
426             break;
427         }
428
429     frm_stride = width * bpp;
430     frm_ptr = frame;
431     frm_end = frm_ptr + width * height * bpp;
432
433     if(len != size)
434         {
435         if(len & 0x01) len++; /* AVIs tend to have a size mismatch */
436         if(len != size)
437             {
438             ERR("CVID: corruption %d (QT/AVI) != %ld (CV)\n", size, len);
439             /* return; */
440             }
441         }
442
443     cv_width = get_word();
444     cv_height = get_word();
445     strips = get_word();
446
447     if(strips > cvinfo->strip_num)
448         {
449         if(strips >= MAX_STRIPS)
450             {
451             ERR("CVID: strip overflow (more than %d)\n", MAX_STRIPS);
452             return;
453             }
454
455         for(i = cvinfo->strip_num; i < strips; i++)
456             {
457             if((cvinfo->v4_codebook[i] = (cvid_codebook *)ICCVID_Alloc(sizeof(cvid_codebook), 260)) == NULL)
458                 {
459                 ERR("CVID: codebook v4 alloc err\n");
460                 return;
461                 }
462
463             if((cvinfo->v1_codebook[i] = (cvid_codebook *)ICCVID_Alloc(sizeof(cvid_codebook), 260)) == NULL)
464                 {
465                 ERR("CVID: codebook v1 alloc err\n");
466                 return;
467                 }
468             }
469         }
470     cvinfo->strip_num = strips;
471
472     TRACE("CVID: <%ld,%ld> strips %ld\n", cv_width, cv_height, strips);
473
474     for(cur_strip = 0; cur_strip < strips; cur_strip++)
475         {
476         v4_codebook = cvinfo->v4_codebook[cur_strip];
477         v1_codebook = cvinfo->v1_codebook[cur_strip];
478
479         if((cur_strip > 0) && (!(frame_flags & 0x01)))
480             {
481             memcpy(cvinfo->v4_codebook[cur_strip], cvinfo->v4_codebook[cur_strip-1], 260 * sizeof(cvid_codebook));
482             memcpy(cvinfo->v1_codebook[cur_strip], cvinfo->v1_codebook[cur_strip-1], 260 * sizeof(cvid_codebook));
483             }
484
485         strip_id = get_word();        /* 1000 = key strip, 1100 = iter strip */
486         top_size = get_word();
487         y0 = get_word();        /* FIXME: most of these are ignored at the moment */
488         x0 = get_word();
489         y1 = get_word();
490         x1 = get_word();
491
492         y_bottom += y1;
493         top_size -= 12;
494         x = 0;
495         if(x1 != width)
496             WARN("CVID: Warning x1 (%ld) != width (%d)\n", x1, width);
497
498         TRACE("   %d) %04lx %04ld <%ld,%ld> <%ld,%ld> yt %ld\n",
499               cur_strip, strip_id, top_size, x0, y0, x1, y1, y_bottom);
500
501         while(top_size > 0)
502             {
503             chunk_id  = get_word();
504             chunk_size = get_word();
505
506             TRACE("        %04lx %04ld\n", chunk_id, chunk_size);
507             top_size -= chunk_size;
508             chunk_size -= 4;
509
510             switch(chunk_id)
511                 {
512                     /* -------------------- Codebook Entries -------------------- */
513                 case 0x2000:
514                 case 0x2200:
515                     codebook = (chunk_id == 0x2200 ? v1_codebook : v4_codebook);
516                     cnum = chunk_size/6;
517                     for(i = 0; i < cnum; i++) read_codebook(codebook+i, 0);
518                     break;
519
520                 case 0x2400:
521                 case 0x2600:        /* 8 bit per pixel */
522                     codebook = (chunk_id == 0x2600 ? v1_codebook : v4_codebook);
523                     cnum = chunk_size/4;
524                     for(i = 0; i < cnum; i++) read_codebook(codebook+i, 1);
525                     break;
526
527                 case 0x2100:
528                 case 0x2300:
529                     codebook = (chunk_id == 0x2300 ? v1_codebook : v4_codebook);
530
531                     ci = 0;
532                     while(chunk_size > 0)
533                         {
534                         flag = get_long();
535                         chunk_size -= 4;
536
537                         for(i = 0; i < 32; i++)
538                             {
539                             if(flag & 0x80000000)
540                                 {
541                                 chunk_size -= 6;
542                                 read_codebook(codebook+ci, 0);
543                                 }
544
545                             ci++;
546                             flag <<= 1;
547                             }
548                         }
549                     while(chunk_size > 0) { skip_byte(); chunk_size--; }
550                     break;
551
552                 case 0x2500:
553                 case 0x2700:        /* 8 bit per pixel */
554                     codebook = (chunk_id == 0x2700 ? v1_codebook : v4_codebook);
555
556                     ci = 0;
557                     while(chunk_size > 0)
558                         {
559                         flag = get_long();
560                         chunk_size -= 4;
561
562                         for(i = 0; i < 32; i++)
563                             {
564                             if(flag & 0x80000000)
565                                 {
566                                 chunk_size -= 4;
567                                 read_codebook(codebook+ci, 1);
568                                 }
569
570                             ci++;
571                             flag <<= 1;
572                             }
573                         }
574                     while(chunk_size > 0) { skip_byte(); chunk_size--; }
575                     break;
576
577                     /* -------------------- Frame -------------------- */
578                 case 0x3000:
579                     while((chunk_size > 0) && (y < y_bottom))
580                         {
581                         flag = get_long();
582                         chunk_size -= 4;
583
584                         for(i = 0; i < 32; i++)
585                             {
586                             if(y >= y_bottom) break;
587                             if(flag & 0x80000000)    /* 4 bytes per block */
588                                 {
589                                 d0 = get_byte();
590                                 d1 = get_byte();
591                                 d2 = get_byte();
592                                 d3 = get_byte();
593                                 chunk_size -= 4;
594 #ifdef ORIGINAL
595                                 cvid_v4(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3);
596 #else
597                                 cvid_v4(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3);
598 #endif
599                                 }
600                             else        /* 1 byte per block */
601                                 {
602 #ifdef ORIGINAL
603                                 cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte());
604 #else
605                                 cvid_v1(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v1_codebook + get_byte());
606 #endif
607                                 chunk_size--;
608                                 }
609
610                             x += 4;
611                             if(x >= width)
612                                 {
613                                 x = 0;
614                                 y += 4;
615                                 }
616                             flag <<= 1;
617                             }
618                         }
619                     while(chunk_size > 0) { skip_byte(); chunk_size--; }
620                     break;
621
622                 case 0x3100:
623                     while((chunk_size > 0) && (y < y_bottom))
624                         {
625                             /* ---- flag bits: 0 = SKIP, 10 = V1, 11 = V4 ---- */
626                         flag = (unsigned long)get_long();
627                         chunk_size -= 4;
628                         mask = 0x80000000;
629
630                         while((mask) && (y < y_bottom))
631                             {
632                             if(flag & mask)
633                                 {
634                                 if(mask == 1)
635                                     {
636                                     if(chunk_size < 0) break;
637                                     flag = (unsigned long)get_long();
638                                     chunk_size -= 4;
639                                     mask = 0x80000000;
640                                     }
641                                 else mask >>= 1;
642
643                                 if(flag & mask)        /* V4 */
644                                     {
645                                     d0 = get_byte();
646                                     d1 = get_byte();
647                                     d2 = get_byte();
648                                     d3 = get_byte();
649                                     chunk_size -= 4;
650 #ifdef ORIGINAL
651                                     cvid_v4(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3);
652 #else
653                                     cvid_v4(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3);
654 #endif
655                                     }
656                                 else        /* V1 */
657                                     {
658                                     chunk_size--;
659 #ifdef ORIGINAL
660                                     cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte());
661 #else
662                                     cvid_v1(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v1_codebook + get_byte());
663 #endif
664                                     }
665                                 }        /* else SKIP */
666
667                             mask >>= 1;
668                             x += 4;
669                             if(x >= width)
670                                 {
671                                 x = 0;
672                                 y += 4;
673                                 }
674                             }
675                         }
676
677                     while(chunk_size > 0) { skip_byte(); chunk_size--; }
678                     break;
679
680                 case 0x3200:        /* each byte is a V1 codebook */
681                     while((chunk_size > 0) && (y < y_bottom))
682                         {
683 #ifdef ORIGINAL
684                         cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte());
685 #else
686                         cvid_v1(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v1_codebook + get_byte());
687 #endif
688                         chunk_size--;
689                         x += 4;
690                         if(x >= width)
691                             {
692                             x = 0;
693                             y += 4;
694                             }
695                         }
696                     while(chunk_size > 0) { skip_byte(); chunk_size--; }
697                     break;
698
699                 default:
700                     ERR("CVID: unknown chunk_id %08lx\n", chunk_id);
701                     while(chunk_size > 0) { skip_byte(); chunk_size--; }
702                     break;
703                 }
704             }
705         }
706
707     if(len != size)
708         {
709         if(len & 0x01) len++; /* AVIs tend to have a size mismatch */
710         if(len != size)
711             {
712             long xlen;
713             skip_byte();
714             xlen = get_byte() << 16;
715             xlen |= get_byte() << 8;
716             xlen |= get_byte(); /* Read Len */
717             WARN("CVID: END INFO chunk size %d cvid size1 %ld cvid size2 %ld\n",
718                   size, len, xlen);
719             }
720         }
721 }
722
723 static void ICCVID_dump_BITMAPINFO(const BITMAPINFO * bmi)
724 {
725     TRACE(
726         "planes = %d\n"
727         "bpp    = %d\n"
728         "height = %ld\n"
729         "width  = %ld\n"
730         "compr  = %s\n",
731         bmi->bmiHeader.biPlanes,
732         bmi->bmiHeader.biBitCount,
733         bmi->bmiHeader.biHeight,
734         bmi->bmiHeader.biWidth,
735         debugstr_an( (const char *)&bmi->bmiHeader.biCompression, 4 ) );
736 }
737
738 static inline int ICCVID_CheckMask(RGBQUAD bmiColors[3], COLORREF redMask, COLORREF blueMask, COLORREF greenMask)
739 {
740     COLORREF realRedMask = MAKECOLOUR32(bmiColors[0].rgbRed, bmiColors[0].rgbGreen, bmiColors[0].rgbBlue);
741     COLORREF realBlueMask = MAKECOLOUR32(bmiColors[1].rgbRed, bmiColors[1].rgbGreen, bmiColors[1].rgbBlue);
742     COLORREF realGreenMask = MAKECOLOUR32(bmiColors[2].rgbRed, bmiColors[2].rgbGreen, bmiColors[2].rgbBlue);
743
744     TRACE("\nbmiColors[0] = 0x%08lx\nbmiColors[1] = 0x%08lx\nbmiColors[2] = 0x%08lx\n",
745         realRedMask, realBlueMask, realGreenMask);
746         
747     if ((realRedMask == redMask) &&
748         (realBlueMask == blueMask) &&
749         (realGreenMask == greenMask))
750         return TRUE;
751     return FALSE;
752 }
753
754 LRESULT ICCVID_DecompressQuery( ICCVID_Info *info, LPBITMAPINFO in, LPBITMAPINFO out )
755 {
756     TRACE("ICM_DECOMPRESS_QUERY %p %p %p\n", info, in, out);
757
758     if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
759         return ICERR_BADPARAM;
760
761     TRACE("in: ");
762     ICCVID_dump_BITMAPINFO(in);
763
764     if( in->bmiHeader.biCompression != ICCVID_MAGIC )
765         return ICERR_UNSUPPORTED;
766
767     if( out )
768     {
769         TRACE("out: ");
770         ICCVID_dump_BITMAPINFO(out);
771
772         if( in->bmiHeader.biPlanes != out->bmiHeader.biPlanes )
773             return ICERR_UNSUPPORTED;
774         if( in->bmiHeader.biHeight != out->bmiHeader.biHeight )
775             return ICERR_UNSUPPORTED;
776         if( in->bmiHeader.biWidth != out->bmiHeader.biWidth )
777             return ICERR_UNSUPPORTED;
778
779         switch( out->bmiHeader.biBitCount )
780         {
781         case 16:
782             if ( out->bmiHeader.biCompression == BI_BITFIELDS )
783             {
784                 if ( !ICCVID_CheckMask(out->bmiColors, 0x7C00, 0x03E0, 0x001F) &&
785                      !ICCVID_CheckMask(out->bmiColors, 0xF800, 0x07E0, 0x001F) )
786                 {
787                     TRACE("unsupported output bit field(s) for 16-bit colors\n");
788                     return ICERR_UNSUPPORTED;
789                 }
790             }
791             break;
792         case 24:
793         case 32:
794             break;
795         default:
796             TRACE("unsupported output bitcount = %d\n", out->bmiHeader.biBitCount );
797             return ICERR_UNSUPPORTED;
798         }
799     }
800
801     return ICERR_OK;
802 }
803
804 LRESULT ICCVID_DecompressGetFormat( ICCVID_Info *info, LPBITMAPINFO in, LPBITMAPINFO out )
805 {
806     DWORD size;
807
808     TRACE("ICM_DECOMPRESS_GETFORMAT %p %p %p\n", info, in, out);
809
810     if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
811         return ICERR_BADPARAM;
812
813     size = in->bmiHeader.biSize;
814     if (in->bmiHeader.biBitCount <= 8)
815         size += in->bmiHeader.biClrUsed * sizeof(RGBQUAD);
816
817     if( out )
818     {
819         memcpy( out, in, size );
820         out->bmiHeader.biCompression = BI_RGB;
821         out->bmiHeader.biSizeImage = in->bmiHeader.biHeight
822                                    * in->bmiHeader.biWidth *4;
823         return ICERR_OK;
824     }
825     return size;
826 }
827
828 LRESULT ICCVID_DecompressBegin( ICCVID_Info *info, LPBITMAPINFO in, LPBITMAPINFO out )
829 {
830     TRACE("ICM_DECOMPRESS_BEGIN %p %p %p\n", info, in, out);
831
832     if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
833         return ICERR_BADPARAM;
834
835     info->bits_per_pixel = out->bmiHeader.biBitCount;
836
837     if (info->bits_per_pixel == 16)
838     {
839         if ( out->bmiHeader.biCompression == BI_BITFIELDS )
840         {
841             if ( ICCVID_CheckMask(out->bmiColors, 0x7C00, 0x03E0, 0x001F) )
842                 info->bits_per_pixel = 15;
843             else if ( ICCVID_CheckMask(out->bmiColors, 0xF800, 0x07E0, 0x001F) )
844                 info->bits_per_pixel = 16;
845             else
846             {
847                 TRACE("unsupported output bit field(s) for 16-bit colors\n");
848                 return ICERR_UNSUPPORTED;
849             }
850         }
851         else
852             info->bits_per_pixel = 15;
853     }
854
855     TRACE("bit_per_pixel = %d\n", info->bits_per_pixel);
856
857     if( info->cvinfo )
858         free_cvinfo( info->cvinfo );
859     info->cvinfo = decode_cinepak_init();
860
861     return ICERR_OK;
862 }
863
864 LRESULT ICCVID_Decompress( ICCVID_Info *info, ICDECOMPRESS *icd, DWORD size )
865 {
866     LONG width, height;
867
868     TRACE("ICM_DECOMPRESS %p %p %ld\n", info, icd, size);
869
870     if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
871         return ICERR_BADPARAM;
872
873     width  = icd->lpbiInput->biWidth;
874     height = icd->lpbiInput->biHeight;
875
876     decode_cinepak(info->cvinfo, icd->lpInput, icd->lpbiInput->biSizeImage,
877                    icd->lpOutput, width, height, info->bits_per_pixel);
878
879     return ICERR_OK;
880 }
881
882 LRESULT ICCVID_DecompressEx( ICCVID_Info *info, ICDECOMPRESSEX *icd, DWORD size )
883 {
884     LONG width, height;
885
886     TRACE("ICM_DECOMPRESSEX %p %p %ld\n", info, icd, size);
887
888     if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
889         return ICERR_BADPARAM;
890
891     /* FIXME: flags are ignored */
892
893     width  = icd->lpbiSrc->biWidth;
894     height = icd->lpbiSrc->biHeight;
895
896     decode_cinepak(info->cvinfo, icd->lpSrc, icd->lpbiSrc->biSizeImage,
897                    icd->lpDst, width, height, info->bits_per_pixel);
898
899     return ICERR_OK;
900 }
901
902 LRESULT ICCVID_Close( ICCVID_Info *info )
903 {
904     if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
905         return 0;
906     if( info->cvinfo )
907         free_cvinfo( info->cvinfo );
908     ICCVID_Free( info );
909     return 1;
910 }
911
912 LRESULT WINAPI ICCVID_DriverProc( DWORD dwDriverId, HDRVR hdrvr, UINT msg,
913                                   LONG lParam1, LONG lParam2)
914 {
915     ICCVID_Info *info = (ICCVID_Info *) dwDriverId;
916
917     TRACE("%ld %p %d %ld %ld\n", dwDriverId, hdrvr, msg, lParam1, lParam2);
918
919     switch( msg )
920     {
921     case DRV_LOAD:
922         TRACE("Loaded\n");
923         return 1;
924     case DRV_ENABLE:
925         return 0;
926     case DRV_DISABLE:
927         return 0;
928     case DRV_FREE:
929         return 0;
930
931     case DRV_OPEN:
932         TRACE("Opened\n");
933         info = ICCVID_Alloc( sizeof (ICCVID_Info), 1 );
934         if( info )
935         {
936             info->dwMagic = ICCVID_MAGIC;
937             info->cvinfo = NULL;
938         }
939         return (LRESULT) info;
940
941     case ICM_DECOMPRESS_QUERY:
942         return ICCVID_DecompressQuery( info, (LPBITMAPINFO) lParam1,
943                                        (LPBITMAPINFO) lParam2 );
944     case ICM_DECOMPRESS_GET_FORMAT:
945         return ICCVID_DecompressGetFormat( info, (LPBITMAPINFO) lParam1,
946                                        (LPBITMAPINFO) lParam2 );
947     case ICM_DECOMPRESS_BEGIN:
948         return ICCVID_DecompressBegin( info, (LPBITMAPINFO) lParam1,
949                                        (LPBITMAPINFO) lParam2 );
950     case ICM_DECOMPRESS:
951         return ICCVID_Decompress( info, (ICDECOMPRESS*) lParam1,
952                                   (DWORD) lParam2 );
953     case ICM_DECOMPRESSEX:
954         return ICCVID_DecompressEx( info, (ICDECOMPRESSEX*) lParam1, 
955                                   (DWORD) lParam2 );
956
957     case DRV_CLOSE:
958         return ICCVID_Close( info );
959
960     default:
961         FIXME("Unknown message: %04x %ld %ld\n", msg, lParam1, lParam2);
962     }
963     return 0;
964 }