ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

iccvid.c
Go to the documentation of this file.
00001 /*
00002  * Radius Cinepak Video Decoder
00003  *
00004  * Copyright 2001 Dr. Tim Ferguson (see below)
00005  * Portions Copyright 2003 Mike McCormack for CodeWeavers
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 /* Copyright notice from original source:
00023  * ------------------------------------------------------------------------
00024  * Radius Cinepak Video Decoder
00025  *
00026  * Dr. Tim Ferguson, 2001.
00027  * For more details on the algorithm:
00028  *         http://www.csse.monash.edu.au/~timf/videocodec.html
00029  *
00030  * This is basically a vector quantiser with adaptive vector density.  The
00031  * frame is segmented into 4x4 pixel blocks, and each block is coded using
00032  * either 1 or 4 vectors.
00033  *
00034  * There are still some issues with this code yet to be resolved.  In
00035  * particular with decoding in the strip boundaries.  However, I have not
00036  * yet found a sequence it doesn't work on.  Ill keep trying :)
00037  *
00038  * You may freely use this source code.  I only ask that you reference its
00039  * source in your projects documentation:
00040  *       Tim Ferguson: http://www.csse.monash.edu.au/~timf/
00041  * ------------------------------------------------------------------------ */
00042 
00043 #include <stdarg.h>
00044 #include "windef.h"
00045 #include "winbase.h"
00046 #include "wingdi.h"
00047 #include "winuser.h"
00048 #include "commdlg.h"
00049 #include "vfw.h"
00050 #include "mmsystem.h"
00051 #include "iccvid_private.h"
00052 
00053 #include "wine/debug.h"
00054 
00055 WINE_DEFAULT_DEBUG_CHANNEL(iccvid);
00056 
00057 static HINSTANCE ICCVID_hModule;
00058 
00059 #define ICCVID_MAGIC mmioFOURCC('c', 'v', 'i', 'd')
00060 #define compare_fourcc(fcc1, fcc2) (((fcc1)^(fcc2))&~0x20202020)
00061 
00062 #define DBUG    0
00063 #define MAX_STRIPS 32
00064 
00065 /* ------------------------------------------------------------------------ */
00066 typedef struct
00067 {
00068     unsigned char y0, y1, y2, y3;
00069     char u, v;
00070     unsigned char r[4], g[4], b[4];
00071 } cvid_codebook;
00072 
00073 typedef struct {
00074     cvid_codebook *v4_codebook[MAX_STRIPS];
00075     cvid_codebook *v1_codebook[MAX_STRIPS];
00076     unsigned int strip_num;
00077 } cinepak_info;
00078 
00079 typedef struct _ICCVID_Info
00080 {
00081     DWORD         dwMagic;
00082     int           bits_per_pixel;
00083     cinepak_info *cvinfo;
00084 } ICCVID_Info;
00085 
00086 static inline LPVOID heap_alloc( size_t size )
00087 {
00088     return HeapAlloc( GetProcessHeap(), 0, size );
00089 }
00090 
00091 static inline BOOL heap_free( LPVOID ptr )
00092 {
00093     return HeapFree( GetProcessHeap(), 0, ptr );
00094 }
00095 
00096 
00097 /* ------------------------------------------------------------------------ */
00098 static unsigned char *in_buffer, uiclip[1024], *uiclp = NULL;
00099 
00100 #define get_byte() *(in_buffer++)
00101 #define skip_byte() in_buffer++
00102 #define get_word() ((unsigned short)(in_buffer += 2, \
00103     (in_buffer[-2] << 8 | in_buffer[-1])))
00104 #define get_long() ((unsigned long)(in_buffer += 4, \
00105     (in_buffer[-4] << 24 | in_buffer[-3] << 16 | in_buffer[-2] << 8 | in_buffer[-1])))
00106 
00107 
00108 /* ---------------------------------------------------------------------- */
00109 static inline void read_codebook(cvid_codebook *c, int mode)
00110 {
00111 int uvr, uvg, uvb;
00112 
00113     if(mode)        /* black and white */
00114         {
00115         c->y0 = get_byte();
00116         c->y1 = get_byte();
00117         c->y2 = get_byte();
00118         c->y3 = get_byte();
00119         c->u = c->v = 0;
00120 
00121         c->r[0] = c->g[0] = c->b[0] = c->y0;
00122         c->r[1] = c->g[1] = c->b[1] = c->y1;
00123         c->r[2] = c->g[2] = c->b[2] = c->y2;
00124         c->r[3] = c->g[3] = c->b[3] = c->y3;
00125         }
00126     else            /* colour */
00127         {
00128         c->y0 = get_byte();  /* luma */
00129         c->y1 = get_byte();
00130         c->y2 = get_byte();
00131         c->y3 = get_byte();
00132         c->u = get_byte(); /* chroma */
00133         c->v = get_byte();
00134 
00135         uvr = c->v << 1;
00136         uvg = -((c->u+1) >> 1) - c->v;
00137         uvb = c->u << 1;
00138 
00139         c->r[0] = uiclp[c->y0 + uvr]; c->g[0] = uiclp[c->y0 + uvg]; c->b[0] = uiclp[c->y0 + uvb];
00140         c->r[1] = uiclp[c->y1 + uvr]; c->g[1] = uiclp[c->y1 + uvg]; c->b[1] = uiclp[c->y1 + uvb];
00141         c->r[2] = uiclp[c->y2 + uvr]; c->g[2] = uiclp[c->y2 + uvg]; c->b[2] = uiclp[c->y2 + uvb];
00142         c->r[3] = uiclp[c->y3 + uvr]; c->g[3] = uiclp[c->y3 + uvg]; c->b[3] = uiclp[c->y3 + uvb];
00143         }
00144 }
00145 
00146 
00147 #define MAKECOLOUR32(r,g,b) (((r) << 16) | ((g) << 8) | (b))
00148 /*#define MAKECOLOUR24(r,g,b) (((r) << 16) | ((g) << 8) | (b))*/
00149 #define MAKECOLOUR16(r,g,b) (((r) >> 3) << 11)| (((g) >> 2) << 5)| (((b) >> 3) << 0)
00150 #define MAKECOLOUR15(r,g,b) (((r) >> 3) << 10)| (((g) >> 3) << 5)| (((b) >> 3) << 0)
00151 
00152 /* ------------------------------------------------------------------------ */
00153 static void cvid_v1_32(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb)
00154 {
00155 unsigned long *vptr = (unsigned long *)frm;
00156 #ifndef ORIGINAL
00157 int row_inc = -stride/4;
00158 #else
00159 int row_inc = stride/4;
00160 #endif
00161 int x, y;
00162 
00163     /* fill 4x4 block of pixels with colour values from codebook */
00164     for (y = 0; y < 4; y++)
00165     {
00166         if (&vptr[y*row_inc] < (unsigned long *)limit) return;
00167         for (x = 0; x < 4; x++)
00168             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]);
00169     }
00170 }
00171 
00172 
00173 /* ------------------------------------------------------------------------ */
00174 static void cvid_v4_32(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0,
00175     cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
00176 {
00177 unsigned long *vptr = (unsigned long *)frm;
00178 #ifndef ORIGINAL
00179 int row_inc = -stride/4;
00180 #else
00181 int row_inc = stride/4;
00182 #endif
00183 int x, y;
00184 cvid_codebook * cb[] = {cb0,cb1,cb2,cb3};
00185 
00186     /* fill 4x4 block of pixels with colour values from codebooks */
00187     for (y = 0; y < 4; y++)
00188     {
00189         if (&vptr[y*row_inc] < (unsigned long *)limit) return;
00190         for (x = 0; x < 4; x++)
00191             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]);
00192     }
00193 }
00194 
00195 
00196 /* ------------------------------------------------------------------------ */
00197 static void cvid_v1_24(unsigned char *vptr, unsigned char *limit, int stride, cvid_codebook *cb)
00198 {
00199 #ifndef ORIGINAL
00200 int row_inc = -stride;
00201 #else
00202 int row_inc = stride;
00203 #endif
00204 int x, y;
00205 
00206     /* fill 4x4 block of pixels with colour values from codebook */
00207     for (y = 0; y < 4; y++)
00208     {
00209         if (&vptr[y*row_inc] < limit) return;
00210         for (x = 0; x < 4; x++)
00211         {
00212             vptr[y*row_inc + x*3 + 0] = cb->b[x/2+(y/2)*2];
00213             vptr[y*row_inc + x*3 + 1] = cb->g[x/2+(y/2)*2];
00214             vptr[y*row_inc + x*3 + 2] = cb->r[x/2+(y/2)*2];
00215         }
00216     }
00217 }
00218 
00219 
00220 /* ------------------------------------------------------------------------ */
00221 static void cvid_v4_24(unsigned char *vptr, unsigned char *limit, int stride, cvid_codebook *cb0,
00222     cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
00223 {
00224 #ifndef ORIGINAL
00225 int row_inc = -stride;
00226 #else
00227 int row_inc = stride;
00228 #endif
00229 cvid_codebook * cb[] = {cb0,cb1,cb2,cb3};
00230 int x, y;
00231 
00232     /* fill 4x4 block of pixels with colour values from codebooks */
00233     for (y = 0; y < 4; y++)
00234     {
00235         if (&vptr[y*row_inc] < limit) return;
00236         for (x = 0; x < 4; x++)
00237         {
00238             vptr[y*row_inc + x*3 + 0] = cb[x/2+(y/2)*2]->b[x%2+(y%2)*2];
00239             vptr[y*row_inc + x*3 + 1] = cb[x/2+(y/2)*2]->g[x%2+(y%2)*2];
00240             vptr[y*row_inc + x*3 + 2] = cb[x/2+(y/2)*2]->r[x%2+(y%2)*2];
00241         }
00242     }
00243 }
00244 
00245 
00246 /* ------------------------------------------------------------------------ */
00247 static void cvid_v1_16(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb)
00248 {
00249 unsigned short *vptr = (unsigned short *)frm;
00250 #ifndef ORIGINAL
00251 int row_inc = -stride/2;
00252 #else
00253 int row_inc = stride/2;
00254 #endif
00255 int x, y;
00256 
00257     /* fill 4x4 block of pixels with colour values from codebook */
00258     for (y = 0; y < 4; y++)
00259     {
00260         if (&vptr[y*row_inc] < (unsigned short *)limit) return;
00261         for (x = 0; x < 4; x++)
00262             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]);
00263     }
00264 }
00265 
00266 
00267 /* ------------------------------------------------------------------------ */
00268 static void cvid_v4_16(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0,
00269     cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
00270 {
00271 unsigned short *vptr = (unsigned short *)frm;
00272 #ifndef ORIGINAL
00273 int row_inc = -stride/2;
00274 #else
00275 int row_inc = stride/2;
00276 #endif
00277 cvid_codebook * cb[] = {cb0,cb1,cb2,cb3};
00278 int x, y;
00279 
00280     /* fill 4x4 block of pixels with colour values from codebooks */
00281     for (y = 0; y < 4; y++)
00282     {
00283         if (&vptr[y*row_inc] < (unsigned short *)limit) return;
00284         for (x = 0; x < 4; x++)
00285             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]);
00286     }
00287 }
00288 
00289 /* ------------------------------------------------------------------------ */
00290 static void cvid_v1_15(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb)
00291 {
00292 unsigned short *vptr = (unsigned short *)frm;
00293 #ifndef ORIGINAL
00294 int row_inc = -stride/2;
00295 #else
00296 int row_inc = stride/2;
00297 #endif
00298 int x, y;
00299 
00300     /* fill 4x4 block of pixels with colour values from codebook */
00301     for (y = 0; y < 4; y++)
00302     {
00303         if (&vptr[y*row_inc] < (unsigned short *)limit) return;
00304         for (x = 0; x < 4; x++)
00305             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]);
00306     }
00307 }
00308 
00309 
00310 /* ------------------------------------------------------------------------ */
00311 static void cvid_v4_15(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0,
00312     cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
00313 {
00314 unsigned short *vptr = (unsigned short *)frm;
00315 #ifndef ORIGINAL
00316 int row_inc = -stride/2;
00317 #else
00318 int row_inc = stride/2;
00319 #endif
00320 cvid_codebook * cb[] = {cb0,cb1,cb2,cb3};
00321 int x, y;
00322 
00323     /* fill 4x4 block of pixels with colour values from codebooks */
00324     for (y = 0; y < 4; y++)
00325     {
00326         if (&vptr[y*row_inc] < (unsigned short *)limit) return;
00327         for (x = 0; x < 4; x++)
00328             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]);
00329     }
00330 }
00331 
00332 
00333 /* ------------------------------------------------------------------------
00334  * Call this function once at the start of the sequence and save the
00335  * returned context for calls to decode_cinepak().
00336  */
00337 static cinepak_info *decode_cinepak_init(void)
00338 {
00339     cinepak_info *cvinfo;
00340     int i;
00341 
00342     cvinfo = heap_alloc( sizeof (cinepak_info) );
00343     if( !cvinfo )
00344         return NULL;
00345     cvinfo->strip_num = 0;
00346 
00347     if(uiclp == NULL)
00348     {
00349         uiclp = uiclip+512;
00350         for(i = -512; i < 512; i++)
00351             uiclp[i] = (i < 0 ? 0 : (i > 255 ? 255 : i));
00352     }
00353 
00354     return cvinfo;
00355 }
00356 
00357 static void free_cvinfo( cinepak_info *cvinfo )
00358 {
00359     unsigned int i;
00360 
00361     for( i=0; i<cvinfo->strip_num; i++ )
00362     {
00363         heap_free(cvinfo->v4_codebook[i]);
00364         heap_free(cvinfo->v1_codebook[i]);
00365     }
00366     heap_free( cvinfo );
00367 }
00368 
00369 typedef void (*fn_cvid_v1)(unsigned char *frm, unsigned char *limit,
00370                            int stride, cvid_codebook *cb);
00371 typedef void (*fn_cvid_v4)(unsigned char *frm, unsigned char *limit, int stride,
00372                            cvid_codebook *cb0, cvid_codebook *cb1,
00373                            cvid_codebook *cb2, cvid_codebook *cb3);
00374 
00375 /* ------------------------------------------------------------------------
00376  * This function decodes a buffer containing a Cinepak encoded frame.
00377  *
00378  * context - the context created by decode_cinepak_init().
00379  * buf - the input buffer to be decoded
00380  * size - the size of the input buffer
00381  * frame - the output frame buffer (24 or 32 bit per pixel)
00382  * width - the width of the output frame
00383  * height - the height of the output frame
00384  * bit_per_pixel - the number of bits per pixel allocated to the output
00385  *   frame (only 24 or 32 bpp are supported)
00386  */
00387 static void decode_cinepak(cinepak_info *cvinfo, unsigned char *buf, int size,
00388            unsigned char *frame, unsigned int width, unsigned int height, int bit_per_pixel)
00389 {
00390     cvid_codebook *v4_codebook, *v1_codebook, *codebook = NULL;
00391     unsigned long x, y, y_bottom, frame_flags, strips, cv_width, cv_height,
00392                   cnum, strip_id, chunk_id, x0, y0, x1, y1, ci, flag, mask;
00393     long len, top_size, chunk_size;
00394     unsigned char *frm_ptr;
00395     unsigned int i, cur_strip;
00396     int d0, d1, d2, d3, frm_stride, bpp = 3;
00397     fn_cvid_v1 cvid_v1 = cvid_v1_24;
00398     fn_cvid_v4 cvid_v4 = cvid_v4_24;
00399 
00400     y = 0;
00401     y_bottom = 0;
00402     in_buffer = buf;
00403 
00404     frame_flags = get_byte();
00405     len = get_byte() << 16;
00406     len |= get_byte() << 8;
00407     len |= get_byte();
00408 
00409     switch(bit_per_pixel)
00410         {
00411         case 15:
00412             bpp = 2;
00413             cvid_v1 = cvid_v1_15;
00414             cvid_v4 = cvid_v4_15;
00415             break;
00416         case 16:
00417             bpp = 2;
00418             cvid_v1 = cvid_v1_16;
00419             cvid_v4 = cvid_v4_16;
00420             break;
00421         case 24:
00422             bpp = 3;
00423             cvid_v1 = cvid_v1_24;
00424             cvid_v4 = cvid_v4_24;
00425             break;
00426         case 32:
00427             bpp = 4;
00428             cvid_v1 = cvid_v1_32;
00429             cvid_v4 = cvid_v4_32;
00430             break;
00431         }
00432 
00433     frm_stride = width * bpp;
00434     frm_ptr = frame;
00435 
00436     if(len != size)
00437         {
00438         if(len & 0x01) len++; /* AVIs tend to have a size mismatch */
00439         if(len != size)
00440             {
00441             ERR("CVID: corruption %d (QT/AVI) != %ld (CV)\n", size, len);
00442             /* return; */
00443             }
00444         }
00445 
00446     cv_width = get_word();
00447     cv_height = get_word();
00448     strips = get_word();
00449 
00450     if(strips > cvinfo->strip_num)
00451         {
00452         if(strips >= MAX_STRIPS)
00453             {
00454             ERR("CVID: strip overflow (more than %d)\n", MAX_STRIPS);
00455             return;
00456             }
00457 
00458         for(i = cvinfo->strip_num; i < strips; i++)
00459             {
00460             if((cvinfo->v4_codebook[i] = heap_alloc(sizeof(cvid_codebook) * 260)) == NULL)
00461                 {
00462                 ERR("CVID: codebook v4 alloc err\n");
00463                 return;
00464                 }
00465 
00466             if((cvinfo->v1_codebook[i] = heap_alloc(sizeof(cvid_codebook) * 260)) == NULL)
00467                 {
00468                 ERR("CVID: codebook v1 alloc err\n");
00469                 return;
00470                 }
00471             }
00472         }
00473     cvinfo->strip_num = strips;
00474 
00475     TRACE("CVID: <%ld,%ld> strips %ld\n", cv_width, cv_height, strips);
00476 
00477     for(cur_strip = 0; cur_strip < strips; cur_strip++)
00478         {
00479         v4_codebook = cvinfo->v4_codebook[cur_strip];
00480         v1_codebook = cvinfo->v1_codebook[cur_strip];
00481 
00482         if((cur_strip > 0) && (!(frame_flags & 0x01)))
00483             {
00484             memcpy(cvinfo->v4_codebook[cur_strip], cvinfo->v4_codebook[cur_strip-1], 260 * sizeof(cvid_codebook));
00485             memcpy(cvinfo->v1_codebook[cur_strip], cvinfo->v1_codebook[cur_strip-1], 260 * sizeof(cvid_codebook));
00486             }
00487 
00488         strip_id = get_word();        /* 1000 = key strip, 1100 = iter strip */
00489         top_size = get_word();
00490         y0 = get_word();        /* FIXME: most of these are ignored at the moment */
00491         x0 = get_word();
00492         y1 = get_word();
00493         x1 = get_word();
00494 
00495         y_bottom += y1;
00496         top_size -= 12;
00497         x = 0;
00498         if(x1 != width)
00499             WARN("CVID: Warning x1 (%ld) != width (%d)\n", x1, width);
00500 
00501         TRACE("   %d) %04lx %04ld <%ld,%ld> <%ld,%ld> yt %ld\n",
00502               cur_strip, strip_id, top_size, x0, y0, x1, y1, y_bottom);
00503 
00504         while(top_size > 0)
00505             {
00506             chunk_id  = get_word();
00507             chunk_size = get_word();
00508 
00509             TRACE("        %04lx %04ld\n", chunk_id, chunk_size);
00510             top_size -= chunk_size;
00511             chunk_size -= 4;
00512 
00513             switch(chunk_id)
00514                 {
00515                     /* -------------------- Codebook Entries -------------------- */
00516                 case 0x2000:
00517                 case 0x2200:
00518                     codebook = (chunk_id == 0x2200 ? v1_codebook : v4_codebook);
00519                     cnum = chunk_size/6;
00520                     for(i = 0; i < cnum; i++) read_codebook(codebook+i, 0);
00521                     break;
00522 
00523                 case 0x2400:
00524                 case 0x2600:        /* 8 bit per pixel */
00525                     codebook = (chunk_id == 0x2600 ? v1_codebook : v4_codebook);
00526                     cnum = chunk_size/4;
00527                     for(i = 0; i < cnum; i++) read_codebook(codebook+i, 1);
00528                     break;
00529 
00530                 case 0x2100:
00531                 case 0x2300:
00532                     codebook = (chunk_id == 0x2300 ? v1_codebook : v4_codebook);
00533 
00534                     ci = 0;
00535                     while(chunk_size > 0)
00536                         {
00537                         flag = get_long();
00538                         chunk_size -= 4;
00539 
00540                         for(i = 0; i < 32; i++)
00541                             {
00542                             if(flag & 0x80000000)
00543                                 {
00544                                 chunk_size -= 6;
00545                                 read_codebook(codebook+ci, 0);
00546                                 }
00547 
00548                             ci++;
00549                             flag <<= 1;
00550                             }
00551                         }
00552                     while(chunk_size > 0) { skip_byte(); chunk_size--; }
00553                     break;
00554 
00555                 case 0x2500:
00556                 case 0x2700:        /* 8 bit per pixel */
00557                     codebook = (chunk_id == 0x2700 ? v1_codebook : v4_codebook);
00558 
00559                     ci = 0;
00560                     while(chunk_size > 0)
00561                         {
00562                         flag = get_long();
00563                         chunk_size -= 4;
00564 
00565                         for(i = 0; i < 32; i++)
00566                             {
00567                             if(flag & 0x80000000)
00568                                 {
00569                                 chunk_size -= 4;
00570                                 read_codebook(codebook+ci, 1);
00571                                 }
00572 
00573                             ci++;
00574                             flag <<= 1;
00575                             }
00576                         }
00577                     while(chunk_size > 0) { skip_byte(); chunk_size--; }
00578                     break;
00579 
00580                     /* -------------------- Frame -------------------- */
00581                 case 0x3000:
00582                     while((chunk_size > 0) && (y < y_bottom))
00583                         {
00584                         flag = get_long();
00585                         chunk_size -= 4;
00586 
00587                         for(i = 0; i < 32; i++)
00588                             {
00589                             if(y >= y_bottom) break;
00590                             if(flag & 0x80000000)    /* 4 bytes per block */
00591                                 {
00592                                 d0 = get_byte();
00593                                 d1 = get_byte();
00594                                 d2 = get_byte();
00595                                 d3 = get_byte();
00596                                 chunk_size -= 4;
00597 #ifdef ORIGINAL
00598                                 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);
00599 #else
00600                                 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);
00601 #endif
00602                                 }
00603                             else        /* 1 byte per block */
00604                                 {
00605 #ifdef ORIGINAL
00606                                 cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte());
00607 #else
00608                                 cvid_v1(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v1_codebook + get_byte());
00609 #endif
00610                                 chunk_size--;
00611                                 }
00612 
00613                             x += 4;
00614                             if(x >= width)
00615                                 {
00616                                 x = 0;
00617                                 y += 4;
00618                                 }
00619                             flag <<= 1;
00620                             }
00621                         }
00622                     while(chunk_size > 0) { skip_byte(); chunk_size--; }
00623                     break;
00624 
00625                 case 0x3100:
00626                     while((chunk_size > 0) && (y < y_bottom))
00627                         {
00628                             /* ---- flag bits: 0 = SKIP, 10 = V1, 11 = V4 ---- */
00629                         flag = get_long();
00630                         chunk_size -= 4;
00631                         mask = 0x80000000;
00632 
00633                         while((mask) && (y < y_bottom))
00634                             {
00635                             if(flag & mask)
00636                                 {
00637                                 if(mask == 1)
00638                                     {
00639                                     if(chunk_size < 0) break;
00640                                     flag = get_long();
00641                                     chunk_size -= 4;
00642                                     mask = 0x80000000;
00643                                     }
00644                                 else mask >>= 1;
00645 
00646                                 if(flag & mask)        /* V4 */
00647                                     {
00648                                     d0 = get_byte();
00649                                     d1 = get_byte();
00650                                     d2 = get_byte();
00651                                     d3 = get_byte();
00652                                     chunk_size -= 4;
00653 #ifdef ORIGINAL
00654                                     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);
00655 #else
00656                                     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);
00657 #endif
00658                                     }
00659                                 else        /* V1 */
00660                                     {
00661                                     chunk_size--;
00662 #ifdef ORIGINAL
00663                                     cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte());
00664 #else
00665                                     cvid_v1(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v1_codebook + get_byte());
00666 #endif
00667                                     }
00668                                 }        /* else SKIP */
00669 
00670                             mask >>= 1;
00671                             x += 4;
00672                             if(x >= width)
00673                                 {
00674                                 x = 0;
00675                                 y += 4;
00676                                 }
00677                             }
00678                         }
00679 
00680                     while(chunk_size > 0) { skip_byte(); chunk_size--; }
00681                     break;
00682 
00683                 case 0x3200:        /* each byte is a V1 codebook */
00684                     while((chunk_size > 0) && (y < y_bottom))
00685                         {
00686 #ifdef ORIGINAL
00687                         cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte());
00688 #else
00689                         cvid_v1(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v1_codebook + get_byte());
00690 #endif
00691                         chunk_size--;
00692                         x += 4;
00693                         if(x >= width)
00694                             {
00695                             x = 0;
00696                             y += 4;
00697                             }
00698                         }
00699                     while(chunk_size > 0) { skip_byte(); chunk_size--; }
00700                     break;
00701 
00702                 default:
00703                     ERR("CVID: unknown chunk_id %08lx\n", chunk_id);
00704                     while(chunk_size > 0) { skip_byte(); chunk_size--; }
00705                     break;
00706                 }
00707             }
00708         }
00709 
00710     if(len != size)
00711         {
00712         if(len & 0x01) len++; /* AVIs tend to have a size mismatch */
00713         if(len != size)
00714             {
00715             long xlen;
00716             skip_byte();
00717             xlen = get_byte() << 16;
00718             xlen |= get_byte() << 8;
00719             xlen |= get_byte(); /* Read Len */
00720             WARN("CVID: END INFO chunk size %d cvid size1 %ld cvid size2 %ld\n",
00721                   size, len, xlen);
00722             }
00723         }
00724 }
00725 
00726 static void ICCVID_dump_BITMAPINFO(const BITMAPINFO * bmi)
00727 {
00728     TRACE(
00729         "planes = %d\n"
00730         "bpp    = %d\n"
00731         "height = %d\n"
00732         "width  = %d\n"
00733         "compr  = %s\n",
00734         bmi->bmiHeader.biPlanes,
00735         bmi->bmiHeader.biBitCount,
00736         bmi->bmiHeader.biHeight,
00737         bmi->bmiHeader.biWidth,
00738         debugstr_an( (const char *)&bmi->bmiHeader.biCompression, 4 ) );
00739 }
00740 
00741 static inline int ICCVID_CheckMask(RGBQUAD bmiColors[3], COLORREF redMask, COLORREF blueMask, COLORREF greenMask)
00742 {
00743     COLORREF realRedMask = MAKECOLOUR32(bmiColors[0].rgbRed, bmiColors[0].rgbGreen, bmiColors[0].rgbBlue);
00744     COLORREF realBlueMask = MAKECOLOUR32(bmiColors[1].rgbRed, bmiColors[1].rgbGreen, bmiColors[1].rgbBlue);
00745     COLORREF realGreenMask = MAKECOLOUR32(bmiColors[2].rgbRed, bmiColors[2].rgbGreen, bmiColors[2].rgbBlue);
00746 
00747     TRACE("\nbmiColors[0] = 0x%08x\nbmiColors[1] = 0x%08x\nbmiColors[2] = 0x%08x\n",
00748         realRedMask, realBlueMask, realGreenMask);
00749         
00750     if ((realRedMask == redMask) &&
00751         (realBlueMask == blueMask) &&
00752         (realGreenMask == greenMask))
00753         return TRUE;
00754     return FALSE;
00755 }
00756 
00757 static LRESULT ICCVID_DecompressQuery( ICCVID_Info *info, LPBITMAPINFO in, LPBITMAPINFO out )
00758 {
00759     TRACE("ICM_DECOMPRESS_QUERY %p %p %p\n", info, in, out);
00760 
00761     if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
00762         return ICERR_BADPARAM;
00763 
00764     TRACE("in: ");
00765     ICCVID_dump_BITMAPINFO(in);
00766 
00767     if( in->bmiHeader.biCompression != ICCVID_MAGIC )
00768         return ICERR_BADFORMAT;
00769 
00770     if( out )
00771     {
00772         TRACE("out: ");
00773         ICCVID_dump_BITMAPINFO(out);
00774 
00775         if( in->bmiHeader.biPlanes != out->bmiHeader.biPlanes )
00776             return ICERR_BADFORMAT;
00777         if( in->bmiHeader.biHeight != out->bmiHeader.biHeight )
00778             return ICERR_BADFORMAT;
00779         if( in->bmiHeader.biWidth != out->bmiHeader.biWidth )
00780             return ICERR_BADFORMAT;
00781 
00782         switch( out->bmiHeader.biBitCount )
00783         {
00784         case 16:
00785             if ( out->bmiHeader.biCompression == BI_BITFIELDS )
00786             {
00787                 if ( !ICCVID_CheckMask(out->bmiColors, 0x7C00, 0x03E0, 0x001F) &&
00788                      !ICCVID_CheckMask(out->bmiColors, 0xF800, 0x07E0, 0x001F) )
00789                 {
00790                     TRACE("unsupported output bit field(s) for 16-bit colors\n");
00791                     return ICERR_BADFORMAT;
00792                 }
00793             }
00794             break;
00795         case 24:
00796         case 32:
00797             break;
00798         default:
00799             TRACE("unsupported output bitcount = %d\n", out->bmiHeader.biBitCount );
00800             return ICERR_BADFORMAT;
00801         }
00802     }
00803 
00804     return ICERR_OK;
00805 }
00806 
00807 static LRESULT ICCVID_DecompressGetFormat( ICCVID_Info *info, LPBITMAPINFO in, LPBITMAPINFO out )
00808 {
00809     DWORD size;
00810 
00811     TRACE("ICM_DECOMPRESS_GETFORMAT %p %p %p\n", info, in, out);
00812 
00813     if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
00814         return ICERR_BADPARAM;
00815 
00816     size = in->bmiHeader.biSize;
00817     if (in->bmiHeader.biBitCount <= 8)
00818         size += in->bmiHeader.biClrUsed * sizeof(RGBQUAD);
00819 
00820     if( out )
00821     {
00822         memcpy( out, in, size );
00823         out->bmiHeader.biCompression = BI_RGB;
00824         out->bmiHeader.biSizeImage = in->bmiHeader.biHeight
00825                                    * in->bmiHeader.biWidth *4;
00826         return ICERR_OK;
00827     }
00828     return size;
00829 }
00830 
00831 static LRESULT ICCVID_DecompressBegin( ICCVID_Info *info, LPBITMAPINFO in, LPBITMAPINFO out )
00832 {
00833     TRACE("ICM_DECOMPRESS_BEGIN %p %p %p\n", info, in, out);
00834 
00835     if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
00836         return ICERR_BADPARAM;
00837 
00838     info->bits_per_pixel = out->bmiHeader.biBitCount;
00839 
00840     if (info->bits_per_pixel == 16)
00841     {
00842         if ( out->bmiHeader.biCompression == BI_BITFIELDS )
00843         {
00844             if ( ICCVID_CheckMask(out->bmiColors, 0x7C00, 0x03E0, 0x001F) )
00845                 info->bits_per_pixel = 15;
00846             else if ( ICCVID_CheckMask(out->bmiColors, 0xF800, 0x07E0, 0x001F) )
00847                 info->bits_per_pixel = 16;
00848             else
00849             {
00850                 TRACE("unsupported output bit field(s) for 16-bit colors\n");
00851                 return ICERR_UNSUPPORTED;
00852             }
00853         }
00854         else
00855             info->bits_per_pixel = 15;
00856     }
00857 
00858     TRACE("bit_per_pixel = %d\n", info->bits_per_pixel);
00859 
00860     if( info->cvinfo )
00861         free_cvinfo( info->cvinfo );
00862     info->cvinfo = decode_cinepak_init();
00863 
00864     return ICERR_OK;
00865 }
00866 
00867 static LRESULT ICCVID_Decompress( ICCVID_Info *info, ICDECOMPRESS *icd, DWORD size )
00868 {
00869     LONG width, height;
00870 
00871     TRACE("ICM_DECOMPRESS %p %p %d\n", info, icd, size);
00872 
00873     if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
00874         return ICERR_BADPARAM;
00875     if (info->cvinfo==NULL)
00876     {
00877         ERR("ICM_DECOMPRESS sent after ICM_DECOMPRESS_END\n");
00878         return ICERR_BADPARAM;
00879     }
00880 
00881     width  = icd->lpbiInput->biWidth;
00882     height = icd->lpbiInput->biHeight;
00883 
00884     decode_cinepak(info->cvinfo, icd->lpInput, icd->lpbiInput->biSizeImage,
00885                    icd->lpOutput, width, height, info->bits_per_pixel);
00886 
00887     return ICERR_OK;
00888 }
00889 
00890 static LRESULT ICCVID_DecompressEx( ICCVID_Info *info, ICDECOMPRESSEX *icd, DWORD size )
00891 {
00892     LONG width, height;
00893 
00894     TRACE("ICM_DECOMPRESSEX %p %p %d\n", info, icd, size);
00895 
00896     if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
00897         return ICERR_BADPARAM;
00898     if (info->cvinfo==NULL)
00899     {
00900         ERR("ICM_DECOMPRESSEX sent after ICM_DECOMPRESS_END\n");
00901         return ICERR_BADPARAM;
00902     }
00903 
00904     /* FIXME: flags are ignored */
00905 
00906     width  = icd->lpbiSrc->biWidth;
00907     height = icd->lpbiSrc->biHeight;
00908 
00909     decode_cinepak(info->cvinfo, icd->lpSrc, icd->lpbiSrc->biSizeImage,
00910                    icd->lpDst, width, height, info->bits_per_pixel);
00911 
00912     return ICERR_OK;
00913 }
00914 
00915 static LRESULT ICCVID_Close( ICCVID_Info *info )
00916 {
00917     if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
00918         return 0;
00919     if( info->cvinfo )
00920         free_cvinfo( info->cvinfo );
00921     heap_free( info );
00922     return 1;
00923 }
00924 
00925 static LRESULT ICCVID_GetInfo( ICCVID_Info *info, ICINFO *icinfo, DWORD dwSize )
00926 {
00927     if (!icinfo) return sizeof(ICINFO);
00928     if (dwSize < sizeof(ICINFO)) return 0;
00929 
00930     icinfo->dwSize = sizeof(ICINFO);
00931     icinfo->fccType = ICTYPE_VIDEO;
00932     icinfo->fccHandler = info ? info->dwMagic : ICCVID_MAGIC;
00933     icinfo->dwFlags = 0;
00934     icinfo->dwVersion = ICVERSION;
00935     icinfo->dwVersionICM = ICVERSION;
00936 
00937     LoadStringW(ICCVID_hModule, IDS_NAME, icinfo->szName, sizeof(icinfo->szName)/sizeof(WCHAR));
00938     LoadStringW(ICCVID_hModule, IDS_DESCRIPTION, icinfo->szDescription, sizeof(icinfo->szDescription)/sizeof(WCHAR));
00939     /* msvfw32 will fill icinfo->szDriver for us */
00940 
00941     return sizeof(ICINFO);
00942 }
00943 
00944 static LRESULT ICCVID_DecompressEnd( ICCVID_Info *info )
00945 {
00946     if( info->cvinfo )
00947     {
00948         free_cvinfo( info->cvinfo );
00949         info->cvinfo = NULL;
00950     }
00951     return ICERR_OK;
00952 }
00953 
00954 LRESULT WINAPI ICCVID_DriverProc( DWORD_PTR dwDriverId, HDRVR hdrvr, UINT msg,
00955                                   LPARAM lParam1, LPARAM lParam2)
00956 {
00957     ICCVID_Info *info = (ICCVID_Info *) dwDriverId;
00958 
00959     TRACE("%ld %p %d %ld %ld\n", dwDriverId, hdrvr, msg, lParam1, lParam2);
00960 
00961     switch( msg )
00962     {
00963     case DRV_LOAD:
00964         TRACE("Loaded\n");
00965         return 1;
00966     case DRV_ENABLE:
00967         return 0;
00968     case DRV_DISABLE:
00969         return 0;
00970     case DRV_FREE:
00971         return 0;
00972 
00973     case DRV_OPEN:
00974     {
00975         ICINFO *icinfo = (ICINFO *)lParam2;
00976 
00977         TRACE("Opened\n");
00978 
00979         if (icinfo && compare_fourcc(icinfo->fccType, ICTYPE_VIDEO)) return 0;
00980 
00981         info = heap_alloc( sizeof (ICCVID_Info) );
00982         if( info )
00983         {
00984             info->dwMagic = ICCVID_MAGIC;
00985             info->cvinfo = NULL;
00986         }
00987         return (LRESULT) info;
00988     }
00989 
00990     case DRV_CLOSE:
00991         return ICCVID_Close( info );
00992 
00993     case ICM_GETINFO:
00994         return ICCVID_GetInfo( info, (ICINFO *)lParam1, (DWORD)lParam2 );
00995 
00996     case ICM_DECOMPRESS_QUERY:
00997         return ICCVID_DecompressQuery( info, (LPBITMAPINFO) lParam1,
00998                                        (LPBITMAPINFO) lParam2 );
00999     case ICM_DECOMPRESS_GET_FORMAT:
01000         return ICCVID_DecompressGetFormat( info, (LPBITMAPINFO) lParam1,
01001                                        (LPBITMAPINFO) lParam2 );
01002     case ICM_DECOMPRESS_BEGIN:
01003         return ICCVID_DecompressBegin( info, (LPBITMAPINFO) lParam1,
01004                                        (LPBITMAPINFO) lParam2 );
01005     case ICM_DECOMPRESS:
01006         return ICCVID_Decompress( info, (ICDECOMPRESS*) lParam1,
01007                                   (DWORD) lParam2 );
01008     case ICM_DECOMPRESSEX:
01009         return ICCVID_DecompressEx( info, (ICDECOMPRESSEX*) lParam1, 
01010                                   (DWORD) lParam2 );
01011 
01012     case ICM_DECOMPRESS_END:
01013         return ICCVID_DecompressEnd( info );
01014 
01015     case ICM_COMPRESS_QUERY:
01016         FIXME("compression not implemented\n");
01017         return ICERR_BADFORMAT;
01018 
01019     case ICM_CONFIGURE:
01020         return ICERR_UNSUPPORTED;
01021 
01022     default:
01023         FIXME("Unknown message: %04x %ld %ld\n", msg, lParam1, lParam2);
01024     }
01025     return ICERR_UNSUPPORTED;
01026 }
01027 
01028 BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved)
01029 {
01030     TRACE("(%p,%d,%p)\n", hModule, dwReason, lpReserved);
01031 
01032     switch (dwReason)
01033     {
01034     case DLL_PROCESS_ATTACH:
01035         DisableThreadLibraryCalls(hModule);
01036         ICCVID_hModule = hModule;
01037         break;
01038 
01039     case DLL_PROCESS_DETACH:
01040         break;
01041     }
01042     return TRUE;
01043 }

Generated on Sat May 26 2012 04:22:38 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.