Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmsvideo_main.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 1998 Marcus Meissner 00003 * Copyright 2000 Bradley Baetz 00004 * Copyright 2003 Michael Günnewig 00005 * Copyright 2005 Dmitry Timoshkov 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 * FIXME: This all assumes 32 bit codecs 00022 * Win95 appears to prefer 32 bit codecs, even from 16 bit code. 00023 * There is the ICOpenFunction16 to worry about still, though. 00024 * 00025 * TODO 00026 * - no thread safety 00027 */ 00028 00029 #include <stdarg.h> 00030 #include <stdio.h> 00031 #include <string.h> 00032 00033 #include "windef.h" 00034 #include "winbase.h" 00035 #include "winreg.h" 00036 #include "winnls.h" 00037 #include "wingdi.h" 00038 #include "winuser.h" 00039 #include "commdlg.h" 00040 #include "vfw.h" 00041 #include "msvideo_private.h" 00042 #include "wine/debug.h" 00043 00044 /* Drivers32 settings */ 00045 #define HKLM_DRIVERS32 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32" 00046 00047 WINE_DEFAULT_DEBUG_CHANNEL(msvideo); 00048 00049 static inline const char *wine_dbgstr_fcc( DWORD fcc ) 00050 { 00051 return wine_dbg_sprintf("%c%c%c%c", 00052 LOBYTE(LOWORD(fcc)), HIBYTE(LOWORD(fcc)), 00053 LOBYTE(HIWORD(fcc)), HIBYTE(HIWORD(fcc))); 00054 } 00055 00056 static WINE_HIC* MSVIDEO_FirstHic /* = NULL */; 00057 00058 typedef struct _reg_driver reg_driver; 00059 struct _reg_driver 00060 { 00061 DWORD fccType; 00062 DWORD fccHandler; 00063 DRIVERPROC proc; 00064 LPWSTR name; 00065 reg_driver* next; 00066 }; 00067 00068 static reg_driver* reg_driver_list = NULL; 00069 00070 /* This one is a macro such that it works for both ASCII and Unicode */ 00071 #define fourcc_to_string(str, fcc) do { \ 00072 (str)[0] = LOBYTE(LOWORD(fcc)); \ 00073 (str)[1] = HIBYTE(LOWORD(fcc)); \ 00074 (str)[2] = LOBYTE(HIWORD(fcc)); \ 00075 (str)[3] = HIBYTE(HIWORD(fcc)); \ 00076 } while(0) 00077 00078 HMODULE MSVFW32_hModule; 00079 00080 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) 00081 { 00082 TRACE("%p,%x,%p\n", hinst, reason, reserved); 00083 00084 switch(reason) 00085 { 00086 case DLL_PROCESS_ATTACH: 00087 DisableThreadLibraryCalls(hinst); 00088 MSVFW32_hModule = hinst; 00089 break; 00090 } 00091 return TRUE; 00092 } 00093 00094 /****************************************************************** 00095 * MSVIDEO_SendMessage 00096 * 00097 * 00098 */ 00099 static LRESULT MSVIDEO_SendMessage(WINE_HIC* whic, UINT msg, DWORD_PTR lParam1, DWORD_PTR lParam2) 00100 { 00101 LRESULT ret; 00102 00103 #define XX(x) case x: TRACE("(%p,"#x",0x%08lx,0x%08lx)\n",whic,lParam1,lParam2); break 00104 00105 switch (msg) { 00106 /* DRV_* */ 00107 XX(DRV_LOAD); 00108 XX(DRV_ENABLE); 00109 XX(DRV_OPEN); 00110 XX(DRV_CLOSE); 00111 XX(DRV_DISABLE); 00112 XX(DRV_FREE); 00113 /* ICM_RESERVED+X */ 00114 XX(ICM_ABOUT); 00115 XX(ICM_CONFIGURE); 00116 XX(ICM_GET); 00117 XX(ICM_GETINFO); 00118 XX(ICM_GETDEFAULTQUALITY); 00119 XX(ICM_GETQUALITY); 00120 XX(ICM_GETSTATE); 00121 XX(ICM_SETQUALITY); 00122 XX(ICM_SET); 00123 XX(ICM_SETSTATE); 00124 /* ICM_USER+X */ 00125 XX(ICM_COMPRESS_FRAMES_INFO); 00126 XX(ICM_COMPRESS_GET_FORMAT); 00127 XX(ICM_COMPRESS_GET_SIZE); 00128 XX(ICM_COMPRESS_QUERY); 00129 XX(ICM_COMPRESS_BEGIN); 00130 XX(ICM_COMPRESS); 00131 XX(ICM_COMPRESS_END); 00132 XX(ICM_DECOMPRESS_GET_FORMAT); 00133 XX(ICM_DECOMPRESS_QUERY); 00134 XX(ICM_DECOMPRESS_BEGIN); 00135 XX(ICM_DECOMPRESS); 00136 XX(ICM_DECOMPRESS_END); 00137 XX(ICM_DECOMPRESS_SET_PALETTE); 00138 XX(ICM_DECOMPRESS_GET_PALETTE); 00139 XX(ICM_DRAW_QUERY); 00140 XX(ICM_DRAW_BEGIN); 00141 XX(ICM_DRAW_GET_PALETTE); 00142 XX(ICM_DRAW_START); 00143 XX(ICM_DRAW_STOP); 00144 XX(ICM_DRAW_END); 00145 XX(ICM_DRAW_GETTIME); 00146 XX(ICM_DRAW); 00147 XX(ICM_DRAW_WINDOW); 00148 XX(ICM_DRAW_SETTIME); 00149 XX(ICM_DRAW_REALIZE); 00150 XX(ICM_DRAW_FLUSH); 00151 XX(ICM_DRAW_RENDERBUFFER); 00152 XX(ICM_DRAW_START_PLAY); 00153 XX(ICM_DRAW_STOP_PLAY); 00154 XX(ICM_DRAW_SUGGESTFORMAT); 00155 XX(ICM_DRAW_CHANGEPALETTE); 00156 XX(ICM_GETBUFFERSWANTED); 00157 XX(ICM_GETDEFAULTKEYFRAMERATE); 00158 XX(ICM_DECOMPRESSEX_BEGIN); 00159 XX(ICM_DECOMPRESSEX_QUERY); 00160 XX(ICM_DECOMPRESSEX); 00161 XX(ICM_DECOMPRESSEX_END); 00162 XX(ICM_SET_STATUS_PROC); 00163 default: 00164 FIXME("(%p,0x%08x,0x%08lx,0x%08lx) unknown message\n",whic,msg,lParam1,lParam2); 00165 } 00166 00167 #undef XX 00168 00169 if (whic->driverproc) { 00170 /* dwDriverId parameter is the value returned by the DRV_OPEN */ 00171 ret = whic->driverproc(whic->driverId, whic->hdrv, msg, lParam1, lParam2); 00172 } else { 00173 ret = SendDriverMessage(whic->hdrv, msg, lParam1, lParam2); 00174 } 00175 00176 TRACE(" -> 0x%08lx\n", ret); 00177 return ret; 00178 } 00179 00180 static int compare_fourcc(DWORD fcc1, DWORD fcc2) 00181 { 00182 char fcc_str1[4]; 00183 char fcc_str2[4]; 00184 fourcc_to_string(fcc_str1, fcc1); 00185 fourcc_to_string(fcc_str2, fcc2); 00186 return strncasecmp(fcc_str1, fcc_str2, 4); 00187 } 00188 00189 typedef BOOL (*enum_handler_t)(const char*, unsigned int, void*); 00190 00191 static BOOL enum_drivers(DWORD fccType, enum_handler_t handler, void* param) 00192 { 00193 CHAR buf[2048], fccTypeStr[5], *s; 00194 DWORD i, cnt = 0, lRet; 00195 BOOL result = FALSE; 00196 HKEY hKey; 00197 00198 fourcc_to_string(fccTypeStr, fccType); 00199 fccTypeStr[4] = '.'; 00200 00201 /* first, go through the registry entries */ 00202 lRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, HKLM_DRIVERS32, 0, KEY_QUERY_VALUE, &hKey); 00203 if (lRet == ERROR_SUCCESS) 00204 { 00205 DWORD name, data, type; 00206 i = 0; 00207 for (;;) 00208 { 00209 name = 10; 00210 data = sizeof buf - name; 00211 lRet = RegEnumValueA(hKey, i++, buf, &name, 0, &type, (LPBYTE)(buf+name), &data); 00212 if (lRet == ERROR_NO_MORE_ITEMS) break; 00213 if (lRet != ERROR_SUCCESS) continue; 00214 if (name != 9 || strncasecmp(buf, fccTypeStr, 5)) continue; 00215 buf[name] = '='; 00216 if ((result = handler(buf, cnt++, param))) break; 00217 } 00218 RegCloseKey( hKey ); 00219 } 00220 if (result) return result; 00221 00222 /* if that didn't work, go through the values in system.ini */ 00223 if (GetPrivateProfileSectionA("drivers32", buf, sizeof(buf), "system.ini")) 00224 { 00225 for (s = buf; *s; s += strlen(s) + 1) 00226 { 00227 TRACE("got %s\n", s); 00228 if (strncasecmp(s, fccTypeStr, 5) || s[9] != '=') continue; 00229 if ((result = handler(s, cnt++, param))) break; 00230 } 00231 } 00232 00233 return result; 00234 } 00235 00236 /****************************************************************** 00237 * MSVIDEO_GetHicPtr 00238 * 00239 * 00240 */ 00241 static WINE_HIC* MSVIDEO_GetHicPtr(HIC hic) 00242 { 00243 WINE_HIC* whic; 00244 00245 for (whic = MSVIDEO_FirstHic; whic && whic->hic != hic; whic = whic->next); 00246 return whic; 00247 } 00248 00249 /*********************************************************************** 00250 * VideoForWindowsVersion [MSVFW32.2] 00251 * VideoForWindowsVersion [MSVIDEO.2] 00252 * Returns the version in major.minor form. 00253 * In Windows95 this returns 0x040003b6 (4.950) 00254 */ 00255 DWORD WINAPI VideoForWindowsVersion(void) 00256 { 00257 return 0x040003B6; /* 4.950 */ 00258 } 00259 00260 static BOOL ICInfo_enum_handler(const char *drv, unsigned int nr, void *param) 00261 { 00262 ICINFO *lpicinfo = param; 00263 DWORD fccHandler = mmioStringToFOURCCA(drv + 5, 0); 00264 00265 /* exact match of fccHandler or nth driver found */ 00266 if ((lpicinfo->fccHandler != nr) && (lpicinfo->fccHandler != fccHandler)) 00267 return FALSE; 00268 00269 lpicinfo->fccHandler = fccHandler; 00270 lpicinfo->dwFlags = 0; 00271 lpicinfo->dwVersion = 0; 00272 lpicinfo->dwVersionICM = ICVERSION; 00273 lpicinfo->szName[0] = 0; 00274 lpicinfo->szDescription[0] = 0; 00275 MultiByteToWideChar(CP_ACP, 0, drv + 10, -1, lpicinfo->szDriver, 00276 sizeof(lpicinfo->szDriver)/sizeof(WCHAR)); 00277 00278 return TRUE; 00279 } 00280 00281 /*********************************************************************** 00282 * ICInfo [MSVFW32.@] 00283 * Get information about an installable compressor. Return TRUE if there 00284 * is one. 00285 * 00286 * PARAMS 00287 * fccType [I] type of compressor (e.g. 'vidc') 00288 * fccHandler [I] real fcc for handler or <n>th compressor 00289 * lpicinfo [O] information about compressor 00290 */ 00291 BOOL VFWAPI ICInfo( DWORD fccType, DWORD fccHandler, ICINFO *lpicinfo) 00292 { 00293 TRACE("(%s,%s/%08x,%p)\n", 00294 wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), fccHandler, lpicinfo); 00295 00296 lpicinfo->fccType = fccType; 00297 lpicinfo->fccHandler = fccHandler; 00298 return enum_drivers(fccType, ICInfo_enum_handler, lpicinfo); 00299 } 00300 00301 static DWORD IC_HandleRef = 1; 00302 00303 /*********************************************************************** 00304 * ICInstall [MSVFW32.@] 00305 */ 00306 BOOL VFWAPI ICInstall(DWORD fccType, DWORD fccHandler, LPARAM lParam, LPSTR szDesc, UINT wFlags) 00307 { 00308 reg_driver* driver; 00309 unsigned len; 00310 00311 TRACE("(%s,%s,%p,%p,0x%08x)\n", wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), (void*)lParam, szDesc, wFlags); 00312 00313 /* Check if a driver is already registered */ 00314 for (driver = reg_driver_list; driver; driver = driver->next) 00315 { 00316 if (!compare_fourcc(fccType, driver->fccType) && 00317 !compare_fourcc(fccHandler, driver->fccHandler)) 00318 break; 00319 } 00320 if (driver) return FALSE; 00321 00322 /* Register the driver */ 00323 driver = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(reg_driver)); 00324 if (!driver) goto oom; 00325 driver->fccType = fccType; 00326 driver->fccHandler = fccHandler; 00327 00328 switch(wFlags) 00329 { 00330 case ICINSTALL_FUNCTION: 00331 driver->proc = (DRIVERPROC)lParam; 00332 driver->name = NULL; 00333 break; 00334 case ICINSTALL_DRIVER: 00335 driver->proc = NULL; 00336 len = MultiByteToWideChar(CP_ACP, 0, (char*)lParam, -1, NULL, 0); 00337 driver->name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 00338 if (!driver->name) goto oom; 00339 MultiByteToWideChar(CP_ACP, 0, (char*)lParam, -1, driver->name, len); 00340 break; 00341 default: 00342 ERR("Invalid flags!\n"); 00343 HeapFree(GetProcessHeap(), 0, driver); 00344 return FALSE; 00345 } 00346 00347 /* Insert our driver in the list*/ 00348 driver->next = reg_driver_list; 00349 reg_driver_list = driver; 00350 00351 return TRUE; 00352 oom: 00353 HeapFree(GetProcessHeap(), 0, driver); 00354 return FALSE; 00355 } 00356 00357 /*********************************************************************** 00358 * ICRemove [MSVFW32.@] 00359 */ 00360 BOOL VFWAPI ICRemove(DWORD fccType, DWORD fccHandler, UINT wFlags) 00361 { 00362 reg_driver** pdriver; 00363 reg_driver* drv; 00364 00365 TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wFlags); 00366 00367 /* Check if a driver is already registered */ 00368 for (pdriver = ®_driver_list; *pdriver; pdriver = &(*pdriver)->next) 00369 { 00370 if (!compare_fourcc(fccType, (*pdriver)->fccType) && 00371 !compare_fourcc(fccHandler, (*pdriver)->fccHandler)) 00372 break; 00373 } 00374 if (!*pdriver) 00375 return FALSE; 00376 00377 /* Remove the driver from the list */ 00378 drv = *pdriver; 00379 *pdriver = (*pdriver)->next; 00380 HeapFree(GetProcessHeap(), 0, drv->name); 00381 HeapFree(GetProcessHeap(), 0, drv); 00382 00383 return TRUE; 00384 } 00385 00386 00387 /*********************************************************************** 00388 * ICOpen [MSVFW32.@] 00389 * Opens an installable compressor. Return special handle. 00390 */ 00391 HIC VFWAPI ICOpen(DWORD fccType, DWORD fccHandler, UINT wMode) 00392 { 00393 WCHAR codecname[10]; 00394 ICOPEN icopen; 00395 HDRVR hdrv; 00396 WINE_HIC* whic; 00397 static const WCHAR drv32W[] = {'d','r','i','v','e','r','s','3','2','\0'}; 00398 reg_driver* driver; 00399 00400 TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wMode); 00401 00402 /* Check if there is a registered driver that matches */ 00403 driver = reg_driver_list; 00404 while(driver) 00405 if (!compare_fourcc(fccType, driver->fccType) && 00406 !compare_fourcc(fccHandler, driver->fccHandler)) 00407 break; 00408 else 00409 driver = driver->next; 00410 00411 if (driver && driver->proc) 00412 /* The driver has been registered at runtime with its driverproc */ 00413 return ICOpenFunction(fccType, fccHandler, wMode, driver->proc); 00414 00415 /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the 00416 * same layout as ICOPEN 00417 */ 00418 icopen.dwSize = sizeof(ICOPEN); 00419 icopen.fccType = fccType; 00420 icopen.fccHandler = fccHandler; 00421 icopen.dwVersion = 0x00001000; /* FIXME */ 00422 icopen.dwFlags = wMode; 00423 icopen.dwError = 0; 00424 icopen.pV1Reserved = NULL; 00425 icopen.pV2Reserved = NULL; 00426 icopen.dnDevNode = 0; /* FIXME */ 00427 00428 if (!driver) { 00429 /* The driver is registered in the registry */ 00430 fourcc_to_string(codecname, fccType); 00431 codecname[4] = '.'; 00432 fourcc_to_string(codecname + 5, fccHandler); 00433 codecname[9] = '\0'; 00434 00435 hdrv = OpenDriver(codecname, drv32W, (LPARAM)&icopen); 00436 if (!hdrv) 00437 return 0; 00438 } else { 00439 /* The driver has been registered at runtime with its name */ 00440 hdrv = OpenDriver(driver->name, NULL, (LPARAM)&icopen); 00441 if (!hdrv) 00442 return 0; 00443 } 00444 00445 whic = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC)); 00446 if (!whic) 00447 { 00448 CloseDriver(hdrv, 0, 0); 00449 return FALSE; 00450 } 00451 whic->hdrv = hdrv; 00452 whic->driverproc = NULL; 00453 whic->type = fccType; 00454 whic->handler = fccHandler; 00455 while (MSVIDEO_GetHicPtr((HIC)(ULONG_PTR)IC_HandleRef) != NULL) IC_HandleRef++; 00456 whic->hic = (HIC)(ULONG_PTR)IC_HandleRef++; 00457 whic->next = MSVIDEO_FirstHic; 00458 MSVIDEO_FirstHic = whic; 00459 00460 TRACE("=> %p\n", whic->hic); 00461 return whic->hic; 00462 } 00463 00464 /*********************************************************************** 00465 * ICOpenFunction [MSVFW32.@] 00466 */ 00467 HIC VFWAPI ICOpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode, DRIVERPROC lpfnHandler) 00468 { 00469 ICOPEN icopen; 00470 WINE_HIC* whic; 00471 00472 TRACE("(%s,%s,%d,%p)\n", 00473 wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wMode, lpfnHandler); 00474 00475 icopen.dwSize = sizeof(ICOPEN); 00476 icopen.fccType = fccType; 00477 icopen.fccHandler = fccHandler; 00478 icopen.dwVersion = ICVERSION; 00479 icopen.dwFlags = wMode; 00480 icopen.dwError = 0; 00481 icopen.pV1Reserved = NULL; 00482 icopen.pV2Reserved = NULL; 00483 icopen.dnDevNode = 0; /* FIXME */ 00484 00485 whic = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC)); 00486 if (!whic) return 0; 00487 00488 whic->driverproc = lpfnHandler; 00489 while (MSVIDEO_GetHicPtr((HIC)(ULONG_PTR)IC_HandleRef) != NULL) IC_HandleRef++; 00490 whic->hic = (HIC)(ULONG_PTR)IC_HandleRef++; 00491 whic->next = MSVIDEO_FirstHic; 00492 MSVIDEO_FirstHic = whic; 00493 00494 /* Now try opening/loading the driver. Taken from DRIVER_AddToList */ 00495 /* What if the function is used more than once? */ 00496 00497 if (MSVIDEO_SendMessage(whic, DRV_LOAD, 0L, 0L) != DRV_SUCCESS) 00498 { 00499 WARN("DRV_LOAD failed for hic %p\n", whic->hic); 00500 MSVIDEO_FirstHic = whic->next; 00501 HeapFree(GetProcessHeap(), 0, whic); 00502 return 0; 00503 } 00504 /* return value is not checked */ 00505 MSVIDEO_SendMessage(whic, DRV_ENABLE, 0L, 0L); 00506 00507 whic->driverId = (DWORD)MSVIDEO_SendMessage(whic, DRV_OPEN, 0, (DWORD_PTR)&icopen); 00508 /* FIXME: What should we put here? */ 00509 whic->hdrv = NULL; 00510 00511 if (whic->driverId == 0) 00512 { 00513 WARN("DRV_OPEN failed for hic %p\n", whic->hic); 00514 MSVIDEO_FirstHic = whic->next; 00515 HeapFree(GetProcessHeap(), 0, whic); 00516 return 0; 00517 } 00518 00519 TRACE("=> %p\n", whic->hic); 00520 return whic->hic; 00521 } 00522 00523 /*********************************************************************** 00524 * ICGetInfo [MSVFW32.@] 00525 */ 00526 LRESULT VFWAPI ICGetInfo(HIC hic, ICINFO *picinfo, DWORD cb) 00527 { 00528 LRESULT ret; 00529 WINE_HIC* whic = MSVIDEO_GetHicPtr(hic); 00530 00531 TRACE("(%p,%p,%d)\n", hic, picinfo, cb); 00532 00533 whic = MSVIDEO_GetHicPtr(hic); 00534 if (!whic) return ICERR_BADHANDLE; 00535 if (!picinfo) return MMSYSERR_INVALPARAM; 00536 00537 /* (WS) The field szDriver should be initialized because the driver 00538 * is not obliged and often will not do it. Some applications, like 00539 * VirtualDub, rely on this field and will occasionally crash if it 00540 * goes uninitialized. 00541 */ 00542 if (cb >= sizeof(ICINFO)) picinfo->szDriver[0] = '\0'; 00543 00544 ret = ICSendMessage(hic, ICM_GETINFO, (DWORD_PTR)picinfo, cb); 00545 00546 /* (WS) When szDriver was not supplied by the driver itself, apparently 00547 * Windows will set its value equal to the driver file name. This can 00548 * be obtained from the registry as we do here. 00549 */ 00550 if (cb >= sizeof(ICINFO) && picinfo->szDriver[0] == 0) 00551 { 00552 ICINFO ii; 00553 00554 memset(&ii, 0, sizeof(ii)); 00555 ii.dwSize = sizeof(ii); 00556 ICInfo(picinfo->fccType, picinfo->fccHandler, &ii); 00557 lstrcpyW(picinfo->szDriver, ii.szDriver); 00558 } 00559 00560 TRACE(" -> 0x%08lx\n", ret); 00561 return ret; 00562 } 00563 00564 typedef struct { 00565 DWORD fccType; 00566 DWORD fccHandler; 00567 LPBITMAPINFOHEADER lpbiIn; 00568 LPBITMAPINFOHEADER lpbiOut; 00569 WORD wMode; 00570 DWORD querymsg; 00571 HIC hic; 00572 } driver_info_t; 00573 00574 static HIC try_driver(driver_info_t *info) 00575 { 00576 HIC hic; 00577 00578 if ((hic = ICOpen(info->fccType, info->fccHandler, info->wMode))) 00579 { 00580 if (!ICSendMessage(hic, info->querymsg, (DWORD_PTR)info->lpbiIn, (DWORD_PTR)info->lpbiOut)) 00581 return hic; 00582 ICClose(hic); 00583 } 00584 return 0; 00585 } 00586 00587 static BOOL ICLocate_enum_handler(const char *drv, unsigned int nr, void *param) 00588 { 00589 driver_info_t *info = param; 00590 info->fccHandler = mmioStringToFOURCCA(drv + 5, 0); 00591 info->hic = try_driver(info); 00592 return info->hic != 0; 00593 } 00594 00595 /*********************************************************************** 00596 * ICLocate [MSVFW32.@] 00597 */ 00598 HIC VFWAPI ICLocate(DWORD fccType, DWORD fccHandler, LPBITMAPINFOHEADER lpbiIn, 00599 LPBITMAPINFOHEADER lpbiOut, WORD wMode) 00600 { 00601 driver_info_t info; 00602 00603 TRACE("(%s,%s,%p,%p,0x%04x)\n", 00604 wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), lpbiIn, lpbiOut, wMode); 00605 00606 info.fccType = fccType; 00607 info.fccHandler = fccHandler; 00608 info.lpbiIn = lpbiIn; 00609 info.lpbiOut = lpbiOut; 00610 info.wMode = wMode; 00611 00612 switch (wMode) 00613 { 00614 case ICMODE_FASTCOMPRESS: 00615 case ICMODE_COMPRESS: 00616 info.querymsg = ICM_COMPRESS_QUERY; 00617 break; 00618 case ICMODE_FASTDECOMPRESS: 00619 case ICMODE_DECOMPRESS: 00620 info.querymsg = ICM_DECOMPRESS_QUERY; 00621 break; 00622 case ICMODE_DRAW: 00623 info.querymsg = ICM_DRAW_QUERY; 00624 break; 00625 default: 00626 WARN("Unknown mode (%d)\n", wMode); 00627 return 0; 00628 } 00629 00630 /* Easy case: handler/type match, we just fire a query and return */ 00631 info.hic = try_driver(&info); 00632 /* If it didn't work, try each driver in turn. 32 bit codecs only. */ 00633 /* FIXME: Move this to an init routine? */ 00634 if (!info.hic) enum_drivers(fccType, ICLocate_enum_handler, &info); 00635 00636 if (info.hic) 00637 { 00638 TRACE("=> %p\n", info.hic); 00639 return info.hic; 00640 } 00641 00642 if (fccType == streamtypeVIDEO) 00643 return ICLocate(ICTYPE_VIDEO, fccHandler, lpbiIn, lpbiOut, wMode); 00644 00645 WARN("(%s,%s,%p,%p,0x%04x) not found!\n", 00646 wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), lpbiIn, lpbiOut, wMode); 00647 return 0; 00648 } 00649 00650 /*********************************************************************** 00651 * ICGetDisplayFormat [MSVFW32.@] 00652 */ 00653 HIC VFWAPI ICGetDisplayFormat( 00654 HIC hic,LPBITMAPINFOHEADER lpbiIn,LPBITMAPINFOHEADER lpbiOut, 00655 INT depth,INT dx,INT dy) 00656 { 00657 HIC tmphic = hic; 00658 00659 TRACE("(%p,%p,%p,%d,%d,%d)!\n",hic,lpbiIn,lpbiOut,depth,dx,dy); 00660 00661 if (!tmphic) { 00662 tmphic=ICLocate(ICTYPE_VIDEO,0,lpbiIn,NULL,ICMODE_DECOMPRESS); 00663 if (!tmphic) 00664 return tmphic; 00665 } 00666 if ((dy == lpbiIn->biHeight) && (dx == lpbiIn->biWidth)) 00667 dy = dx = 0; /* no resize needed */ 00668 00669 /* Can we decompress it ? */ 00670 if (ICDecompressQuery(tmphic,lpbiIn,NULL) != 0) 00671 goto errout; /* no, sorry */ 00672 00673 ICSendMessage(tmphic, ICM_DECOMPRESS_GET_FORMAT, (DWORD_PTR)lpbiIn, (DWORD_PTR)lpbiOut); 00674 00675 if (lpbiOut->biCompression != 0) { 00676 FIXME("Ooch, how come decompressor outputs compressed data (%d)??\n", 00677 lpbiOut->biCompression); 00678 } 00679 if (lpbiOut->biSize < sizeof(*lpbiOut)) { 00680 FIXME("Ooch, size of output BIH is too small (%d)\n", 00681 lpbiOut->biSize); 00682 lpbiOut->biSize = sizeof(*lpbiOut); 00683 } 00684 if (!depth) { 00685 HDC hdc; 00686 00687 hdc = GetDC(0); 00688 depth = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES); 00689 ReleaseDC(0,hdc); 00690 if (depth==15) depth = 16; 00691 if (depth<8) depth = 8; 00692 } 00693 if (lpbiIn->biBitCount == 8) 00694 depth = 8; 00695 00696 TRACE("=> %p\n", tmphic); 00697 return tmphic; 00698 errout: 00699 if (hic!=tmphic) 00700 ICClose(tmphic); 00701 00702 TRACE("=> 0\n"); 00703 return 0; 00704 } 00705 00706 /*********************************************************************** 00707 * ICCompress [MSVFW32.@] 00708 */ 00709 DWORD VFWAPIV 00710 ICCompress( 00711 HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiOutput,LPVOID lpData, 00712 LPBITMAPINFOHEADER lpbiInput,LPVOID lpBits,LPDWORD lpckid, 00713 LPDWORD lpdwFlags,LONG lFrameNum,DWORD dwFrameSize,DWORD dwQuality, 00714 LPBITMAPINFOHEADER lpbiPrev,LPVOID lpPrev) 00715 { 00716 ICCOMPRESS iccmp; 00717 00718 TRACE("(%p,%d,%p,%p,%p,%p,...)\n",hic,dwFlags,lpbiOutput,lpData,lpbiInput,lpBits); 00719 00720 iccmp.dwFlags = dwFlags; 00721 00722 iccmp.lpbiOutput = lpbiOutput; 00723 iccmp.lpOutput = lpData; 00724 iccmp.lpbiInput = lpbiInput; 00725 iccmp.lpInput = lpBits; 00726 00727 iccmp.lpckid = lpckid; 00728 iccmp.lpdwFlags = lpdwFlags; 00729 iccmp.lFrameNum = lFrameNum; 00730 iccmp.dwFrameSize = dwFrameSize; 00731 iccmp.dwQuality = dwQuality; 00732 iccmp.lpbiPrev = lpbiPrev; 00733 iccmp.lpPrev = lpPrev; 00734 return ICSendMessage(hic,ICM_COMPRESS,(DWORD_PTR)&iccmp,sizeof(iccmp)); 00735 } 00736 00737 /*********************************************************************** 00738 * ICDecompress [MSVFW32.@] 00739 */ 00740 DWORD VFWAPIV ICDecompress(HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiFormat, 00741 LPVOID lpData,LPBITMAPINFOHEADER lpbi,LPVOID lpBits) 00742 { 00743 ICDECOMPRESS icd; 00744 DWORD ret; 00745 00746 TRACE("(%p,%d,%p,%p,%p,%p)\n",hic,dwFlags,lpbiFormat,lpData,lpbi,lpBits); 00747 00748 icd.dwFlags = dwFlags; 00749 icd.lpbiInput = lpbiFormat; 00750 icd.lpInput = lpData; 00751 00752 icd.lpbiOutput = lpbi; 00753 icd.lpOutput = lpBits; 00754 icd.ckid = 0; 00755 ret = ICSendMessage(hic,ICM_DECOMPRESS,(DWORD_PTR)&icd,sizeof(ICDECOMPRESS)); 00756 00757 TRACE("-> %d\n",ret); 00758 00759 return ret; 00760 } 00761 00762 00763 struct choose_compressor 00764 { 00765 UINT flags; 00766 LPCSTR title; 00767 COMPVARS cv; 00768 }; 00769 00770 struct codec_info 00771 { 00772 HIC hic; 00773 ICINFO icinfo; 00774 }; 00775 00776 static BOOL enum_compressors(HWND list, COMPVARS *pcv, BOOL enum_all) 00777 { 00778 UINT id, total = 0; 00779 ICINFO icinfo; 00780 00781 id = 0; 00782 00783 while (ICInfo(pcv->fccType, id, &icinfo)) 00784 { 00785 struct codec_info *ic; 00786 DWORD idx; 00787 HIC hic; 00788 00789 id++; 00790 00791 hic = ICOpen(icinfo.fccType, icinfo.fccHandler, ICMODE_COMPRESS); 00792 00793 if (hic) 00794 { 00795 /* for unknown reason fccHandler reported by the driver 00796 * doesn't always work, use the one returned by ICInfo instead. 00797 */ 00798 DWORD fccHandler = icinfo.fccHandler; 00799 00800 if (!enum_all && pcv->lpbiIn) 00801 { 00802 if (ICCompressQuery(hic, pcv->lpbiIn, NULL) != ICERR_OK) 00803 { 00804 TRACE("fccHandler %s doesn't support input DIB format %d\n", 00805 wine_dbgstr_fcc(icinfo.fccHandler), pcv->lpbiIn->bmiHeader.biCompression); 00806 ICClose(hic); 00807 continue; 00808 } 00809 } 00810 00811 ICGetInfo(hic, &icinfo, sizeof(icinfo)); 00812 icinfo.fccHandler = fccHandler; 00813 00814 idx = SendMessageW(list, CB_ADDSTRING, 0, (LPARAM)icinfo.szDescription); 00815 00816 ic = HeapAlloc(GetProcessHeap(), 0, sizeof(struct codec_info)); 00817 ic->icinfo = icinfo; 00818 ic->hic = hic; 00819 SendMessageW(list, CB_SETITEMDATA, idx, (LPARAM)ic); 00820 } 00821 total++; 00822 } 00823 00824 return total != 0; 00825 } 00826 00827 static INT_PTR CALLBACK icm_choose_compressor_dlgproc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam) 00828 { 00829 switch (msg) 00830 { 00831 case WM_INITDIALOG: 00832 { 00833 struct codec_info *ic; 00834 WCHAR buf[128]; 00835 struct choose_compressor *choose_comp = (struct choose_compressor *)lparam; 00836 00837 SetWindowLongPtrW(hdlg, DWLP_USER, lparam); 00838 00839 /* FIXME */ 00840 choose_comp->flags &= ~(ICMF_CHOOSE_DATARATE | ICMF_CHOOSE_KEYFRAME); 00841 00842 if (choose_comp->title) 00843 SetWindowTextA(hdlg, choose_comp->title); 00844 00845 if (!(choose_comp->flags & ICMF_CHOOSE_DATARATE)) 00846 { 00847 ShowWindow(GetDlgItem(hdlg, IDC_DATARATE_CHECKBOX), SW_HIDE); 00848 ShowWindow(GetDlgItem(hdlg, IDC_DATARATE), SW_HIDE); 00849 ShowWindow(GetDlgItem(hdlg, IDC_DATARATE_KB), SW_HIDE); 00850 } 00851 00852 if (!(choose_comp->flags & ICMF_CHOOSE_KEYFRAME)) 00853 { 00854 ShowWindow(GetDlgItem(hdlg, IDC_KEYFRAME_CHECKBOX), SW_HIDE); 00855 ShowWindow(GetDlgItem(hdlg, IDC_KEYFRAME), SW_HIDE); 00856 ShowWindow(GetDlgItem(hdlg, IDC_KEYFRAME_FRAMES), SW_HIDE); 00857 } 00858 00859 /* FIXME */ 00860 EnableWindow(GetDlgItem(hdlg, IDC_QUALITY_SCROLL), FALSE); 00861 EnableWindow(GetDlgItem(hdlg, IDC_QUALITY_TXT), FALSE); 00862 00863 /*if (!(choose_comp->flags & ICMF_CHOOSE_PREVIEW)) 00864 ShowWindow(GetDlgItem(hdlg, IDC_PREVIEW), SW_HIDE);*/ 00865 00866 LoadStringW(MSVFW32_hModule, IDS_FULLFRAMES, buf, 128); 00867 SendDlgItemMessageW(hdlg, IDC_COMP_LIST, CB_ADDSTRING, 0, (LPARAM)buf); 00868 00869 ic = HeapAlloc(GetProcessHeap(), 0, sizeof(struct codec_info)); 00870 ic->icinfo.fccType = streamtypeVIDEO; 00871 ic->icinfo.fccHandler = comptypeDIB; 00872 ic->hic = 0; 00873 SendDlgItemMessageW(hdlg, IDC_COMP_LIST, CB_SETITEMDATA, 0, (LPARAM)ic); 00874 00875 enum_compressors(GetDlgItem(hdlg, IDC_COMP_LIST), &choose_comp->cv, choose_comp->flags & ICMF_CHOOSE_ALLCOMPRESSORS); 00876 00877 SendDlgItemMessageW(hdlg, IDC_COMP_LIST, CB_SETCURSEL, 0, 0); 00878 SetFocus(GetDlgItem(hdlg, IDC_COMP_LIST)); 00879 00880 SetWindowLongPtrW(hdlg, DWLP_USER, (ULONG_PTR)choose_comp); 00881 break; 00882 } 00883 00884 case WM_COMMAND: 00885 switch (LOWORD(wparam)) 00886 { 00887 case IDC_COMP_LIST: 00888 { 00889 INT cur_sel; 00890 struct codec_info *ic; 00891 BOOL can_configure = FALSE, can_about = FALSE; 00892 struct choose_compressor *choose_comp; 00893 00894 if (HIWORD(wparam) != CBN_SELCHANGE && HIWORD(wparam) != CBN_SETFOCUS) 00895 break; 00896 00897 choose_comp = (struct choose_compressor *)GetWindowLongPtrW(hdlg, DWLP_USER); 00898 00899 cur_sel = SendMessageW((HWND)lparam, CB_GETCURSEL, 0, 0); 00900 00901 ic = (struct codec_info *)SendMessageW((HWND)lparam, CB_GETITEMDATA, cur_sel, 0); 00902 if (ic && ic->hic) 00903 { 00904 if (ICQueryConfigure(ic->hic) == DRVCNF_OK) 00905 can_configure = TRUE; 00906 if (ICQueryAbout(ic->hic) == DRVCNF_OK) 00907 can_about = TRUE; 00908 } 00909 EnableWindow(GetDlgItem(hdlg, IDC_CONFIGURE), can_configure); 00910 EnableWindow(GetDlgItem(hdlg, IDC_ABOUT), can_about); 00911 00912 if (choose_comp->flags & ICMF_CHOOSE_DATARATE) 00913 { 00914 /* FIXME */ 00915 } 00916 if (choose_comp->flags & ICMF_CHOOSE_KEYFRAME) 00917 { 00918 /* FIXME */ 00919 } 00920 00921 break; 00922 } 00923 00924 case IDC_CONFIGURE: 00925 case IDC_ABOUT: 00926 { 00927 HWND list = GetDlgItem(hdlg, IDC_COMP_LIST); 00928 INT cur_sel; 00929 struct codec_info *ic; 00930 00931 if (HIWORD(wparam) != BN_CLICKED) 00932 break; 00933 00934 cur_sel = SendMessageW(list, CB_GETCURSEL, 0, 0); 00935 00936 ic = (struct codec_info *)SendMessageW(list, CB_GETITEMDATA, cur_sel, 0); 00937 if (ic && ic->hic) 00938 { 00939 if (LOWORD(wparam) == IDC_CONFIGURE) 00940 ICConfigure(ic->hic, hdlg); 00941 else 00942 ICAbout(ic->hic, hdlg); 00943 } 00944 00945 break; 00946 } 00947 00948 case IDOK: 00949 { 00950 HWND list = GetDlgItem(hdlg, IDC_COMP_LIST); 00951 INT cur_sel; 00952 struct codec_info *ic; 00953 00954 if (HIWORD(wparam) != BN_CLICKED) 00955 break; 00956 00957 cur_sel = SendMessageW(list, CB_GETCURSEL, 0, 0); 00958 ic = (struct codec_info *)SendMessageW(list, CB_GETITEMDATA, cur_sel, 0); 00959 if (ic) 00960 { 00961 struct choose_compressor *choose_comp = (struct choose_compressor *)GetWindowLongPtrW(hdlg, DWLP_USER); 00962 00963 choose_comp->cv.hic = ic->hic; 00964 choose_comp->cv.fccType = ic->icinfo.fccType; 00965 choose_comp->cv.fccHandler = ic->icinfo.fccHandler; 00966 /* FIXME: fill everything else */ 00967 00968 /* prevent closing the codec handle below */ 00969 ic->hic = 0; 00970 } 00971 } 00972 /* fall through */ 00973 case IDCANCEL: 00974 { 00975 HWND list = GetDlgItem(hdlg, IDC_COMP_LIST); 00976 INT idx = 0; 00977 00978 if (HIWORD(wparam) != BN_CLICKED) 00979 break; 00980 00981 while (1) 00982 { 00983 struct codec_info *ic; 00984 00985 ic = (struct codec_info *)SendMessageW(list, CB_GETITEMDATA, idx++, 0); 00986 00987 if (!ic || (LONG_PTR)ic == CB_ERR) break; 00988 00989 if (ic->hic) ICClose(ic->hic); 00990 HeapFree(GetProcessHeap(), 0, ic); 00991 } 00992 00993 EndDialog(hdlg, LOWORD(wparam) == IDOK); 00994 break; 00995 } 00996 00997 default: 00998 break; 00999 } 01000 break; 01001 01002 default: 01003 break; 01004 } 01005 01006 return FALSE; 01007 } 01008 01009 /*********************************************************************** 01010 * ICCompressorChoose [MSVFW32.@] 01011 */ 01012 BOOL VFWAPI ICCompressorChoose(HWND hwnd, UINT uiFlags, LPVOID pvIn, 01013 LPVOID lpData, PCOMPVARS pc, LPSTR lpszTitle) 01014 { 01015 struct choose_compressor choose_comp; 01016 BOOL ret; 01017 01018 TRACE("(%p,%08x,%p,%p,%p,%s)\n", hwnd, uiFlags, pvIn, lpData, pc, lpszTitle); 01019 01020 if (!pc || pc->cbSize != sizeof(COMPVARS)) 01021 return FALSE; 01022 01023 if (!(pc->dwFlags & ICMF_COMPVARS_VALID)) 01024 { 01025 pc->dwFlags = 0; 01026 pc->fccType = pc->fccHandler = 0; 01027 pc->hic = NULL; 01028 pc->lpbiIn = NULL; 01029 pc->lpbiOut = NULL; 01030 pc->lpBitsOut = pc->lpBitsPrev = pc->lpState = NULL; 01031 pc->lQ = ICQUALITY_DEFAULT; 01032 pc->lKey = -1; 01033 pc->lDataRate = 300; /* kB */ 01034 pc->lpState = NULL; 01035 pc->cbState = 0; 01036 } 01037 if (pc->fccType == 0) 01038 pc->fccType = ICTYPE_VIDEO; 01039 01040 choose_comp.cv = *pc; 01041 choose_comp.flags = uiFlags; 01042 choose_comp.title = lpszTitle; 01043 01044 ret = DialogBoxParamW(MSVFW32_hModule, MAKEINTRESOURCEW(ICM_CHOOSE_COMPRESSOR), hwnd, 01045 icm_choose_compressor_dlgproc, (LPARAM)&choose_comp); 01046 01047 if (ret) 01048 { 01049 *pc = choose_comp.cv; 01050 pc->dwFlags |= ICMF_COMPVARS_VALID; 01051 } 01052 01053 return ret; 01054 } 01055 01056 01057 /*********************************************************************** 01058 * ICCompressorFree [MSVFW32.@] 01059 */ 01060 void VFWAPI ICCompressorFree(PCOMPVARS pc) 01061 { 01062 TRACE("(%p)\n",pc); 01063 01064 if (pc != NULL && pc->cbSize == sizeof(COMPVARS)) { 01065 if (pc->hic != NULL) { 01066 ICClose(pc->hic); 01067 pc->hic = NULL; 01068 } 01069 HeapFree(GetProcessHeap(), 0, pc->lpbiIn); 01070 pc->lpbiIn = NULL; 01071 HeapFree(GetProcessHeap(), 0, pc->lpBitsOut); 01072 pc->lpBitsOut = NULL; 01073 HeapFree(GetProcessHeap(), 0, pc->lpBitsPrev); 01074 pc->lpBitsPrev = NULL; 01075 HeapFree(GetProcessHeap(), 0, pc->lpState); 01076 pc->lpState = NULL; 01077 pc->dwFlags = 0; 01078 } 01079 } 01080 01081 /*********************************************************************** 01082 * ICSendMessage [MSVFW32.@] 01083 */ 01084 LRESULT VFWAPI ICSendMessage(HIC hic, UINT msg, DWORD_PTR lParam1, DWORD_PTR lParam2) 01085 { 01086 WINE_HIC* whic = MSVIDEO_GetHicPtr(hic); 01087 01088 if (!whic) return ICERR_BADHANDLE; 01089 return MSVIDEO_SendMessage(whic, msg, lParam1, lParam2); 01090 } 01091 01092 /*********************************************************************** 01093 * ICDrawBegin [MSVFW32.@] 01094 */ 01095 DWORD VFWAPIV ICDrawBegin( 01096 HIC hic, /* [in] */ 01097 DWORD dwFlags, /* [in] flags */ 01098 HPALETTE hpal, /* [in] palette to draw with */ 01099 HWND hwnd, /* [in] window to draw to */ 01100 HDC hdc, /* [in] HDC to draw to */ 01101 INT xDst, /* [in] destination rectangle */ 01102 INT yDst, /* [in] */ 01103 INT dxDst, /* [in] */ 01104 INT dyDst, /* [in] */ 01105 LPBITMAPINFOHEADER lpbi, /* [in] format of frame to draw */ 01106 INT xSrc, /* [in] source rectangle */ 01107 INT ySrc, /* [in] */ 01108 INT dxSrc, /* [in] */ 01109 INT dySrc, /* [in] */ 01110 DWORD dwRate, /* [in] frames/second = (dwRate/dwScale) */ 01111 DWORD dwScale) /* [in] */ 01112 { 01113 01114 ICDRAWBEGIN icdb; 01115 01116 TRACE("(%p,%d,%p,%p,%p,%u,%u,%u,%u,%p,%u,%u,%u,%u,%d,%d)\n", 01117 hic, dwFlags, hpal, hwnd, hdc, xDst, yDst, dxDst, dyDst, 01118 lpbi, xSrc, ySrc, dxSrc, dySrc, dwRate, dwScale); 01119 01120 icdb.dwFlags = dwFlags; 01121 icdb.hpal = hpal; 01122 icdb.hwnd = hwnd; 01123 icdb.hdc = hdc; 01124 icdb.xDst = xDst; 01125 icdb.yDst = yDst; 01126 icdb.dxDst = dxDst; 01127 icdb.dyDst = dyDst; 01128 icdb.lpbi = lpbi; 01129 icdb.xSrc = xSrc; 01130 icdb.ySrc = ySrc; 01131 icdb.dxSrc = dxSrc; 01132 icdb.dySrc = dySrc; 01133 icdb.dwRate = dwRate; 01134 icdb.dwScale = dwScale; 01135 return ICSendMessage(hic,ICM_DRAW_BEGIN,(DWORD_PTR)&icdb,sizeof(icdb)); 01136 } 01137 01138 /*********************************************************************** 01139 * ICDraw [MSVFW32.@] 01140 */ 01141 DWORD VFWAPIV ICDraw(HIC hic, DWORD dwFlags, LPVOID lpFormat, LPVOID lpData, DWORD cbData, LONG lTime) { 01142 ICDRAW icd; 01143 01144 TRACE("(%p,%d,%p,%p,%d,%d)\n",hic,dwFlags,lpFormat,lpData,cbData,lTime); 01145 01146 icd.dwFlags = dwFlags; 01147 icd.lpFormat = lpFormat; 01148 icd.lpData = lpData; 01149 icd.cbData = cbData; 01150 icd.lTime = lTime; 01151 01152 return ICSendMessage(hic,ICM_DRAW,(DWORD_PTR)&icd,sizeof(icd)); 01153 } 01154 01155 /*********************************************************************** 01156 * ICClose [MSVFW32.@] 01157 */ 01158 LRESULT WINAPI ICClose(HIC hic) 01159 { 01160 WINE_HIC* whic = MSVIDEO_GetHicPtr(hic); 01161 WINE_HIC** p; 01162 01163 TRACE("(%p)\n",hic); 01164 01165 if (!whic) return ICERR_BADHANDLE; 01166 01167 if (whic->driverproc) 01168 { 01169 MSVIDEO_SendMessage(whic, DRV_CLOSE, 0, 0); 01170 MSVIDEO_SendMessage(whic, DRV_DISABLE, 0, 0); 01171 MSVIDEO_SendMessage(whic, DRV_FREE, 0, 0); 01172 } 01173 else 01174 { 01175 CloseDriver(whic->hdrv, 0, 0); 01176 } 01177 01178 /* remove whic from list */ 01179 for (p = &MSVIDEO_FirstHic; *p != NULL; p = &((*p)->next)) 01180 { 01181 if ((*p) == whic) 01182 { 01183 *p = whic->next; 01184 break; 01185 } 01186 } 01187 01188 HeapFree(GetProcessHeap(), 0, whic); 01189 return 0; 01190 } 01191 01192 01193 01194 /*********************************************************************** 01195 * ICImageCompress [MSVFW32.@] 01196 */ 01197 HANDLE VFWAPI ICImageCompress( 01198 HIC hic, UINT uiFlags, 01199 LPBITMAPINFO lpbiIn, LPVOID lpBits, 01200 LPBITMAPINFO lpbiOut, LONG lQuality, 01201 LONG* plSize) 01202 { 01203 FIXME("(%p,%08x,%p,%p,%p,%d,%p)\n", 01204 hic, uiFlags, lpbiIn, lpBits, lpbiOut, lQuality, plSize); 01205 01206 return NULL; 01207 } 01208 01209 /*********************************************************************** 01210 * ICImageDecompress [MSVFW32.@] 01211 */ 01212 01213 HANDLE VFWAPI ICImageDecompress( 01214 HIC hic, UINT uiFlags, LPBITMAPINFO lpbiIn, 01215 LPVOID lpBits, LPBITMAPINFO lpbiOut) 01216 { 01217 HGLOBAL hMem = NULL; 01218 BYTE* pMem = NULL; 01219 BOOL bReleaseIC = FALSE; 01220 BYTE* pHdr = NULL; 01221 ULONG cbHdr = 0; 01222 BOOL bSucceeded = FALSE; 01223 BOOL bInDecompress = FALSE; 01224 DWORD biSizeImage; 01225 01226 TRACE("(%p,%08x,%p,%p,%p)\n", 01227 hic, uiFlags, lpbiIn, lpBits, lpbiOut); 01228 01229 if ( hic == NULL ) 01230 { 01231 hic = ICDecompressOpen( ICTYPE_VIDEO, 0, &lpbiIn->bmiHeader, (lpbiOut != NULL) ? &lpbiOut->bmiHeader : NULL ); 01232 if ( hic == NULL ) 01233 { 01234 WARN("no handler\n" ); 01235 goto err; 01236 } 01237 bReleaseIC = TRUE; 01238 } 01239 if ( uiFlags != 0 ) 01240 { 01241 FIXME( "unknown flag %08x\n", uiFlags ); 01242 goto err; 01243 } 01244 if ( lpbiIn == NULL || lpBits == NULL ) 01245 { 01246 WARN("invalid argument\n"); 01247 goto err; 01248 } 01249 01250 if ( lpbiOut != NULL ) 01251 { 01252 if ( lpbiOut->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ) 01253 goto err; 01254 cbHdr = sizeof(BITMAPINFOHEADER); 01255 if ( lpbiOut->bmiHeader.biCompression == 3 ) 01256 cbHdr += sizeof(DWORD)*3; 01257 else 01258 if ( lpbiOut->bmiHeader.biBitCount <= 8 ) 01259 { 01260 if ( lpbiOut->bmiHeader.biClrUsed == 0 ) 01261 cbHdr += sizeof(RGBQUAD) * (1<<lpbiOut->bmiHeader.biBitCount); 01262 else 01263 cbHdr += sizeof(RGBQUAD) * lpbiOut->bmiHeader.biClrUsed; 01264 } 01265 } 01266 else 01267 { 01268 TRACE( "get format\n" ); 01269 01270 cbHdr = ICDecompressGetFormatSize(hic,lpbiIn); 01271 if ( cbHdr < sizeof(BITMAPINFOHEADER) ) 01272 goto err; 01273 pHdr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,cbHdr+sizeof(RGBQUAD)*256); 01274 if ( pHdr == NULL ) 01275 goto err; 01276 if ( ICDecompressGetFormat( hic, lpbiIn, pHdr ) != ICERR_OK ) 01277 goto err; 01278 lpbiOut = (BITMAPINFO*)pHdr; 01279 if ( lpbiOut->bmiHeader.biBitCount <= 8 && 01280 ICDecompressGetPalette( hic, lpbiIn, lpbiOut ) != ICERR_OK && 01281 lpbiIn->bmiHeader.biBitCount == lpbiOut->bmiHeader.biBitCount ) 01282 { 01283 if ( lpbiIn->bmiHeader.biClrUsed == 0 ) 01284 memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*(1<<lpbiOut->bmiHeader.biBitCount) ); 01285 else 01286 memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*lpbiIn->bmiHeader.biClrUsed ); 01287 } 01288 if ( lpbiOut->bmiHeader.biBitCount <= 8 && 01289 lpbiOut->bmiHeader.biClrUsed == 0 ) 01290 lpbiOut->bmiHeader.biClrUsed = 1<<lpbiOut->bmiHeader.biBitCount; 01291 01292 lpbiOut->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 01293 cbHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*lpbiOut->bmiHeader.biClrUsed; 01294 } 01295 01296 biSizeImage = lpbiOut->bmiHeader.biSizeImage; 01297 if ( biSizeImage == 0 ) 01298 biSizeImage = ((((lpbiOut->bmiHeader.biWidth * lpbiOut->bmiHeader.biBitCount + 7) >> 3) + 3) & (~3)) * abs(lpbiOut->bmiHeader.biHeight); 01299 01300 TRACE( "call ICDecompressBegin\n" ); 01301 01302 if ( ICDecompressBegin( hic, lpbiIn, lpbiOut ) != ICERR_OK ) 01303 goto err; 01304 bInDecompress = TRUE; 01305 01306 TRACE( "cbHdr %d, biSizeImage %d\n", cbHdr, biSizeImage ); 01307 01308 hMem = GlobalAlloc( GMEM_MOVEABLE|GMEM_ZEROINIT, cbHdr + biSizeImage ); 01309 if ( hMem == NULL ) 01310 { 01311 WARN( "out of memory\n" ); 01312 goto err; 01313 } 01314 pMem = GlobalLock( hMem ); 01315 if ( pMem == NULL ) 01316 goto err; 01317 memcpy( pMem, lpbiOut, cbHdr ); 01318 01319 TRACE( "call ICDecompress\n" ); 01320 if ( ICDecompress( hic, 0, &lpbiIn->bmiHeader, lpBits, &lpbiOut->bmiHeader, pMem+cbHdr ) != ICERR_OK ) 01321 goto err; 01322 01323 bSucceeded = TRUE; 01324 err: 01325 if ( bInDecompress ) 01326 ICDecompressEnd( hic ); 01327 if ( bReleaseIC ) 01328 ICClose(hic); 01329 HeapFree(GetProcessHeap(),0,pHdr); 01330 if ( pMem != NULL ) 01331 GlobalUnlock( hMem ); 01332 if ( !bSucceeded && hMem != NULL ) 01333 { 01334 GlobalFree(hMem); hMem = NULL; 01335 } 01336 01337 return hMem; 01338 } 01339 01340 /*********************************************************************** 01341 * ICSeqCompressFrame [MSVFW32.@] 01342 */ 01343 LPVOID VFWAPI ICSeqCompressFrame(PCOMPVARS pc, UINT uiFlags, LPVOID lpBits, BOOL *pfKey, LONG *plSize) 01344 { 01345 ICCOMPRESS* icComp = pc->lpState; 01346 DWORD ret; 01347 TRACE("(%p, 0x%08x, %p, %p, %p)\n", pc, uiFlags, lpBits, pfKey, plSize); 01348 01349 if (pc->cbState != sizeof(ICCOMPRESS)) 01350 { 01351 ERR("Invalid cbState %i\n", pc->cbState); 01352 return NULL; 01353 } 01354 01355 if (!pc->lKeyCount++) 01356 icComp->dwFlags = ICCOMPRESS_KEYFRAME; 01357 else 01358 { 01359 if (pc->lKey && pc->lKeyCount == (pc->lKey - 1)) 01360 /* No key frames if pc->lKey == 0 */ 01361 pc->lKeyCount = 0; 01362 icComp->dwFlags = 0; 01363 } 01364 01365 icComp->lpInput = lpBits; 01366 icComp->lFrameNum = pc->lFrame++; 01367 icComp->lpOutput = pc->lpBitsOut; 01368 icComp->lpPrev = pc->lpBitsPrev; 01369 ret = ICSendMessage(pc->hic, ICM_COMPRESS, (DWORD_PTR)icComp, sizeof(icComp)); 01370 01371 if (icComp->dwFlags & AVIIF_KEYFRAME) 01372 { 01373 pc->lKeyCount = 1; 01374 *pfKey = TRUE; 01375 TRACE("Key frame\n"); 01376 } 01377 else 01378 *pfKey = FALSE; 01379 01380 *plSize = icComp->lpbiOutput->biSizeImage; 01381 TRACE(" -- 0x%08x\n", ret); 01382 if (ret == ICERR_OK) 01383 { 01384 LPVOID oldprev, oldout; 01385 /* We shift Prev and Out, so we don't have to allocate and release memory */ 01386 oldprev = pc->lpBitsPrev; 01387 oldout = pc->lpBitsOut; 01388 pc->lpBitsPrev = oldout; 01389 pc->lpBitsOut = oldprev; 01390 01391 TRACE("returning: %p\n", icComp->lpOutput); 01392 return icComp->lpOutput; 01393 } 01394 return NULL; 01395 } 01396 01397 /*********************************************************************** 01398 * ICSeqCompressFrameEnd [MSVFW32.@] 01399 */ 01400 void VFWAPI ICSeqCompressFrameEnd(PCOMPVARS pc) 01401 { 01402 DWORD ret; 01403 TRACE("(%p)\n", pc); 01404 ret = ICSendMessage(pc->hic, ICM_COMPRESS_END, 0, 0); 01405 TRACE(" -- %x\n", ret); 01406 HeapFree(GetProcessHeap(), 0, pc->lpbiIn); 01407 HeapFree(GetProcessHeap(), 0, pc->lpBitsPrev); 01408 HeapFree(GetProcessHeap(), 0, pc->lpBitsOut); 01409 HeapFree(GetProcessHeap(), 0, pc->lpState); 01410 pc->lpbiIn = pc->lpBitsPrev = pc->lpBitsOut = pc->lpState = NULL; 01411 } 01412 01413 /*********************************************************************** 01414 * ICSeqCompressFrameStart [MSVFW32.@] 01415 */ 01416 BOOL VFWAPI ICSeqCompressFrameStart(PCOMPVARS pc, LPBITMAPINFO lpbiIn) 01417 { 01418 /* I'm ignoring bmiColors as I don't know what to do with it, 01419 * it doesn't appear to be used though 01420 */ 01421 DWORD ret; 01422 pc->lpbiIn = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFO)); 01423 if (!pc->lpbiIn) 01424 return FALSE; 01425 01426 *pc->lpbiIn = *lpbiIn; 01427 pc->lpBitsPrev = HeapAlloc(GetProcessHeap(), 0, pc->lpbiIn->bmiHeader.biSizeImage); 01428 if (!pc->lpBitsPrev) 01429 { 01430 HeapFree(GetProcessHeap(), 0, pc->lpbiIn); 01431 return FALSE; 01432 } 01433 01434 pc->lpState = HeapAlloc(GetProcessHeap(), 0, sizeof(ICCOMPRESS)); 01435 if (!pc->lpState) 01436 { 01437 HeapFree(GetProcessHeap(), 0, pc->lpbiIn); 01438 HeapFree(GetProcessHeap(), 0, pc->lpBitsPrev); 01439 return FALSE; 01440 } 01441 pc->cbState = sizeof(ICCOMPRESS); 01442 01443 pc->lpBitsOut = HeapAlloc(GetProcessHeap(), 0, pc->lpbiOut->bmiHeader.biSizeImage); 01444 if (!pc->lpBitsOut) 01445 { 01446 HeapFree(GetProcessHeap(), 0, pc->lpbiIn); 01447 HeapFree(GetProcessHeap(), 0, pc->lpBitsPrev); 01448 HeapFree(GetProcessHeap(), 0, pc->lpState); 01449 return FALSE; 01450 } 01451 TRACE("Compvars:\n" 01452 "\tpc:\n" 01453 "\tsize: %i\n" 01454 "\tflags: %i\n" 01455 "\thic: %p\n" 01456 "\ttype: %x\n" 01457 "\thandler: %x\n" 01458 "\tin/out: %p/%p\n" 01459 "key/data/quality: %i/%i/%i\n", 01460 pc->cbSize, pc->dwFlags, pc->hic, pc->fccType, pc->fccHandler, 01461 pc->lpbiIn, pc->lpbiOut, pc->lKey, pc->lDataRate, pc->lQ); 01462 01463 ret = ICSendMessage(pc->hic, ICM_COMPRESS_BEGIN, (DWORD_PTR)pc->lpbiIn, (DWORD_PTR)pc->lpbiOut); 01464 TRACE(" -- %x\n", ret); 01465 if (ret == ICERR_OK) 01466 { 01467 ICCOMPRESS* icComp = pc->lpState; 01468 /* Initialise some variables */ 01469 pc->lFrame = 0; pc->lKeyCount = 0; 01470 01471 icComp->lpbiOutput = &pc->lpbiOut->bmiHeader; 01472 icComp->lpbiInput = &pc->lpbiIn->bmiHeader; 01473 icComp->lpckid = NULL; 01474 icComp->dwFrameSize = 0; 01475 icComp->dwQuality = pc->lQ; 01476 icComp->lpbiPrev = &pc->lpbiIn->bmiHeader; 01477 return TRUE; 01478 } 01479 HeapFree(GetProcessHeap(), 0, pc->lpbiIn); 01480 HeapFree(GetProcessHeap(), 0, pc->lpBitsPrev); 01481 HeapFree(GetProcessHeap(), 0, pc->lpState); 01482 HeapFree(GetProcessHeap(), 0, pc->lpBitsOut); 01483 pc->lpBitsPrev = pc->lpbiIn = pc->lpState = pc->lpBitsOut = NULL; 01484 return FALSE; 01485 } 01486 01487 /*********************************************************************** 01488 * GetFileNamePreview [MSVFW32.@] 01489 */ 01490 static BOOL GetFileNamePreview(LPVOID lpofn,BOOL bSave,BOOL bUnicode) 01491 { 01492 CHAR szFunctionName[20]; 01493 BOOL (*fnGetFileName)(LPVOID); 01494 HMODULE hComdlg32; 01495 BOOL ret; 01496 01497 FIXME("(%p,%d,%d), semi-stub!\n",lpofn,bSave,bUnicode); 01498 01499 lstrcpyA(szFunctionName, (bSave ? "GetSaveFileName" : "GetOpenFileName")); 01500 lstrcatA(szFunctionName, (bUnicode ? "W" : "A")); 01501 01502 hComdlg32 = LoadLibraryA("COMDLG32.DLL"); 01503 if (hComdlg32 == NULL) 01504 return FALSE; 01505 01506 fnGetFileName = (LPVOID)GetProcAddress(hComdlg32, szFunctionName); 01507 if (fnGetFileName == NULL) 01508 return FALSE; 01509 01510 /* FIXME: need to add OFN_ENABLEHOOK and our own handler */ 01511 ret = fnGetFileName(lpofn); 01512 01513 FreeLibrary(hComdlg32); 01514 return ret; 01515 } 01516 01517 /*********************************************************************** 01518 * GetOpenFileNamePreviewA [MSVFW32.@] 01519 */ 01520 BOOL WINAPI GetOpenFileNamePreviewA(LPOPENFILENAMEA lpofn) 01521 { 01522 FIXME("(%p), semi-stub!\n", lpofn); 01523 01524 return GetFileNamePreview(lpofn, FALSE, FALSE); 01525 } 01526 01527 /*********************************************************************** 01528 * GetOpenFileNamePreviewW [MSVFW32.@] 01529 */ 01530 BOOL WINAPI GetOpenFileNamePreviewW(LPOPENFILENAMEW lpofn) 01531 { 01532 FIXME("(%p), semi-stub!\n", lpofn); 01533 01534 return GetFileNamePreview(lpofn, FALSE, TRUE); 01535 } 01536 01537 /*********************************************************************** 01538 * GetSaveFileNamePreviewA [MSVFW32.@] 01539 */ 01540 BOOL WINAPI GetSaveFileNamePreviewA(LPOPENFILENAMEA lpofn) 01541 { 01542 FIXME("(%p), semi-stub!\n", lpofn); 01543 01544 return GetFileNamePreview(lpofn, TRUE, FALSE); 01545 } 01546 01547 /*********************************************************************** 01548 * GetSaveFileNamePreviewW [MSVFW32.@] 01549 */ 01550 BOOL WINAPI GetSaveFileNamePreviewW(LPOPENFILENAMEW lpofn) 01551 { 01552 FIXME("(%p), semi-stub!\n", lpofn); 01553 01554 return GetFileNamePreview(lpofn, TRUE, TRUE); 01555 } Generated on Sun May 27 2012 04:25:22 for ReactOS by
1.7.6.1
|