2 * Copyright 1998 Marcus Meissner
3 * Copyright 2000 Bradley Baetz
4 * Copyright 2003 Michael Günnewig
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * FIXME: This all assumes 32 bit codecs
21 * Win95 appears to prefer 32 bit codecs, even from 16 bit code.
22 * There is the ICOpenFunction16 to worry about still, though.
31 #include "msvideo_private.h"
39 #include "wine/debug.h"
41 /* Drivers32 settings */
42 #define HKLM_DRIVERS32 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32"
44 WINE_DEFAULT_DEBUG_CHANNEL(msvideo
);
46 static inline const char *wine_dbgstr_fcc( DWORD fcc
)
48 return wine_dbg_sprintf("%c%c%c%c",
49 LOBYTE(LOWORD(fcc
)), HIBYTE(LOWORD(fcc
)),
50 LOBYTE(HIWORD(fcc
)), HIBYTE(HIWORD(fcc
)));
53 LRESULT (CALLBACK
*pFnCallTo16
)(HDRVR
, HIC
, UINT
, LPARAM
, LPARAM
) = NULL
;
55 static WINE_HIC
* MSVIDEO_FirstHic
/* = NULL */;
57 typedef struct _reg_driver reg_driver
;
67 static reg_driver
* reg_driver_list
= NULL
;
69 /* This one is a macro such that it works for both ASCII and Unicode */
70 #define fourcc_to_string(str, fcc) do { \
71 (str)[0] = LOBYTE(LOWORD(fcc)); \
72 (str)[1] = HIBYTE(LOWORD(fcc)); \
73 (str)[2] = LOBYTE(HIWORD(fcc)); \
74 (str)[3] = HIBYTE(HIWORD(fcc)); \
77 HMODULE MSVFW32_hModule
;
79 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
81 TRACE("%p,%lx,%p\n", hinst
, reason
, reserved
);
85 case DLL_PROCESS_ATTACH
:
86 DisableThreadLibraryCalls(hinst
);
87 MSVFW32_hModule
= (HMODULE
)hinst
;
93 static int compare_fourcc(DWORD fcc1
, DWORD fcc2
)
97 fourcc_to_string(fcc_str1
, fcc1
);
98 fourcc_to_string(fcc_str2
, fcc2
);
99 return strncasecmp(fcc_str1
, fcc_str2
, 4);
102 typedef BOOL (*enum_handler_t
)(const char*, int, void*);
104 static BOOL
enum_drivers(DWORD fccType
, enum_handler_t handler
, void* param
)
106 CHAR buf
[2048], fccTypeStr
[5], *s
;
107 DWORD i
, cnt
= 0, bufLen
, lRet
;
112 fourcc_to_string(fccTypeStr
, fccType
);
115 /* first, go through the registry entries */
116 lRet
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
, HKLM_DRIVERS32
, 0, KEY_QUERY_VALUE
, &hKey
);
117 if (lRet
== ERROR_SUCCESS
)
120 RegQueryInfoKeyA( hKey
, 0, 0, 0, &numkeys
, 0, 0, 0, 0, 0, 0, 0);
121 for (i
= 0; i
< numkeys
; i
++)
123 bufLen
= sizeof(buf
) / sizeof(buf
[0]);
124 lRet
= RegEnumKeyExA(hKey
, i
, buf
, &bufLen
, 0, 0, 0, &lastWrite
);
125 if (lRet
!= ERROR_SUCCESS
) continue;
126 if (strncasecmp(buf
, fccTypeStr
, 5) || buf
[9] != '=') continue;
127 if ((result
= handler(buf
, cnt
++, param
))) break;
131 if (result
) return result
;
133 /* if that didn't work, go through the values in system.ini */
134 if (GetPrivateProfileSectionA("drivers32", buf
, sizeof(buf
), "system.ini"))
136 for (s
= buf
; *s
; s
+= strlen(s
) + 1)
138 if (strncasecmp(s
, fccTypeStr
, 5) || s
[9] != '=') continue;
139 if ((result
= handler(s
, cnt
++, param
))) break;
146 /******************************************************************
151 WINE_HIC
* MSVIDEO_GetHicPtr(HIC hic
)
155 for (whic
= MSVIDEO_FirstHic
; whic
&& whic
->hic
!= hic
; whic
= whic
->next
);
159 /***********************************************************************
160 * VideoForWindowsVersion [MSVFW32.2]
161 * VideoForWindowsVersion [MSVIDEO.2]
162 * Returns the version in major.minor form.
163 * In Windows95 this returns 0x040003b6 (4.950)
165 DWORD WINAPI
VideoForWindowsVersion(void)
167 return 0x040003B6; /* 4.950 */
170 static BOOL
ICInfo_enum_handler(const char *drv
, int nr
, void *param
)
172 ICINFO
*lpicinfo
= (ICINFO
*)param
;
173 DWORD fccHandler
= mmioStringToFOURCCA(drv
+ 5, 0);
175 /* exact match of fccHandler or nth driver found */
176 if ((lpicinfo
->fccHandler
!= nr
) && (lpicinfo
->fccHandler
!= fccHandler
))
179 lpicinfo
->fccType
= mmioStringToFOURCCA(drv
, 0);
180 lpicinfo
->fccHandler
= fccHandler
;
181 lpicinfo
->dwFlags
= 0;
182 lpicinfo
->dwVersion
= 0;
183 lpicinfo
->dwVersionICM
= 0x104;
184 lpicinfo
->szName
[0] = 0;
185 lpicinfo
->szDescription
[0] = 0;
186 MultiByteToWideChar(CP_ACP
, 0, drv
+ 10, -1, lpicinfo
->szDriver
,
187 sizeof(lpicinfo
->szDriver
)/sizeof(WCHAR
));
192 /***********************************************************************
194 * Get information about an installable compressor. Return TRUE if there
198 * fccType [I] type of compressor (e.g. 'vidc')
199 * fccHandler [I] real fcc for handler or <n>th compressor
200 * lpicinfo [O] information about compressor
202 BOOL VFWAPI
ICInfo( DWORD fccType
, DWORD fccHandler
, ICINFO
*lpicinfo
)
204 TRACE("(%s,%s/%08lx,%p)\n",
205 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), fccHandler
, lpicinfo
);
207 lpicinfo
->fccHandler
= fccHandler
;
208 return enum_drivers(fccType
, ICInfo_enum_handler
, lpicinfo
);
211 static DWORD IC_HandleRef
= 1;
213 /***********************************************************************
214 * ICInstall [MSVFW32.@]
216 BOOL VFWAPI
ICInstall(DWORD fccType
, DWORD fccHandler
, LPARAM lParam
, LPSTR szDesc
, UINT wFlags
)
221 TRACE("(%s,%s,%p,%p,0x%08x)\n", wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), (void*)lParam
, szDesc
, wFlags
);
223 /* Check if a driver is already registered */
224 for (driver
= reg_driver_list
; driver
; driver
= driver
->next
)
226 if (!compare_fourcc(fccType
, driver
->fccType
) &&
227 !compare_fourcc(fccHandler
, driver
->fccHandler
))
230 if (driver
) return FALSE
;
232 /* Register the driver */
233 driver
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(reg_driver
));
234 if (!driver
) goto oom
;
235 driver
->fccType
= fccType
;
236 driver
->fccHandler
= fccHandler
;
240 case ICINSTALL_FUNCTION
:
241 driver
->proc
= (DRIVERPROC
)lParam
;
244 case ICINSTALL_DRIVER
:
246 len
= MultiByteToWideChar(CP_ACP
, 0, (char*)lParam
, -1, NULL
, 0);
247 driver
->name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
248 if (!driver
->name
) goto oom
;
249 MultiByteToWideChar(CP_ACP
, 0, (char*)lParam
, -1, driver
->name
, len
);
252 ERR("Invalid flags!\n");
253 HeapFree(GetProcessHeap(), 0, driver
);
257 /* Insert our driver in the list*/
258 driver
->next
= reg_driver_list
;
259 reg_driver_list
= driver
;
263 HeapFree(GetProcessHeap(), 0, driver
);
267 /***********************************************************************
268 * ICRemove [MSVFW32.@]
270 BOOL VFWAPI
ICRemove(DWORD fccType
, DWORD fccHandler
, UINT wFlags
)
272 reg_driver
** pdriver
;
274 TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), wFlags
);
276 /* Check if a driver is already registered */
277 for (pdriver
= ®_driver_list
; *pdriver
; pdriver
= &(*pdriver
)->next
)
279 if (!compare_fourcc(fccType
, (*pdriver
)->fccType
) &&
280 !compare_fourcc(fccHandler
, (*pdriver
)->fccHandler
))
286 /* Remove the driver from the list */
287 *pdriver
= (*pdriver
)->next
;
288 HeapFree(GetProcessHeap(), 0, (*pdriver
)->name
);
289 HeapFree(GetProcessHeap(), 0, *pdriver
);
295 /***********************************************************************
297 * Opens an installable compressor. Return special handle.
299 HIC VFWAPI
ICOpen(DWORD fccType
, DWORD fccHandler
, UINT wMode
)
306 static const WCHAR drv32W
[] = {'d','r','i','v','e','r','s','3','2','\0'};
309 TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), wMode
);
311 /* Check if there is a registered driver that matches */
312 driver
= reg_driver_list
;
314 if (!compare_fourcc(fccType
, driver
->fccType
) &&
315 !compare_fourcc(fccHandler
, driver
->fccHandler
))
318 driver
= driver
->next
;
320 if (driver
&& driver
->proc
)
321 /* The driver has been registered at runtime with its driverproc */
322 return MSVIDEO_OpenFunction(fccType
, fccHandler
, wMode
, (DRIVERPROC
)driver
->proc
, (DWORD
)NULL
);
324 /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the
325 * same layout as ICOPEN
327 icopen
.dwSize
= sizeof(ICOPEN
);
328 icopen
.fccType
= fccType
;
329 icopen
.fccHandler
= fccHandler
;
330 icopen
.dwVersion
= 0x00001000; /* FIXME */
331 icopen
.dwFlags
= wMode
;
333 icopen
.pV1Reserved
= NULL
;
334 icopen
.pV2Reserved
= NULL
;
335 icopen
.dnDevNode
= 0; /* FIXME */
338 /* The driver is registered in the registry */
339 fourcc_to_string(codecname
, fccType
);
341 fourcc_to_string(codecname
+ 5, fccHandler
);
344 hdrv
= OpenDriver(codecname
, drv32W
, (LPARAM
)&icopen
);
347 if (fccType
== streamtypeVIDEO
)
354 fccType
= ICTYPE_VIDEO
;
355 hdrv
= OpenDriver(codecname
, drv32W
, (LPARAM
)&icopen
);
361 /* The driver has been registered at runtime with its name */
362 hdrv
= OpenDriver(driver
->name
, NULL
, (LPARAM
)&icopen
);
366 bIs16
= GetDriverFlags(hdrv
) & 0x10000000; /* undocumented flag: WINE_GDF_16BIT */
368 if (bIs16
&& !pFnCallTo16
)
370 FIXME("Got a 16 bit driver, but no 16 bit support in msvfw\n");
373 whic
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC
));
376 CloseDriver(hdrv
, 0, 0);
380 /* FIXME: is the signature the real one ? */
381 whic
->driverproc
= bIs16
? (DRIVERPROC
)pFnCallTo16
: NULL
;
382 whic
->driverproc16
= 0;
383 whic
->type
= fccType
;
384 whic
->handler
= fccHandler
;
385 while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef
)) != NULL
) IC_HandleRef
++;
386 whic
->hic
= HIC_32(IC_HandleRef
++);
387 whic
->next
= MSVIDEO_FirstHic
;
388 MSVIDEO_FirstHic
= whic
;
390 TRACE("=> %p\n", whic
->hic
);
394 /***********************************************************************
395 * MSVIDEO_OpenFunction
397 HIC
MSVIDEO_OpenFunction(DWORD fccType
, DWORD fccHandler
, UINT wMode
,
398 DRIVERPROC lpfnHandler
, DWORD lpfnHandler16
)
403 TRACE("(%s,%s,%d,%p,%08lx)\n",
404 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), wMode
, lpfnHandler
, lpfnHandler16
);
406 icopen
.dwSize
= sizeof(ICOPEN
);
407 icopen
.fccType
= fccType
;
408 icopen
.fccHandler
= fccHandler
;
409 icopen
.dwVersion
= 0x00001000; /* FIXME */
410 icopen
.dwFlags
= wMode
;
412 icopen
.pV1Reserved
= NULL
;
413 icopen
.pV2Reserved
= NULL
;
414 icopen
.dnDevNode
= 0; /* FIXME */
416 whic
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC
));
419 whic
->driverproc
= lpfnHandler
;
420 whic
->driverproc16
= lpfnHandler16
;
421 while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef
)) != NULL
) IC_HandleRef
++;
422 whic
->hic
= HIC_32(IC_HandleRef
++);
423 whic
->next
= MSVIDEO_FirstHic
;
424 MSVIDEO_FirstHic
= whic
;
426 /* Now try opening/loading the driver. Taken from DRIVER_AddToList */
427 /* What if the function is used more than once? */
429 if (MSVIDEO_SendMessage(whic
, DRV_LOAD
, 0L, 0L) != DRV_SUCCESS
)
431 WARN("DRV_LOAD failed for hic %p\n", whic
->hic
);
432 MSVIDEO_FirstHic
= whic
->next
;
433 HeapFree(GetProcessHeap(), 0, whic
);
436 /* return value is not checked */
437 MSVIDEO_SendMessage(whic
, DRV_ENABLE
, 0L, 0L);
439 whic
->driverId
= (DWORD
)MSVIDEO_SendMessage(whic
, DRV_OPEN
, 0, (DWORD
)&icopen
);
440 /* FIXME: What should we put here? */
443 if (whic
->driverId
== 0)
445 WARN("DRV_OPEN failed for hic %p\n", whic
->hic
);
446 MSVIDEO_FirstHic
= whic
->next
;
447 HeapFree(GetProcessHeap(), 0, whic
);
451 TRACE("=> %p\n", whic
->hic
);
455 /***********************************************************************
456 * ICOpenFunction [MSVFW32.@]
458 HIC VFWAPI
ICOpenFunction(DWORD fccType
, DWORD fccHandler
, UINT wMode
, FARPROC lpfnHandler
)
460 return MSVIDEO_OpenFunction(fccType
, fccHandler
, wMode
, (DRIVERPROC
)lpfnHandler
, 0);
463 /***********************************************************************
464 * ICGetInfo [MSVFW32.@]
466 LRESULT VFWAPI
ICGetInfo(HIC hic
, ICINFO
*picinfo
, DWORD cb
)
469 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
471 TRACE("(%p,%p,%ld)\n", hic
, picinfo
, cb
);
473 whic
= MSVIDEO_GetHicPtr(hic
);
474 if (!whic
) return ICERR_BADHANDLE
;
475 if (!picinfo
) return MMSYSERR_INVALPARAM
;
477 /* (WS) The field szDriver should be initialized because the driver
478 * is not obliged and often will not do it. Some applications, like
479 * VirtualDub, rely on this field and will occasionally crash if it
482 if (cb
>= sizeof(ICINFO
)) picinfo
->szDriver
[0] = '\0';
484 ret
= ICSendMessage(hic
, ICM_GETINFO
, (DWORD
)picinfo
, cb
);
486 /* (WS) When szDriver was not supplied by the driver itself, apparently
487 * Windows will set its value equal to the driver file name. This can
488 * be obtained from the registry as we do here.
490 if (cb
>= sizeof(ICINFO
) && picinfo
->szDriver
[0] == 0)
494 memset(&ii
, 0, sizeof(ii
));
495 ii
.dwSize
= sizeof(ii
);
496 ICInfo(picinfo
->fccType
, picinfo
->fccHandler
, &ii
);
497 lstrcpyW(picinfo
->szDriver
, ii
.szDriver
);
500 TRACE(" -> 0x%08lx\n", ret
);
507 LPBITMAPINFOHEADER lpbiIn
;
508 LPBITMAPINFOHEADER lpbiOut
;
514 static HIC
try_driver(driver_info_t
*info
)
518 if ((hic
= ICOpen(info
->fccType
, info
->fccHandler
, info
->wMode
)))
520 if (!ICSendMessage(hic
, info
->querymsg
, (DWORD
)info
->lpbiIn
, (DWORD
)info
->lpbiOut
))
527 static BOOL
ICLocate_enum_handler(const char *drv
, int nr
, void *param
)
529 driver_info_t
*info
= (driver_info_t
*)param
;
530 info
->fccHandler
= mmioStringToFOURCCA(drv
+ 5, 0);
531 info
->hic
= try_driver(info
);
532 return info
->hic
!= 0;
535 /***********************************************************************
536 * ICLocate [MSVFW32.@]
538 HIC VFWAPI
ICLocate(DWORD fccType
, DWORD fccHandler
, LPBITMAPINFOHEADER lpbiIn
,
539 LPBITMAPINFOHEADER lpbiOut
, WORD wMode
)
543 TRACE("(%s,%s,%p,%p,0x%04x)\n",
544 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), lpbiIn
, lpbiOut
, wMode
);
546 info
.fccType
= fccType
;
547 info
.fccHandler
= fccHandler
;
548 info
.lpbiIn
= lpbiIn
;
549 info
.lpbiOut
= lpbiOut
;
554 case ICMODE_FASTCOMPRESS
:
555 case ICMODE_COMPRESS
:
556 info
.querymsg
= ICM_COMPRESS_QUERY
;
558 case ICMODE_FASTDECOMPRESS
:
559 case ICMODE_DECOMPRESS
:
560 info
.querymsg
= ICM_DECOMPRESS_QUERY
;
563 info
.querymsg
= ICM_DRAW_QUERY
;
566 WARN("Unknown mode (%d)\n", wMode
);
570 /* Easy case: handler/type match, we just fire a query and return */
571 info
.hic
= try_driver(&info
);
572 /* If it didn't work, try each driver in turn. 32 bit codecs only. */
573 /* FIXME: Move this to an init routine? */
574 if (!info
.hic
) enum_drivers(fccType
, ICLocate_enum_handler
, &info
);
578 TRACE("=> %p\n", info
.hic
);
582 if (fccType
== streamtypeVIDEO
)
583 return ICLocate(ICTYPE_VIDEO
, fccHandler
, lpbiIn
, lpbiOut
, wMode
);
585 WARN("(%s,%s,%p,%p,0x%04x) not found!\n",
586 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), lpbiIn
, lpbiOut
, wMode
);
590 /***********************************************************************
591 * ICGetDisplayFormat [MSVFW32.@]
593 HIC VFWAPI
ICGetDisplayFormat(
594 HIC hic
,LPBITMAPINFOHEADER lpbiIn
,LPBITMAPINFOHEADER lpbiOut
,
595 INT depth
,INT dx
,INT dy
)
599 TRACE("(%p,%p,%p,%d,%d,%d)!\n",hic
,lpbiIn
,lpbiOut
,depth
,dx
,dy
);
602 tmphic
=ICLocate(ICTYPE_VIDEO
,0,lpbiIn
,NULL
,ICMODE_DECOMPRESS
);
606 if ((dy
== lpbiIn
->biHeight
) && (dx
== lpbiIn
->biWidth
))
607 dy
= dx
= 0; /* no resize needed */
609 /* Can we decompress it ? */
610 if (ICDecompressQuery(tmphic
,lpbiIn
,NULL
) != 0)
611 goto errout
; /* no, sorry */
613 ICDecompressGetFormat(tmphic
,lpbiIn
,lpbiOut
);
615 if (lpbiOut
->biCompression
!= 0) {
616 FIXME("Ooch, how come decompressor outputs compressed data (%ld)??\n",
617 lpbiOut
->biCompression
);
619 if (lpbiOut
->biSize
< sizeof(*lpbiOut
)) {
620 FIXME("Ooch, size of output BIH is too small (%ld)\n",
622 lpbiOut
->biSize
= sizeof(*lpbiOut
);
628 depth
= GetDeviceCaps(hdc
,BITSPIXEL
)*GetDeviceCaps(hdc
,PLANES
);
630 if (depth
==15) depth
= 16;
631 if (depth
<8) depth
= 8;
633 if (lpbiIn
->biBitCount
== 8)
636 TRACE("=> %p\n", tmphic
);
646 /***********************************************************************
647 * ICCompress [MSVFW32.@]
651 HIC hic
,DWORD dwFlags
,LPBITMAPINFOHEADER lpbiOutput
,LPVOID lpData
,
652 LPBITMAPINFOHEADER lpbiInput
,LPVOID lpBits
,LPDWORD lpckid
,
653 LPDWORD lpdwFlags
,LONG lFrameNum
,DWORD dwFrameSize
,DWORD dwQuality
,
654 LPBITMAPINFOHEADER lpbiPrev
,LPVOID lpPrev
)
658 TRACE("(%p,%ld,%p,%p,%p,%p,...)\n",hic
,dwFlags
,lpbiOutput
,lpData
,lpbiInput
,lpBits
);
660 iccmp
.dwFlags
= dwFlags
;
662 iccmp
.lpbiOutput
= lpbiOutput
;
663 iccmp
.lpOutput
= lpData
;
664 iccmp
.lpbiInput
= lpbiInput
;
665 iccmp
.lpInput
= lpBits
;
667 iccmp
.lpckid
= lpckid
;
668 iccmp
.lpdwFlags
= lpdwFlags
;
669 iccmp
.lFrameNum
= lFrameNum
;
670 iccmp
.dwFrameSize
= dwFrameSize
;
671 iccmp
.dwQuality
= dwQuality
;
672 iccmp
.lpbiPrev
= lpbiPrev
;
673 iccmp
.lpPrev
= lpPrev
;
674 return ICSendMessage(hic
,ICM_COMPRESS
,(DWORD
)&iccmp
,sizeof(iccmp
));
677 /***********************************************************************
678 * ICDecompress [MSVFW32.@]
680 DWORD VFWAPIV
ICDecompress(HIC hic
,DWORD dwFlags
,LPBITMAPINFOHEADER lpbiFormat
,
681 LPVOID lpData
,LPBITMAPINFOHEADER lpbi
,LPVOID lpBits
)
686 TRACE("(%p,%ld,%p,%p,%p,%p)\n",hic
,dwFlags
,lpbiFormat
,lpData
,lpbi
,lpBits
);
688 TRACE("lpBits[0] == %lx\n",((LPDWORD
)lpBits
)[0]);
690 icd
.dwFlags
= dwFlags
;
691 icd
.lpbiInput
= lpbiFormat
;
692 icd
.lpInput
= lpData
;
694 icd
.lpbiOutput
= lpbi
;
695 icd
.lpOutput
= lpBits
;
697 ret
= ICSendMessage(hic
,ICM_DECOMPRESS
,(DWORD
)&icd
,sizeof(ICDECOMPRESS
));
699 TRACE("lpBits[0] == %lx\n",((LPDWORD
)lpBits
)[0]);
701 TRACE("-> %ld\n",ret
);
706 /***********************************************************************
707 * ICCompressorChoose [MSVFW32.@]
709 BOOL VFWAPI
ICCompressorChoose(HWND hwnd
, UINT uiFlags
, LPVOID pvIn
,
710 LPVOID lpData
, PCOMPVARS pc
, LPSTR lpszTitle
)
712 FIXME("(%p,0x%X,%p,%p,%p,%s),stub!\n",hwnd
,uiFlags
,pvIn
,lpData
,pc
,lpszTitle
);
714 if (pc
== NULL
|| pc
->cbSize
!= sizeof(COMPVARS
))
717 if ((pc
->dwFlags
& ICMF_COMPVARS_VALID
) == 0) {
719 pc
->fccType
= pc
->fccHandler
= 0;
722 pc
->lpBitsOut
= pc
->lpBitsPrev
= pc
->lpState
= NULL
;
723 pc
->lQ
= ICQUALITY_DEFAULT
;
725 pc
->lDataRate
= 300; /* kB */
729 if (pc
->fccType
== 0)
730 pc
->fccType
= ICTYPE_VIDEO
;
738 /***********************************************************************
739 * ICCompressorFree [MSVFW32.@]
741 void VFWAPI
ICCompressorFree(PCOMPVARS pc
)
745 if (pc
!= NULL
&& pc
->cbSize
== sizeof(COMPVARS
)) {
746 if (pc
->hic
!= NULL
) {
750 if (pc
->lpbiOut
!= NULL
) {
751 GlobalFreePtr(pc
->lpbiOut
);
754 if (pc
->lpBitsOut
!= NULL
) {
755 GlobalFreePtr(pc
->lpBitsOut
);
756 pc
->lpBitsOut
= NULL
;
758 if (pc
->lpBitsPrev
!= NULL
) {
759 GlobalFreePtr(pc
->lpBitsPrev
);
760 pc
->lpBitsPrev
= NULL
;
762 if (pc
->lpState
!= NULL
) {
763 GlobalFreePtr(pc
->lpBitsPrev
);
771 /******************************************************************
772 * MSVIDEO_SendMessage
776 LRESULT
MSVIDEO_SendMessage(WINE_HIC
* whic
, UINT msg
, DWORD lParam1
, DWORD lParam2
)
780 #define XX(x) case x: TRACE("(%p,"#x",0x%08lx,0x%08lx)\n",whic,lParam1,lParam2); break;
795 XX(ICM_GETDEFAULTQUALITY
);
802 XX(ICM_COMPRESS_FRAMES_INFO
);
803 XX(ICM_COMPRESS_GET_FORMAT
);
804 XX(ICM_COMPRESS_GET_SIZE
);
805 XX(ICM_COMPRESS_QUERY
);
806 XX(ICM_COMPRESS_BEGIN
);
808 XX(ICM_COMPRESS_END
);
809 XX(ICM_DECOMPRESS_GET_FORMAT
);
810 XX(ICM_DECOMPRESS_QUERY
);
811 XX(ICM_DECOMPRESS_BEGIN
);
813 XX(ICM_DECOMPRESS_END
);
814 XX(ICM_DECOMPRESS_SET_PALETTE
);
815 XX(ICM_DECOMPRESS_GET_PALETTE
);
818 XX(ICM_DRAW_GET_PALETTE
);
822 XX(ICM_DRAW_GETTIME
);
825 XX(ICM_DRAW_SETTIME
);
826 XX(ICM_DRAW_REALIZE
);
828 XX(ICM_DRAW_RENDERBUFFER
);
829 XX(ICM_DRAW_START_PLAY
);
830 XX(ICM_DRAW_STOP_PLAY
);
831 XX(ICM_DRAW_SUGGESTFORMAT
);
832 XX(ICM_DRAW_CHANGEPALETTE
);
833 XX(ICM_GETBUFFERSWANTED
);
834 XX(ICM_GETDEFAULTKEYFRAMERATE
);
835 XX(ICM_DECOMPRESSEX_BEGIN
);
836 XX(ICM_DECOMPRESSEX_QUERY
);
837 XX(ICM_DECOMPRESSEX
);
838 XX(ICM_DECOMPRESSEX_END
);
839 XX(ICM_SET_STATUS_PROC
);
841 FIXME("(%p,0x%08lx,0x%08lx,0x%08lx) unknown message\n",whic
,(DWORD
)msg
,lParam1
,lParam2
);
846 if (whic
->driverproc
) {
847 /* dwDriverId parameter is the value returned by the DRV_OPEN */
848 ret
= whic
->driverproc(whic
->driverId
, whic
->hdrv
, msg
, lParam1
, lParam2
);
850 ret
= SendDriverMessage(whic
->hdrv
, msg
, lParam1
, lParam2
);
853 TRACE(" -> 0x%08lx\n", ret
);
857 /***********************************************************************
858 * ICSendMessage [MSVFW32.@]
860 LRESULT VFWAPI
ICSendMessage(HIC hic
, UINT msg
, DWORD lParam1
, DWORD lParam2
)
862 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
864 if (!whic
) return ICERR_BADHANDLE
;
865 return MSVIDEO_SendMessage(whic
, msg
, lParam1
, lParam2
);
868 /***********************************************************************
869 * ICDrawBegin [MSVFW32.@]
871 DWORD VFWAPIV
ICDrawBegin(
873 DWORD dwFlags
, /* [in] flags */
874 HPALETTE hpal
, /* [in] palette to draw with */
875 HWND hwnd
, /* [in] window to draw to */
876 HDC hdc
, /* [in] HDC to draw to */
877 INT xDst
, /* [in] destination rectangle */
879 INT dxDst
, /* [in] */
880 INT dyDst
, /* [in] */
881 LPBITMAPINFOHEADER lpbi
, /* [in] format of frame to draw */
882 INT xSrc
, /* [in] source rectangle */
884 INT dxSrc
, /* [in] */
885 INT dySrc
, /* [in] */
886 DWORD dwRate
, /* [in] frames/second = (dwRate/dwScale) */
887 DWORD dwScale
) /* [in] */
892 TRACE("(%p,%ld,%p,%p,%p,%u,%u,%u,%u,%p,%u,%u,%u,%u,%ld,%ld)\n",
893 hic
, dwFlags
, hpal
, hwnd
, hdc
, xDst
, yDst
, dxDst
, dyDst
,
894 lpbi
, xSrc
, ySrc
, dxSrc
, dySrc
, dwRate
, dwScale
);
896 icdb
.dwFlags
= dwFlags
;
909 icdb
.dwRate
= dwRate
;
910 icdb
.dwScale
= dwScale
;
911 return ICSendMessage(hic
,ICM_DRAW_BEGIN
,(DWORD
)&icdb
,sizeof(icdb
));
914 /***********************************************************************
917 DWORD VFWAPIV
ICDraw(HIC hic
, DWORD dwFlags
, LPVOID lpFormat
, LPVOID lpData
, DWORD cbData
, LONG lTime
) {
920 TRACE("(%p,%ld,%p,%p,%ld,%ld)\n",hic
,dwFlags
,lpFormat
,lpData
,cbData
,lTime
);
922 icd
.dwFlags
= dwFlags
;
923 icd
.lpFormat
= lpFormat
;
928 return ICSendMessage(hic
,ICM_DRAW
,(DWORD
)&icd
,sizeof(icd
));
931 /***********************************************************************
932 * ICClose [MSVFW32.@]
934 LRESULT WINAPI
ICClose(HIC hic
)
936 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
941 if (!whic
) return ICERR_BADHANDLE
;
943 if (whic
->driverproc
)
945 MSVIDEO_SendMessage(whic
, DRV_CLOSE
, 0, 0);
946 MSVIDEO_SendMessage(whic
, DRV_DISABLE
, 0, 0);
947 MSVIDEO_SendMessage(whic
, DRV_FREE
, 0, 0);
951 CloseDriver(whic
->hdrv
, 0, 0);
954 /* remove whic from list */
955 for (p
= &MSVIDEO_FirstHic
; *p
!= NULL
; p
= &((*p
)->next
))
964 HeapFree(GetProcessHeap(), 0, whic
);
970 /***********************************************************************
971 * ICImageCompress [MSVFW32.@]
973 HANDLE VFWAPI
ICImageCompress(
974 HIC hic
, UINT uiFlags
,
975 LPBITMAPINFO lpbiIn
, LPVOID lpBits
,
976 LPBITMAPINFO lpbiOut
, LONG lQuality
,
979 FIXME("(%p,%08x,%p,%p,%p,%ld,%p)\n",
980 hic
, uiFlags
, lpbiIn
, lpBits
, lpbiOut
, lQuality
, plSize
);
985 /***********************************************************************
986 * ICImageDecompress [MSVFW32.@]
989 HANDLE VFWAPI
ICImageDecompress(
990 HIC hic
, UINT uiFlags
, LPBITMAPINFO lpbiIn
,
991 LPVOID lpBits
, LPBITMAPINFO lpbiOut
)
995 BOOL bReleaseIC
= FALSE
;
998 BOOL bSucceeded
= FALSE
;
999 BOOL bInDecompress
= FALSE
;
1002 TRACE("(%p,%08x,%p,%p,%p)\n",
1003 hic
, uiFlags
, lpbiIn
, lpBits
, lpbiOut
);
1007 hic
= ICDecompressOpen( ICTYPE_VIDEO
, 0, &lpbiIn
->bmiHeader
, (lpbiOut
!= NULL
) ? &lpbiOut
->bmiHeader
: NULL
);
1010 WARN("no handler\n" );
1017 FIXME( "unknown flag %08x\n", uiFlags
);
1020 if ( lpbiIn
== NULL
|| lpBits
== NULL
)
1022 WARN("invalid argument\n");
1026 if ( lpbiOut
!= NULL
)
1028 if ( lpbiOut
->bmiHeader
.biSize
!= sizeof(BITMAPINFOHEADER
) )
1030 cbHdr
= sizeof(BITMAPINFOHEADER
);
1031 if ( lpbiOut
->bmiHeader
.biCompression
== 3 )
1032 cbHdr
+= sizeof(DWORD
)*3;
1034 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 )
1036 if ( lpbiOut
->bmiHeader
.biClrUsed
== 0 )
1037 cbHdr
+= sizeof(RGBQUAD
) * (1<<lpbiOut
->bmiHeader
.biBitCount
);
1039 cbHdr
+= sizeof(RGBQUAD
) * lpbiOut
->bmiHeader
.biClrUsed
;
1044 TRACE( "get format\n" );
1046 cbHdr
= ICDecompressGetFormatSize(hic
,lpbiIn
);
1047 if ( cbHdr
< sizeof(BITMAPINFOHEADER
) )
1049 pHdr
= HeapAlloc(GetProcessHeap(),0,cbHdr
+sizeof(RGBQUAD
)*256);
1052 ZeroMemory( pHdr
, cbHdr
+sizeof(RGBQUAD
)*256 );
1053 if ( ICDecompressGetFormat( hic
, lpbiIn
, (BITMAPINFO
*)pHdr
) != ICERR_OK
)
1055 lpbiOut
= (BITMAPINFO
*)pHdr
;
1056 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 &&
1057 ICDecompressGetPalette( hic
, lpbiIn
, lpbiOut
) != ICERR_OK
&&
1058 lpbiIn
->bmiHeader
.biBitCount
== lpbiOut
->bmiHeader
.biBitCount
)
1060 if ( lpbiIn
->bmiHeader
.biClrUsed
== 0 )
1061 memcpy( lpbiOut
->bmiColors
, lpbiIn
->bmiColors
, sizeof(RGBQUAD
)*(1<<lpbiOut
->bmiHeader
.biBitCount
) );
1063 memcpy( lpbiOut
->bmiColors
, lpbiIn
->bmiColors
, sizeof(RGBQUAD
)*lpbiIn
->bmiHeader
.biClrUsed
);
1065 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 &&
1066 lpbiOut
->bmiHeader
.biClrUsed
== 0 )
1067 lpbiOut
->bmiHeader
.biClrUsed
= 1<<lpbiOut
->bmiHeader
.biBitCount
;
1069 lpbiOut
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1070 cbHdr
= sizeof(BITMAPINFOHEADER
) + sizeof(RGBQUAD
)*lpbiOut
->bmiHeader
.biClrUsed
;
1073 biSizeImage
= lpbiOut
->bmiHeader
.biSizeImage
;
1074 if ( biSizeImage
== 0 )
1075 biSizeImage
= ((((lpbiOut
->bmiHeader
.biWidth
* lpbiOut
->bmiHeader
.biBitCount
+ 7) >> 3) + 3) & (~3)) * abs(lpbiOut
->bmiHeader
.biHeight
);
1077 TRACE( "call ICDecompressBegin\n" );
1079 if ( ICDecompressBegin( hic
, lpbiIn
, lpbiOut
) != ICERR_OK
)
1081 bInDecompress
= TRUE
;
1083 TRACE( "cbHdr %ld, biSizeImage %ld\n", cbHdr
, biSizeImage
);
1085 hMem
= GlobalAlloc( GMEM_MOVEABLE
|GMEM_ZEROINIT
, cbHdr
+ biSizeImage
);
1088 WARN( "out of memory\n" );
1091 pMem
= (BYTE
*)GlobalLock( hMem
);
1094 memcpy( pMem
, lpbiOut
, cbHdr
);
1096 TRACE( "call ICDecompress\n" );
1097 if ( ICDecompress( hic
, 0, &lpbiIn
->bmiHeader
, lpBits
, &lpbiOut
->bmiHeader
, pMem
+cbHdr
) != ICERR_OK
)
1102 if ( bInDecompress
)
1103 ICDecompressEnd( hic
);
1106 HeapFree(GetProcessHeap(),0,pHdr
);
1108 GlobalUnlock( hMem
);
1109 if ( !bSucceeded
&& hMem
!= NULL
)
1111 GlobalFree(hMem
); hMem
= NULL
;
1114 return (HANDLE
)hMem
;
1117 /***********************************************************************
1118 * ICSeqCompressFrame [MSVFW32.@]
1120 LPVOID VFWAPI
ICSeqCompressFrame(PCOMPVARS pc
, UINT uiFlags
, LPVOID lpBits
, BOOL
*pfKey
, LONG
*plSize
)
1122 FIXME("(%p, 0x%08x, %p, %p, %p), stub!\n", pc
, uiFlags
, lpBits
, pfKey
, plSize
);
1126 /***********************************************************************
1127 * ICSeqCompressFrameEnd [MSVFW32.@]
1129 void VFWAPI
ICSeqCompressFrameEnd(PCOMPVARS pc
)
1131 FIXME("(%p), stub!\n", pc
);
1134 /***********************************************************************
1135 * ICSeqCompressFrameStart [MSVFW32.@]
1137 BOOL VFWAPI
ICSeqCompressFrameStart(PCOMPVARS pc
, LPBITMAPINFO lpbiIn
)
1139 FIXME("(%p, %p), stub!\n", pc
, lpbiIn
);
1143 /***********************************************************************
1144 * GetFileNamePreview [MSVFW32.@]
1146 static BOOL
GetFileNamePreview(LPVOID lpofn
,BOOL bSave
,BOOL bUnicode
)
1148 CHAR szFunctionName
[20];
1149 BOOL (*fnGetFileName
)(LPVOID
);
1153 FIXME("(%p,%d,%d), semi-stub!\n",lpofn
,bSave
,bUnicode
);
1155 lstrcpyA(szFunctionName
, (bSave
? "GetSaveFileName" : "GetOpenFileName"));
1156 lstrcatA(szFunctionName
, (bUnicode
? "W" : "A"));
1158 hComdlg32
= LoadLibraryA("COMDLG32.DLL");
1159 if (hComdlg32
== NULL
)
1162 fnGetFileName
= (LPVOID
)GetProcAddress(hComdlg32
, szFunctionName
);
1163 if (fnGetFileName
== NULL
)
1166 /* FIXME: need to add OFN_ENABLEHOOK and our own handler */
1167 ret
= fnGetFileName(lpofn
);
1169 FreeLibrary(hComdlg32
);
1173 /***********************************************************************
1174 * GetOpenFileNamePreviewA [MSVFW32.@]
1176 BOOL WINAPI
GetOpenFileNamePreviewA(LPOPENFILENAMEA lpofn
)
1178 FIXME("(%p), semi-stub!\n", lpofn
);
1180 return GetFileNamePreview(lpofn
, FALSE
, FALSE
);
1183 /***********************************************************************
1184 * GetOpenFileNamePreviewW [MSVFW32.@]
1186 BOOL WINAPI
GetOpenFileNamePreviewW(LPOPENFILENAMEW lpofn
)
1188 FIXME("(%p), semi-stub!\n", lpofn
);
1190 return GetFileNamePreview(lpofn
, FALSE
, TRUE
);
1193 /***********************************************************************
1194 * GetSaveFileNamePreviewA [MSVFW32.@]
1196 BOOL WINAPI
GetSaveFileNamePreviewA(LPOPENFILENAMEA lpofn
)
1198 FIXME("(%p), semi-stub!\n", lpofn
);
1200 return GetFileNamePreview(lpofn
, TRUE
, FALSE
);
1203 /***********************************************************************
1204 * GetSaveFileNamePreviewW [MSVFW32.@]
1206 BOOL WINAPI
GetSaveFileNamePreviewW(LPOPENFILENAMEW lpofn
)
1208 FIXME("(%p), semi-stub!\n", lpofn
);
1210 return GetFileNamePreview(lpofn
, TRUE
, TRUE
);