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

msvideo1.c
Go to the documentation of this file.
00001 /*
00002  * Microsoft Video-1 Decoder
00003  * Copyright (C) 2003 the ffmpeg project
00004  *
00005  * Portions Copyright (C) 2004 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 
00034 #include <stdarg.h>
00035 #include "windef.h"
00036 #include "winbase.h"
00037 #include "wingdi.h"
00038 #include "winuser.h" 
00039 #include "commdlg.h"
00040 #include "vfw.h"
00041 #include "mmsystem.h"
00042 #include "msvidc32_private.h"
00043  
00044 #include "wine/debug.h"
00045  
00046 WINE_DEFAULT_DEBUG_CHANNEL(msvidc32); 
00047 
00048 static HINSTANCE MSVIDC32_hModule;
00049 
00050 #define CRAM_MAGIC mmioFOURCC('C', 'R', 'A', 'M')
00051 #define MSVC_MAGIC mmioFOURCC('M', 'S', 'V', 'C')
00052 #define WHAM_MAGIC mmioFOURCC('W', 'H', 'A', 'M')
00053 #define compare_fourcc(fcc1, fcc2) (((fcc1)^(fcc2))&~0x20202020)
00054 
00055 #define PALETTE_COUNT 256
00056 #define LE_16(x)  ((((const uint8_t *)(x))[1] << 8) | ((const uint8_t *)(x))[0])
00057 
00058 /* FIXME - check the stream size */
00059 #define CHECK_STREAM_PTR(n) \
00060   if ((stream_ptr + n) > buf_size ) { \
00061     WARN("stream_ptr out of bounds (%d >= %d)\n", \
00062       stream_ptr + n, buf_size); \
00063     return; \
00064   }
00065 
00066 typedef BYTE uint8_t;
00067 
00068 typedef struct Msvideo1Context {
00069     DWORD dwMagic;
00070     int mode_8bit;  /* if it's not 8-bit, it's 16-bit */
00071 } Msvideo1Context;
00072 
00073 static void 
00074 msvideo1_decode_8bit( int width, int height, const unsigned char *buf, int buf_size,
00075                       unsigned char *pixels, int stride)
00076 {
00077     int block_ptr, pixel_ptr;
00078     int total_blocks;
00079     int pixel_x, pixel_y;  /* pixel width and height iterators */
00080     int block_x, block_y;  /* block width and height iterators */
00081     int blocks_wide, blocks_high;  /* width and height in 4x4 blocks */
00082     int block_inc;
00083     int row_dec;
00084 
00085     /* decoding parameters */
00086     int stream_ptr;
00087     unsigned char byte_a, byte_b;
00088     unsigned short flags;
00089     int skip_blocks;
00090     unsigned char colors[8];
00091 
00092     stream_ptr = 0;
00093     skip_blocks = 0;
00094     blocks_wide = width / 4;
00095     blocks_high = height / 4;
00096     total_blocks = blocks_wide * blocks_high;
00097     block_inc = 4;
00098 #ifdef ORIGINAL
00099     row_dec = stride + 4;
00100 #else
00101     row_dec = - (stride - 4); /* such that -row_dec > 0 */
00102 #endif
00103 
00104     for (block_y = blocks_high; block_y > 0; block_y--) {
00105 #ifdef ORIGINAL
00106         block_ptr = ((block_y * 4) - 1) * stride;
00107 #else
00108         block_ptr = ((blocks_high - block_y) * 4) * stride;
00109 #endif
00110         for (block_x = blocks_wide; block_x > 0; block_x--) {
00111             /* check if this block should be skipped */
00112             if (skip_blocks) {
00113                 block_ptr += block_inc;
00114                 skip_blocks--;
00115                 total_blocks--;
00116                 continue;
00117             }
00118 
00119             pixel_ptr = block_ptr;
00120 
00121             /* get the next two bytes in the encoded data stream */
00122             CHECK_STREAM_PTR(2);
00123             byte_a = buf[stream_ptr++];
00124             byte_b = buf[stream_ptr++];
00125 
00126             /* check if the decode is finished */
00127             if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0))
00128                 return;
00129             else if ((byte_b & 0xFC) == 0x84) {
00130                 /* skip code, but don't count the current block */
00131                 skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
00132             } else if (byte_b < 0x80) {
00133                 /* 2-color encoding */
00134                 flags = (byte_b << 8) | byte_a;
00135 
00136                 CHECK_STREAM_PTR(2);
00137                 colors[0] = buf[stream_ptr++];
00138                 colors[1] = buf[stream_ptr++];
00139 
00140                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00141                     for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
00142                         pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1];
00143                     pixel_ptr -= row_dec;
00144                 }
00145             } else if (byte_b >= 0x90) {
00146                 /* 8-color encoding */
00147                 flags = (byte_b << 8) | byte_a;
00148 
00149                 CHECK_STREAM_PTR(8);
00150                 memcpy(colors, &buf[stream_ptr], 8);
00151                 stream_ptr += 8;
00152 
00153                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00154                     for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
00155                         pixels[pixel_ptr++] =
00156                             colors[((pixel_y & 0x2) << 1) +
00157                                 (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
00158                     pixel_ptr -= row_dec;
00159                 }
00160             } else {
00161                 /* 1-color encoding */
00162                 colors[0] = byte_a;
00163 
00164                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00165                     for (pixel_x = 0; pixel_x < 4; pixel_x++)
00166                         pixels[pixel_ptr++] = colors[0];
00167                     pixel_ptr -= row_dec;
00168                 }
00169             }
00170 
00171             block_ptr += block_inc;
00172             total_blocks--;
00173         }
00174     }
00175 }
00176 
00177 static void
00178 msvideo1_decode_16bit( int width, int height, const unsigned char *buf, int buf_size,
00179                        unsigned short *pixels, int stride)
00180 {
00181     int block_ptr, pixel_ptr;
00182     int total_blocks;
00183     int pixel_x, pixel_y;  /* pixel width and height iterators */
00184     int block_x, block_y;  /* block width and height iterators */
00185     int blocks_wide, blocks_high;  /* width and height in 4x4 blocks */
00186     int block_inc;
00187     int row_dec;
00188 
00189     /* decoding parameters */
00190     int stream_ptr;
00191     unsigned char byte_a, byte_b;
00192     unsigned short flags;
00193     int skip_blocks;
00194     unsigned short colors[8];
00195 
00196     stream_ptr = 0;
00197     skip_blocks = 0;
00198     blocks_wide = width / 4;
00199     blocks_high = height / 4;
00200     total_blocks = blocks_wide * blocks_high;
00201     block_inc = 4;
00202 #ifdef ORIGINAL
00203     row_dec = stride + 4;
00204 #else
00205     row_dec = - (stride - 4); /* such that -row_dec > 0 */
00206 #endif
00207 
00208     for (block_y = blocks_high; block_y > 0; block_y--) {
00209 #ifdef ORIGINAL
00210         block_ptr = ((block_y * 4) - 1) * stride;
00211 #else
00212         block_ptr = ((blocks_high - block_y) * 4) * stride;
00213 #endif
00214         for (block_x = blocks_wide; block_x > 0; block_x--) {
00215             /* check if this block should be skipped */
00216             if (skip_blocks) {
00217                 block_ptr += block_inc;
00218                 skip_blocks--;
00219                 total_blocks--;
00220                 continue;
00221             }
00222 
00223             pixel_ptr = block_ptr;
00224 
00225             /* get the next two bytes in the encoded data stream */
00226             CHECK_STREAM_PTR(2);
00227             byte_a = buf[stream_ptr++];
00228             byte_b = buf[stream_ptr++];
00229 
00230             /* check if the decode is finished */
00231             if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0)) {
00232                 return;
00233             } else if ((byte_b & 0xFC) == 0x84) {
00234                 /* skip code, but don't count the current block */
00235                 skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
00236             } else if (byte_b < 0x80) {
00237                 /* 2- or 8-color encoding modes */
00238                 flags = (byte_b << 8) | byte_a;
00239 
00240                 CHECK_STREAM_PTR(4);
00241                 colors[0] = LE_16(&buf[stream_ptr]);
00242                 stream_ptr += 2;
00243                 colors[1] = LE_16(&buf[stream_ptr]);
00244                 stream_ptr += 2;
00245 
00246                 if (colors[0] & 0x8000) {
00247                     /* 8-color encoding */
00248                     CHECK_STREAM_PTR(12);
00249                     colors[2] = LE_16(&buf[stream_ptr]);
00250                     stream_ptr += 2;
00251                     colors[3] = LE_16(&buf[stream_ptr]);
00252                     stream_ptr += 2;
00253                     colors[4] = LE_16(&buf[stream_ptr]);
00254                     stream_ptr += 2;
00255                     colors[5] = LE_16(&buf[stream_ptr]);
00256                     stream_ptr += 2;
00257                     colors[6] = LE_16(&buf[stream_ptr]);
00258                     stream_ptr += 2;
00259                     colors[7] = LE_16(&buf[stream_ptr]);
00260                     stream_ptr += 2;
00261 
00262                     for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00263                         for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
00264                             pixels[pixel_ptr++] =
00265                                 colors[((pixel_y & 0x2) << 1) +
00266                                     (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
00267                         pixel_ptr -= row_dec;
00268                     }
00269                 } else {
00270                     /* 2-color encoding */
00271                     for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00272                         for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
00273                             pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1];
00274                         pixel_ptr -= row_dec;
00275                     }
00276                 }
00277             } else {
00278                 /* otherwise, it's a 1-color block */
00279                 colors[0] = (byte_b << 8) | byte_a;
00280 
00281                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00282                     for (pixel_x = 0; pixel_x < 4; pixel_x++)
00283                         pixels[pixel_ptr++] = colors[0];
00284                     pixel_ptr -= row_dec;
00285                 }
00286             }
00287 
00288             block_ptr += block_inc;
00289             total_blocks--;
00290         }
00291     }
00292 }
00293 
00294 static LRESULT
00295 CRAM_DecompressQuery( Msvideo1Context *info, LPBITMAPINFO in, LPBITMAPINFO out )
00296 {
00297     TRACE("ICM_DECOMPRESS_QUERY %p %p %p\n", info, in, out);
00298 
00299     if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) )
00300         return ICERR_BADPARAM;
00301 
00302     TRACE("planes = %d\n", in->bmiHeader.biPlanes );
00303     TRACE("bpp    = %d\n", in->bmiHeader.biBitCount );
00304     TRACE("height = %d\n", in->bmiHeader.biHeight );
00305     TRACE("width  = %d\n", in->bmiHeader.biWidth );
00306     TRACE("compr  = %x\n", in->bmiHeader.biCompression );
00307 
00308     if( ( in->bmiHeader.biCompression != CRAM_MAGIC ) &&
00309         ( in->bmiHeader.biCompression != MSVC_MAGIC ) &&
00310         ( in->bmiHeader.biCompression != WHAM_MAGIC ) )
00311         return ICERR_UNSUPPORTED;
00312 
00313     if( ( in->bmiHeader.biBitCount != 16 ) &&
00314         ( in->bmiHeader.biBitCount != 8 ) )
00315     {
00316         TRACE("can't do %d bpp\n", in->bmiHeader.biBitCount );
00317         return ICERR_UNSUPPORTED;
00318     }
00319 
00320     /* output must be same dimensions as input */
00321     if( out )
00322     {
00323         if( in->bmiHeader.biBitCount != out->bmiHeader.biBitCount )
00324             return ICERR_UNSUPPORTED;
00325         if( in->bmiHeader.biPlanes != out->bmiHeader.biPlanes )
00326             return ICERR_UNSUPPORTED;
00327         if( in->bmiHeader.biHeight != out->bmiHeader.biHeight )
00328             return ICERR_UNSUPPORTED;
00329         if( in->bmiHeader.biWidth != out->bmiHeader.biWidth )
00330             return ICERR_UNSUPPORTED;
00331     }
00332 
00333     TRACE("OK!\n");
00334 
00335     return ICERR_OK;
00336 }
00337 
00338 static LRESULT 
00339 CRAM_DecompressGetFormat( Msvideo1Context *info, LPBITMAPINFO in, LPBITMAPINFO out )
00340 {
00341     DWORD size;
00342 
00343     TRACE("ICM_DECOMPRESS_GETFORMAT %p %p %p\n", info, in, out);
00344 
00345     if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) )
00346         return ICERR_BADPARAM;
00347 
00348     size = in->bmiHeader.biSize;
00349     if (in->bmiHeader.biBitCount <= 8)
00350         size += in->bmiHeader.biClrUsed * sizeof(RGBQUAD);
00351 
00352     if( out )
00353     {
00354         memcpy( out, in, size );
00355         out->bmiHeader.biCompression = BI_RGB;
00356         out->bmiHeader.biSizeImage = in->bmiHeader.biHeight
00357                                    * in->bmiHeader.biWidth *4;
00358         return ICERR_OK;
00359     }
00360 
00361     return size;
00362 }
00363 
00364 static LRESULT CRAM_DecompressBegin( Msvideo1Context *info, LPBITMAPINFO in, LPBITMAPINFO out )
00365 {
00366     TRACE("ICM_DECOMPRESS_BEGIN %p %p %p\n", info, in, out);
00367 
00368     if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) )
00369         return ICERR_BADPARAM;
00370 
00371     TRACE("bitmap is %d bpp\n", in->bmiHeader.biBitCount);
00372     if( in->bmiHeader.biBitCount == 8 )
00373         info->mode_8bit = 1;
00374     else if( in->bmiHeader.biBitCount == 16 )
00375         info->mode_8bit = 0;
00376     else
00377     {
00378         info->mode_8bit = 0;
00379         FIXME("Unsupported output format %i\n", in->bmiHeader.biBitCount);
00380     }
00381 
00382     return ICERR_OK;
00383 }
00384 
00385 static LRESULT CRAM_Decompress( Msvideo1Context *info, ICDECOMPRESS *icd, DWORD size )
00386 {
00387     LONG width, height, stride, sz;
00388 
00389     TRACE("ICM_DECOMPRESS %p %p %d\n", info, icd, size);
00390 
00391     if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) )
00392         return ICERR_BADPARAM;
00393 
00394     /* FIXME: flags are ignored */
00395 
00396     width  = icd->lpbiInput->biWidth;
00397     height = icd->lpbiInput->biHeight;
00398     stride = width; /* in bytes or 16bit words */
00399     sz = icd->lpbiInput->biSizeImage;
00400 
00401     if (info->mode_8bit)
00402     {
00403         msvideo1_decode_8bit( width, height, icd->lpInput, sz,
00404                               icd->lpOutput, stride);
00405     }
00406     else
00407     {
00408         msvideo1_decode_16bit( width, height, icd->lpInput, sz,
00409                                icd->lpOutput, stride);
00410     }
00411 
00412     return ICERR_OK;
00413 }
00414 
00415 static LRESULT CRAM_DecompressEx( Msvideo1Context *info, ICDECOMPRESSEX *icd, DWORD size )
00416 {
00417     LONG width, height, stride, sz;
00418 
00419     TRACE("ICM_DECOMPRESSEX %p %p %d\n", info, icd, size);
00420 
00421     if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) )
00422         return ICERR_BADPARAM;
00423 
00424     /* FIXME: flags are ignored */
00425 
00426     width  = icd->lpbiSrc->biWidth;
00427     height = icd->lpbiSrc->biHeight;
00428     stride = width;
00429     sz = icd->lpbiSrc->biSizeImage;
00430 
00431     if (info->mode_8bit)
00432     {
00433         msvideo1_decode_8bit( width, height, icd->lpSrc, sz, 
00434                              icd->lpDst, stride);
00435     }
00436     else
00437     {
00438         msvideo1_decode_16bit( width, height, icd->lpSrc, sz,
00439                               icd->lpDst, stride);
00440     }
00441 
00442     return ICERR_OK;
00443 }
00444 
00445 static LRESULT CRAM_GetInfo( const Msvideo1Context *info, ICINFO *icinfo, DWORD dwSize )
00446 {
00447     if (!icinfo) return sizeof(ICINFO);
00448     if (dwSize < sizeof(ICINFO)) return 0;
00449 
00450     icinfo->dwSize = sizeof(ICINFO);
00451     icinfo->fccType = ICTYPE_VIDEO;
00452     icinfo->fccHandler = info ? info->dwMagic : CRAM_MAGIC;
00453     icinfo->dwFlags = 0;
00454     icinfo->dwVersion = ICVERSION;
00455     icinfo->dwVersionICM = ICVERSION;
00456 
00457     LoadStringW(MSVIDC32_hModule, IDS_NAME, icinfo->szName, sizeof(icinfo->szName)/sizeof(WCHAR));
00458     LoadStringW(MSVIDC32_hModule, IDS_DESCRIPTION, icinfo->szDescription, sizeof(icinfo->szDescription)/sizeof(WCHAR));
00459     /* msvfw32 will fill icinfo->szDriver for us */
00460 
00461     return sizeof(ICINFO);
00462 }
00463 
00464 /***********************************************************************
00465  *      DriverProc (MSVIDC32.@)
00466  */
00467 LRESULT WINAPI CRAM_DriverProc( DWORD_PTR dwDriverId, HDRVR hdrvr, UINT msg,
00468                                 LPARAM lParam1, LPARAM lParam2 )
00469 {
00470     Msvideo1Context *info = (Msvideo1Context *) dwDriverId;
00471     LRESULT r = ICERR_UNSUPPORTED;
00472 
00473     TRACE("%ld %p %04x %08lx %08lx\n", dwDriverId, hdrvr, msg, lParam1, lParam2);
00474 
00475     switch( msg )
00476     {
00477     case DRV_LOAD:
00478         TRACE("Loaded\n");
00479         r = 1;
00480         break;
00481 
00482     case DRV_ENABLE:
00483         break;
00484 
00485     case DRV_OPEN:
00486     {
00487         ICINFO *icinfo = (ICINFO *)lParam2;
00488 
00489         TRACE("Opened\n");
00490 
00491         if (icinfo && compare_fourcc(icinfo->fccType, ICTYPE_VIDEO)) return 0;
00492 
00493         info = HeapAlloc( GetProcessHeap(), 0, sizeof (Msvideo1Context) );
00494         if( info )
00495         {
00496             memset( info, 0, sizeof *info );
00497             info->dwMagic = CRAM_MAGIC;
00498         }
00499         r = (LRESULT) info;
00500         break;
00501     }
00502 
00503     case DRV_CLOSE:
00504         HeapFree( GetProcessHeap(), 0, info );
00505         break;
00506 
00507     case DRV_DISABLE:
00508         break;
00509 
00510     case DRV_FREE:
00511         break;
00512 
00513     case ICM_GETINFO:
00514         r = CRAM_GetInfo( info, (ICINFO *)lParam1, (DWORD)lParam2 );
00515         break;
00516 
00517     case ICM_DECOMPRESS_QUERY:
00518         r = CRAM_DecompressQuery( info, (LPBITMAPINFO) lParam1,
00519                                        (LPBITMAPINFO) lParam2 );
00520         break;
00521 
00522     case ICM_DECOMPRESS_GET_FORMAT:
00523         r = CRAM_DecompressGetFormat( info, (LPBITMAPINFO) lParam1,
00524                                        (LPBITMAPINFO) lParam2 );
00525         break;
00526 
00527     case ICM_DECOMPRESS_GET_PALETTE:
00528         FIXME("ICM_DECOMPRESS_GET_PALETTE\n");
00529         break;
00530 
00531     case ICM_DECOMPRESSEX_QUERY:
00532         FIXME("ICM_DECOMPRESSEX_QUERY\n");
00533         break;
00534 
00535     case ICM_DECOMPRESS:
00536         r = CRAM_Decompress( info, (ICDECOMPRESS*) lParam1,
00537                                   (DWORD) lParam2 );
00538         break;
00539 
00540     case ICM_DECOMPRESS_BEGIN:
00541         r = CRAM_DecompressBegin( info, (LPBITMAPINFO) lParam1,
00542                                        (LPBITMAPINFO) lParam2 );
00543         break;
00544 
00545     case ICM_DECOMPRESSEX:
00546         r = CRAM_DecompressEx( info, (ICDECOMPRESSEX*) lParam1,
00547                                   (DWORD) lParam2 );
00548         break;
00549 
00550     case ICM_DECOMPRESS_END:
00551         r = ICERR_OK;
00552         break;
00553 
00554     case ICM_COMPRESS_QUERY:
00555         FIXME("compression not implemented\n");
00556         r = ICERR_BADFORMAT;
00557         break;
00558 
00559     case ICM_CONFIGURE:
00560         r = ICERR_UNSUPPORTED;
00561         break;
00562 
00563     default:
00564         FIXME("Unknown message: %04x %ld %ld\n", msg, lParam1, lParam2);
00565     }
00566 
00567     return r;
00568 }
00569 
00570 /***********************************************************************
00571  *      DllMain
00572  */
00573 BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved)
00574 {
00575     TRACE("(%p,%d,%p)\n", hModule, dwReason, lpReserved);
00576 
00577     switch (dwReason)
00578     {
00579     case DLL_PROCESS_ATTACH:
00580         DisableThreadLibraryCalls(hModule);
00581         MSVIDC32_hModule = hModule;
00582         break;
00583 
00584     case DLL_PROCESS_DETACH:
00585         break;
00586     }
00587     return TRUE;
00588 }

Generated on Fri May 25 2012 04:23:25 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.