Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmsvideo1.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
1.7.6.1
|