xref: /reactos/dll/win32/msvidc32/msvideo1.c (revision e0b67a29)
1 /*
2  * Microsoft Video-1 Decoder
3  * Copyright (C) 2003 the ffmpeg project
4  *
5  * Portions Copyright (C) 2004 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  */
22 
23 /**
24  * @file msvideo1.c
25  * Microsoft Video-1 Decoder by Mike Melanson (melanson@pcisys.net)
26  * For more information about the MS Video-1 format, visit:
27  *   http://www.pcisys.net/~melanson/codecs/
28  *
29  * This decoder outputs either PAL8 or RGB555 data, depending on the
30  * whether a RGB palette was passed through palctrl;
31  * if it's present, then the data is PAL8; RGB555 otherwise.
32  */
33 
34 #include <stdarg.h>
35 #include "windef.h"
36 #include "winbase.h"
37 #include "wingdi.h"
38 #include "winuser.h"
39 #include "commdlg.h"
40 #include "vfw.h"
41 #include "mmsystem.h"
42 #include "msvidc32_private.h"
43 
44 #include "wine/debug.h"
45 
46 WINE_DEFAULT_DEBUG_CHANNEL(msvidc32);
47 
48 static HINSTANCE MSVIDC32_hModule;
49 
50 #define CRAM_MAGIC mmioFOURCC('C', 'R', 'A', 'M')
51 #define MSVC_MAGIC mmioFOURCC('M', 'S', 'V', 'C')
52 #define WHAM_MAGIC mmioFOURCC('W', 'H', 'A', 'M')
53 #define compare_fourcc(fcc1, fcc2) (((fcc1)^(fcc2))&~0x20202020)
54 
55 #define PALETTE_COUNT 256
56 #define LE_16(x)  ((((const uint8_t *)(x))[1] << 8) | ((const uint8_t *)(x))[0])
57 
58 /* FIXME - check the stream size */
59 #define CHECK_STREAM_PTR(n) \
60   if ((stream_ptr + n) > buf_size ) { \
61     WARN("stream_ptr out of bounds (%d >= %d)\n", \
62       stream_ptr + n, buf_size); \
63     return; \
64   }
65 
66 typedef BYTE uint8_t;
67 
68 typedef struct Msvideo1Context {
69     DWORD dwMagic;
70     int depth;
71 } Msvideo1Context;
72 
get_stride(int width,int depth)73 static inline int get_stride(int width, int depth)
74 {
75     return ((depth * width + 31) >> 3) & ~3;
76 }
77 
78 static void
msvideo1_decode_8bit(int width,int height,const unsigned char * buf,int buf_size,unsigned char * pixels,int stride)79 msvideo1_decode_8bit( int width, int height, const unsigned char *buf, int buf_size,
80                       unsigned char *pixels, int stride)
81 {
82     int block_ptr, pixel_ptr;
83     int total_blocks;
84     int pixel_x, pixel_y;  /* pixel width and height iterators */
85     int block_x, block_y;  /* block width and height iterators */
86     int blocks_wide, blocks_high;  /* width and height in 4x4 blocks */
87     int block_inc;
88     int row_dec;
89 
90     /* decoding parameters */
91     int stream_ptr;
92     unsigned char byte_a, byte_b;
93     unsigned short flags;
94     int skip_blocks;
95     unsigned char colors[8];
96 
97     stream_ptr = 0;
98     skip_blocks = 0;
99     blocks_wide = width / 4;
100     blocks_high = height / 4;
101     total_blocks = blocks_wide * blocks_high;
102     block_inc = 4;
103 #ifdef ORIGINAL
104     row_dec = stride + 4;
105 #else
106     row_dec = - (stride - 4); /* such that -row_dec > 0 */
107 #endif
108 
109     for (block_y = blocks_high; block_y > 0; block_y--) {
110 #ifdef ORIGINAL
111         block_ptr = ((block_y * 4) - 1) * stride;
112 #else
113         block_ptr = ((blocks_high - block_y) * 4) * stride;
114 #endif
115         for (block_x = blocks_wide; block_x > 0; block_x--) {
116             /* check if this block should be skipped */
117             if (skip_blocks) {
118                 block_ptr += block_inc;
119                 skip_blocks--;
120                 total_blocks--;
121                 continue;
122             }
123 
124             pixel_ptr = block_ptr;
125 
126             /* get the next two bytes in the encoded data stream */
127             CHECK_STREAM_PTR(2);
128             byte_a = buf[stream_ptr++];
129             byte_b = buf[stream_ptr++];
130 
131             /* check if the decode is finished */
132             if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0))
133                 return;
134             else if ((byte_b & 0xFC) == 0x84) {
135                 /* skip code, but don't count the current block */
136                 skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
137             } else if (byte_b < 0x80) {
138                 /* 2-color encoding */
139                 flags = (byte_b << 8) | byte_a;
140 
141                 CHECK_STREAM_PTR(2);
142                 colors[0] = buf[stream_ptr++];
143                 colors[1] = buf[stream_ptr++];
144 
145                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
146                     for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
147                         pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1];
148                     pixel_ptr -= row_dec;
149                 }
150             } else if (byte_b >= 0x90) {
151                 /* 8-color encoding */
152                 flags = (byte_b << 8) | byte_a;
153 
154                 CHECK_STREAM_PTR(8);
155                 memcpy(colors, &buf[stream_ptr], 8);
156                 stream_ptr += 8;
157 
158                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
159                     for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
160                         pixels[pixel_ptr++] =
161                             colors[((pixel_y & 0x2) << 1) +
162                                 (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
163                     pixel_ptr -= row_dec;
164                 }
165             } else {
166                 /* 1-color encoding */
167                 colors[0] = byte_a;
168 
169                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
170                     for (pixel_x = 0; pixel_x < 4; pixel_x++)
171                         pixels[pixel_ptr++] = colors[0];
172                     pixel_ptr -= row_dec;
173                 }
174             }
175 
176             block_ptr += block_inc;
177             total_blocks--;
178         }
179     }
180 }
181 
182 static void
msvideo1_decode_16bit(int width,int height,const unsigned char * buf,int buf_size,unsigned short * pixels,int stride)183 msvideo1_decode_16bit( int width, int height, const unsigned char *buf, int buf_size,
184                        unsigned short *pixels, int stride)
185 {
186     int block_ptr, pixel_ptr;
187     int total_blocks;
188     int pixel_x, pixel_y;  /* pixel width and height iterators */
189     int block_x, block_y;  /* block width and height iterators */
190     int blocks_wide, blocks_high;  /* width and height in 4x4 blocks */
191     int block_inc;
192     int row_dec;
193 
194     /* decoding parameters */
195     int stream_ptr;
196     unsigned char byte_a, byte_b;
197     unsigned short flags;
198     int skip_blocks;
199     unsigned short colors[8];
200 
201     stream_ptr = 0;
202     skip_blocks = 0;
203     blocks_wide = width / 4;
204     blocks_high = height / 4;
205     total_blocks = blocks_wide * blocks_high;
206     block_inc = 4;
207 #ifdef ORIGINAL
208     row_dec = stride + 4;
209 #else
210     row_dec = - (stride - 4); /* such that -row_dec > 0 */
211 #endif
212 
213     for (block_y = blocks_high; block_y > 0; block_y--) {
214 #ifdef ORIGINAL
215         block_ptr = ((block_y * 4) - 1) * stride;
216 #else
217         block_ptr = ((blocks_high - block_y) * 4) * stride;
218 #endif
219         for (block_x = blocks_wide; block_x > 0; block_x--) {
220             /* check if this block should be skipped */
221             if (skip_blocks) {
222                 block_ptr += block_inc;
223                 skip_blocks--;
224                 total_blocks--;
225                 continue;
226             }
227 
228             pixel_ptr = block_ptr;
229 
230             /* get the next two bytes in the encoded data stream */
231             CHECK_STREAM_PTR(2);
232             byte_a = buf[stream_ptr++];
233             byte_b = buf[stream_ptr++];
234 
235             /* check if the decode is finished */
236             if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0)) {
237                 return;
238             } else if ((byte_b & 0xFC) == 0x84) {
239                 /* skip code, but don't count the current block */
240                 skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
241             } else if (byte_b < 0x80) {
242                 /* 2- or 8-color encoding modes */
243                 flags = (byte_b << 8) | byte_a;
244 
245                 CHECK_STREAM_PTR(4);
246                 colors[0] = LE_16(&buf[stream_ptr]);
247                 stream_ptr += 2;
248                 colors[1] = LE_16(&buf[stream_ptr]);
249                 stream_ptr += 2;
250 
251                 if (colors[0] & 0x8000) {
252                     /* 8-color encoding */
253                     CHECK_STREAM_PTR(12);
254                     colors[2] = LE_16(&buf[stream_ptr]);
255                     stream_ptr += 2;
256                     colors[3] = LE_16(&buf[stream_ptr]);
257                     stream_ptr += 2;
258                     colors[4] = LE_16(&buf[stream_ptr]);
259                     stream_ptr += 2;
260                     colors[5] = LE_16(&buf[stream_ptr]);
261                     stream_ptr += 2;
262                     colors[6] = LE_16(&buf[stream_ptr]);
263                     stream_ptr += 2;
264                     colors[7] = LE_16(&buf[stream_ptr]);
265                     stream_ptr += 2;
266 
267                     for (pixel_y = 0; pixel_y < 4; pixel_y++) {
268                         for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
269                             pixels[pixel_ptr++] =
270                                 colors[((pixel_y & 0x2) << 1) +
271                                     (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
272                         pixel_ptr -= row_dec;
273                     }
274                 } else {
275                     /* 2-color encoding */
276                     for (pixel_y = 0; pixel_y < 4; pixel_y++) {
277                         for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
278                             pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1];
279                         pixel_ptr -= row_dec;
280                     }
281                 }
282             } else {
283                 /* otherwise, it's a 1-color block */
284                 colors[0] = (byte_b << 8) | byte_a;
285 
286                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
287                     for (pixel_x = 0; pixel_x < 4; pixel_x++)
288                         pixels[pixel_ptr++] = colors[0];
289                     pixel_ptr -= row_dec;
290                 }
291             }
292 
293             block_ptr += block_inc;
294             total_blocks--;
295         }
296     }
297 }
298 
299 static LRESULT
CRAM_DecompressQuery(Msvideo1Context * info,LPBITMAPINFO in,LPBITMAPINFO out)300 CRAM_DecompressQuery( Msvideo1Context *info, LPBITMAPINFO in, LPBITMAPINFO out )
301 {
302     TRACE("ICM_DECOMPRESS_QUERY %p %p %p\n", info, in, out);
303 
304     if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) )
305         return ICERR_BADPARAM;
306 
307     TRACE("in->planes  = %d\n", in->bmiHeader.biPlanes );
308     TRACE("in->bpp     = %d\n", in->bmiHeader.biBitCount );
309     TRACE("in->height  = %d\n", in->bmiHeader.biHeight );
310     TRACE("in->width   = %d\n", in->bmiHeader.biWidth );
311     TRACE("in->compr   = 0x%x\n", in->bmiHeader.biCompression );
312 
313     if( ( in->bmiHeader.biCompression != CRAM_MAGIC ) &&
314         ( in->bmiHeader.biCompression != MSVC_MAGIC ) &&
315         ( in->bmiHeader.biCompression != WHAM_MAGIC ) )
316     {
317         TRACE("can't do 0x%x compression\n", in->bmiHeader.biCompression);
318         return ICERR_BADFORMAT;
319     }
320 
321     if( ( in->bmiHeader.biBitCount != 16 ) &&
322         ( in->bmiHeader.biBitCount != 8 ) )
323     {
324         TRACE("can't do %d bpp\n", in->bmiHeader.biBitCount );
325         return ICERR_BADFORMAT;
326     }
327 
328     /* output must be same dimensions as input */
329     if( out )
330     {
331         TRACE("out->planes = %d\n", out->bmiHeader.biPlanes );
332         TRACE("out->bpp    = %d\n", out->bmiHeader.biBitCount );
333         TRACE("out->height = %d\n", out->bmiHeader.biHeight );
334         TRACE("out->width  = %d\n", out->bmiHeader.biWidth );
335 
336         if ((in->bmiHeader.biBitCount != out->bmiHeader.biBitCount) &&
337             (in->bmiHeader.biBitCount != 16 || out->bmiHeader.biBitCount != 24))
338         {
339             TRACE("incompatible depth requested\n");
340             return ICERR_BADFORMAT;
341         }
342 
343         if(( in->bmiHeader.biPlanes != out->bmiHeader.biPlanes ) ||
344           ( in->bmiHeader.biHeight != out->bmiHeader.biHeight ) ||
345           ( in->bmiHeader.biWidth != out->bmiHeader.biWidth ))
346         {
347             TRACE("incompatible output requested\n");
348             return ICERR_BADFORMAT;
349         }
350     }
351 
352     TRACE("OK!\n");
353     return ICERR_OK;
354 }
355 
356 static LRESULT
CRAM_DecompressGetFormat(Msvideo1Context * info,LPBITMAPINFO in,LPBITMAPINFO out)357 CRAM_DecompressGetFormat( Msvideo1Context *info, LPBITMAPINFO in, LPBITMAPINFO out )
358 {
359     DWORD size;
360 
361     TRACE("ICM_DECOMPRESS_GETFORMAT %p %p %p\n", info, in, out);
362 
363     if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) )
364         return ICERR_BADPARAM;
365 
366     size = in->bmiHeader.biSize;
367     if (in->bmiHeader.biBitCount <= 8)
368         size += in->bmiHeader.biClrUsed * sizeof(RGBQUAD);
369 
370     if (in->bmiHeader.biBitCount != 8 && in->bmiHeader.biBitCount != 16)
371         return ICERR_BADFORMAT;
372 
373     if( out )
374     {
375         memcpy( out, in, size );
376         out->bmiHeader.biWidth = in->bmiHeader.biWidth & ~1;
377         out->bmiHeader.biHeight = in->bmiHeader.biHeight & ~1;
378         out->bmiHeader.biCompression = BI_RGB;
379         out->bmiHeader.biSizeImage = in->bmiHeader.biHeight *
380                                      get_stride(out->bmiHeader.biWidth, out->bmiHeader.biBitCount);
381         return ICERR_OK;
382     }
383 
384     return size;
385 }
386 
CRAM_DecompressBegin(Msvideo1Context * info,LPBITMAPINFO in,LPBITMAPINFO out)387 static LRESULT CRAM_DecompressBegin( Msvideo1Context *info, LPBITMAPINFO in, LPBITMAPINFO out )
388 {
389     TRACE("ICM_DECOMPRESS_BEGIN %p %p %p\n", info, in, out);
390 
391     if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) )
392         return ICERR_BADPARAM;
393 
394     TRACE("bitmap is %d bpp\n", in->bmiHeader.biBitCount);
395     if( in->bmiHeader.biBitCount == 8 )
396         info->depth = 8;
397     else if( in->bmiHeader.biBitCount == 16 )
398         info->depth = 16;
399     else
400     {
401         info->depth = 0;
402         FIXME("Unsupported output format %i\n", in->bmiHeader.biBitCount);
403     }
404 
405     return ICERR_OK;
406 }
407 
convert_depth(char * input,int depth_in,char * output,BITMAPINFOHEADER * out_hdr)408 static void convert_depth(char *input, int depth_in, char *output, BITMAPINFOHEADER *out_hdr)
409 {
410     int x, y;
411     int stride_in  = get_stride(out_hdr->biWidth, depth_in);
412     int stride_out = get_stride(out_hdr->biWidth, out_hdr->biBitCount);
413 
414     if (depth_in == 16 && out_hdr->biBitCount == 24)
415     {
416         static const unsigned char convert_5to8[] =
417         {
418             0x00, 0x08, 0x10, 0x19, 0x21, 0x29, 0x31, 0x3a,
419             0x42, 0x4a, 0x52, 0x5a, 0x63, 0x6b, 0x73, 0x7b,
420             0x84, 0x8c, 0x94, 0x9c, 0xa5, 0xad, 0xb5, 0xbd,
421             0xc5, 0xce, 0xd6, 0xde, 0xe6, 0xef, 0xf7, 0xff,
422         };
423 
424         for (y = 0; y < out_hdr->biHeight; y++)
425         {
426             WORD *src_row = (WORD *)(input + y * stride_in);
427             char *out_row = output + y * stride_out;
428 
429             for (x = 0; x < out_hdr->biWidth; x++)
430             {
431                 WORD pixel = *src_row++;
432                 *out_row++ = convert_5to8[(pixel & 0x7c00u) >> 10];
433                 *out_row++ = convert_5to8[(pixel & 0x03e0u) >> 5];
434                 *out_row++ = convert_5to8[(pixel & 0x001fu)];
435             }
436         }
437     }
438     else
439         FIXME("Conversion from %d to %d bit unimplemented\n", depth_in, out_hdr->biBitCount);
440 }
441 
CRAM_Decompress(Msvideo1Context * info,ICDECOMPRESS * icd,DWORD size)442 static LRESULT CRAM_Decompress( Msvideo1Context *info, ICDECOMPRESS *icd, DWORD size )
443 {
444     LONG width, height, stride, sz;
445     void *output;
446 
447     TRACE("ICM_DECOMPRESS %p %p %d\n", info, icd, size);
448 
449     if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) )
450         return ICERR_BADPARAM;
451 
452     /* FIXME: flags are ignored */
453 
454     width  = icd->lpbiInput->biWidth;
455     height = icd->lpbiInput->biHeight;
456     sz = icd->lpbiInput->biSizeImage;
457 
458     output = icd->lpOutput;
459 
460     if (icd->lpbiOutput->biBitCount != info->depth)
461     {
462         output = HeapAlloc(GetProcessHeap(), 0, icd->lpbiOutput->biWidth * icd->lpbiOutput->biHeight * info->depth / 8);
463         if (!output) return ICERR_MEMORY;
464     }
465 
466     if (info->depth == 8)
467     {
468         stride = get_stride(width, 8);
469         msvideo1_decode_8bit( width, height, icd->lpInput, sz,
470                               output, stride );
471     }
472     else
473     {
474         stride = get_stride(width, 16) / 2;
475         msvideo1_decode_16bit( width, height, icd->lpInput, sz,
476                                output, stride );
477     }
478 
479     if (icd->lpbiOutput->biBitCount != info->depth)
480     {
481         convert_depth(output, info->depth, icd->lpOutput, icd->lpbiOutput);
482         HeapFree(GetProcessHeap(), 0, output);
483     }
484 
485     return ICERR_OK;
486 }
487 
CRAM_DecompressEx(Msvideo1Context * info,ICDECOMPRESSEX * icd,DWORD size)488 static LRESULT CRAM_DecompressEx( Msvideo1Context *info, ICDECOMPRESSEX *icd, DWORD size )
489 {
490     LONG width, height, stride, sz;
491     void *output;
492 
493     TRACE("ICM_DECOMPRESSEX %p %p %d\n", info, icd, size);
494 
495     if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) )
496         return ICERR_BADPARAM;
497 
498     /* FIXME: flags are ignored */
499 
500     width  = icd->lpbiSrc->biWidth;
501     height = icd->lpbiSrc->biHeight;
502     sz = icd->lpbiSrc->biSizeImage;
503 
504     output = icd->lpDst;
505 
506     if (icd->lpbiDst->biBitCount != info->depth)
507     {
508         output = HeapAlloc(GetProcessHeap(), 0, icd->lpbiDst->biWidth * icd->lpbiDst->biHeight * info->depth / 8);
509         if (!output) return ICERR_MEMORY;
510     }
511 
512     if (info->depth == 8)
513     {
514         stride = get_stride(width, 8);
515         msvideo1_decode_8bit( width, height, icd->lpSrc, sz,
516                               output, stride );
517     }
518     else
519     {
520         stride = get_stride(width, 16) / 2;
521         msvideo1_decode_16bit( width, height, icd->lpSrc, sz,
522                                output, stride );
523     }
524 
525     if (icd->lpbiDst->biBitCount != info->depth)
526     {
527         convert_depth(output, info->depth, icd->lpDst, icd->lpbiDst);
528         HeapFree(GetProcessHeap(), 0, output);
529     }
530 
531     return ICERR_OK;
532 }
533 
CRAM_GetInfo(const Msvideo1Context * info,ICINFO * icinfo,DWORD dwSize)534 static LRESULT CRAM_GetInfo( const Msvideo1Context *info, ICINFO *icinfo, DWORD dwSize )
535 {
536     if (!icinfo) return sizeof(ICINFO);
537     if (dwSize < sizeof(ICINFO)) return 0;
538 
539     icinfo->dwSize = sizeof(ICINFO);
540     icinfo->fccType = ICTYPE_VIDEO;
541 #ifdef __REACTOS__
542     icinfo->fccHandler = MSVC_MAGIC;
543 #else
544     icinfo->fccHandler = info ? info->dwMagic : CRAM_MAGIC;
545 #endif
546     icinfo->dwFlags = 0;
547     icinfo->dwVersion = ICVERSION;
548     icinfo->dwVersionICM = ICVERSION;
549 
550     LoadStringW(MSVIDC32_hModule, IDS_NAME, icinfo->szName, ARRAY_SIZE(icinfo->szName));
551     LoadStringW(MSVIDC32_hModule, IDS_DESCRIPTION, icinfo->szDescription, ARRAY_SIZE(icinfo->szDescription));
552     /* msvfw32 will fill icinfo->szDriver for us */
553 
554     return sizeof(ICINFO);
555 }
556 
557 /***********************************************************************
558  *		DriverProc (MSVIDC32.@)
559  */
CRAM_DriverProc(DWORD_PTR dwDriverId,HDRVR hdrvr,UINT msg,LPARAM lParam1,LPARAM lParam2)560 LRESULT WINAPI CRAM_DriverProc( DWORD_PTR dwDriverId, HDRVR hdrvr, UINT msg,
561                                 LPARAM lParam1, LPARAM lParam2 )
562 {
563     Msvideo1Context *info = (Msvideo1Context *) dwDriverId;
564     LRESULT r = ICERR_UNSUPPORTED;
565 
566     TRACE("%ld %p %04x %08lx %08lx\n", dwDriverId, hdrvr, msg, lParam1, lParam2);
567 
568     switch( msg )
569     {
570     case DRV_LOAD:
571         TRACE("Loaded\n");
572         r = 1;
573         break;
574 
575     case DRV_ENABLE:
576         break;
577 
578     case DRV_OPEN:
579     {
580         ICINFO *icinfo = (ICINFO *)lParam2;
581 
582         TRACE("Opened\n");
583 
584         if (icinfo && compare_fourcc(icinfo->fccType, ICTYPE_VIDEO)) return 0;
585 
586         info = HeapAlloc( GetProcessHeap(), 0, sizeof (Msvideo1Context) );
587         if( info )
588         {
589             memset( info, 0, sizeof *info );
590             info->dwMagic = CRAM_MAGIC;
591         }
592         r = (LRESULT) info;
593         break;
594     }
595 
596     case DRV_CLOSE:
597         HeapFree( GetProcessHeap(), 0, info );
598         break;
599 
600     case DRV_DISABLE:
601         break;
602 
603     case DRV_FREE:
604         break;
605 
606     case ICM_GETINFO:
607         r = CRAM_GetInfo( info, (ICINFO *)lParam1, (DWORD)lParam2 );
608         break;
609 
610     case ICM_DECOMPRESS_QUERY:
611         r = CRAM_DecompressQuery( info, (LPBITMAPINFO) lParam1,
612                                        (LPBITMAPINFO) lParam2 );
613         break;
614 
615     case ICM_DECOMPRESS_GET_FORMAT:
616         r = CRAM_DecompressGetFormat( info, (LPBITMAPINFO) lParam1,
617                                        (LPBITMAPINFO) lParam2 );
618         break;
619 
620     case ICM_DECOMPRESS_GET_PALETTE:
621         FIXME("ICM_DECOMPRESS_GET_PALETTE\n");
622         break;
623 
624     case ICM_DECOMPRESSEX_QUERY:
625         FIXME("ICM_DECOMPRESSEX_QUERY\n");
626         break;
627 
628     case ICM_DECOMPRESS:
629         r = CRAM_Decompress( info, (ICDECOMPRESS*) lParam1,
630                                   (DWORD) lParam2 );
631         break;
632 
633     case ICM_DECOMPRESS_BEGIN:
634         r = CRAM_DecompressBegin( info, (LPBITMAPINFO) lParam1,
635                                        (LPBITMAPINFO) lParam2 );
636         break;
637 
638     case ICM_DECOMPRESSEX:
639         r = CRAM_DecompressEx( info, (ICDECOMPRESSEX*) lParam1,
640                                   (DWORD) lParam2 );
641         break;
642 
643     case ICM_DECOMPRESS_END:
644         r = ICERR_OK;
645         break;
646 
647     case ICM_COMPRESS_QUERY:
648         r = ICERR_BADFORMAT;
649         /* fall through */
650     case ICM_COMPRESS_GET_FORMAT:
651     case ICM_COMPRESS_END:
652     case ICM_COMPRESS:
653         FIXME("compression not implemented\n");
654         break;
655 
656     case ICM_CONFIGURE:
657         break;
658 
659     default:
660         FIXME("Unknown message: %04x %ld %ld\n", msg, lParam1, lParam2);
661     }
662 
663     return r;
664 }
665 
666 /***********************************************************************
667  *		DllMain
668  */
DllMain(HINSTANCE hModule,DWORD dwReason,LPVOID lpReserved)669 BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved)
670 {
671     TRACE("(%p,%d,%p)\n", hModule, dwReason, lpReserved);
672 
673     switch (dwReason)
674     {
675     case DLL_PROCESS_ATTACH:
676         DisableThreadLibraryCalls(hModule);
677         MSVIDC32_hModule = hModule;
678         break;
679     }
680     return TRUE;
681 }
682