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"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msvideo
);
42 static inline const char *wine_dbgstr_fcc( DWORD fcc
)
44 return wine_dbg_sprintf("%c%c%c%c",
45 LOBYTE(LOWORD(fcc
)), HIBYTE(LOWORD(fcc
)),
46 LOBYTE(HIWORD(fcc
)), HIBYTE(HIWORD(fcc
)));
49 LRESULT (CALLBACK
*pFnCallTo16
)(HDRVR
, HIC
, UINT
, LPARAM
, LPARAM
) = NULL
;
51 static WINE_HIC
* MSVIDEO_FirstHic
/* = NULL */;
53 typedef struct _reg_driver reg_driver
;
63 static reg_driver
* reg_driver_list
= NULL
;
65 HMODULE MSVFW32_hModule
;
67 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
69 TRACE("%p,%lx,%p\n", hinst
, reason
, reserved
);
73 case DLL_PROCESS_ATTACH
:
74 DisableThreadLibraryCalls(hinst
);
75 MSVFW32_hModule
= (HMODULE
)hinst
;
81 static int compare_fourcc(DWORD fcc1
, DWORD fcc2
)
85 fcc_str1
[0] = LOBYTE(LOWORD(fcc1
));
86 fcc_str1
[1] = HIBYTE(LOWORD(fcc1
));
87 fcc_str1
[2] = LOBYTE(HIWORD(fcc1
));
88 fcc_str1
[3] = HIBYTE(HIWORD(fcc1
));
90 fcc_str2
[0] = LOBYTE(LOWORD(fcc2
));
91 fcc_str2
[1] = HIBYTE(LOWORD(fcc2
));
92 fcc_str2
[2] = LOBYTE(HIWORD(fcc2
));
93 fcc_str2
[3] = HIBYTE(HIWORD(fcc2
));
96 return strcasecmp(fcc_str1
,fcc_str2
);
99 /******************************************************************
104 WINE_HIC
* MSVIDEO_GetHicPtr(HIC hic
)
108 for (whic
= MSVIDEO_FirstHic
; whic
&& whic
->hic
!= hic
; whic
= whic
->next
);
112 /***********************************************************************
113 * VideoForWindowsVersion [MSVFW32.2]
114 * VideoForWindowsVersion [MSVIDEO.2]
115 * Returns the version in major.minor form.
116 * In Windows95 this returns 0x040003b6 (4.950)
118 DWORD WINAPI
VideoForWindowsVersion(void)
120 return 0x040003B6; /* 4.950 */
123 /* system.ini: [drivers] */
125 /***********************************************************************
127 * Get information about an installable compressor. Return TRUE if there
131 DWORD fccType
, /* [in] type of compressor ('vidc') */
132 DWORD fccHandler
, /* [in] real fcc for handler or <n>th compressor */
133 ICINFO
*lpicinfo
) /* [out] information about compressor */
137 TRACE("(%s,%s/%08lx,%p)\n",
138 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), fccHandler
, lpicinfo
);
140 if (GetPrivateProfileSectionA("drivers32", buf
, sizeof(buf
), "system.ini"))
143 char fccHandlerStr
[4];
146 fccTypeStr
[0] = LOBYTE(LOWORD(fccType
));
147 fccTypeStr
[1] = HIBYTE(LOWORD(fccType
));
148 fccTypeStr
[2] = LOBYTE(HIWORD(fccType
));
149 fccTypeStr
[3] = HIBYTE(HIWORD(fccType
));
151 fccHandlerStr
[0] = LOBYTE(LOWORD(fccHandler
));
152 fccHandlerStr
[1] = HIBYTE(LOWORD(fccHandler
));
153 fccHandlerStr
[2] = LOBYTE(HIWORD(fccHandler
));
154 fccHandlerStr
[3] = HIBYTE(HIWORD(fccHandler
));
156 for (s
= buf
; *s
; s
+= strlen(s
) + 1)
158 if (!strncasecmp(fccTypeStr
, s
, 4) && s
[4] == '.' && s
[9] == '=' &&
159 (!fccHandler
-- || !strncasecmp(fccHandlerStr
, s
+ 5, 4)))
161 /* exact match of fccHandler or nth driver found ?? */
162 lpicinfo
->fccType
= fccType
;
163 lpicinfo
->fccHandler
= mmioStringToFOURCCA(s
+ 5, 0);
164 lpicinfo
->dwFlags
= 0;
165 lpicinfo
->dwVersion
= 0;
166 lpicinfo
->dwVersionICM
= 0x104;
167 lpicinfo
->szName
[0] = 0;
168 lpicinfo
->szDescription
[0] = 0;
169 MultiByteToWideChar(CP_ACP
, 0, s
+ 10, -1,
171 sizeof(lpicinfo
->szDriver
)/sizeof(WCHAR
));
179 static DWORD IC_HandleRef
= 1;
181 /***********************************************************************
182 * ICInstall [MSVFW32.@]
184 BOOL VFWAPI
ICInstall(DWORD fccType
, DWORD fccHandler
, LPARAM lParam
, LPSTR szDesc
, UINT wFlags
)
189 TRACE("(%s,%s,%p,%p,0x%08x)\n", wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), (void*)lParam
, szDesc
, wFlags
);
191 /* Check if a driver is already registered */
192 for (driver
= reg_driver_list
; driver
; driver
= driver
->next
)
194 if (!compare_fourcc(fccType
, driver
->fccType
) &&
195 !compare_fourcc(fccHandler
, driver
->fccHandler
))
198 if (driver
) return FALSE
;
200 /* Register the driver */
201 driver
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(reg_driver
));
202 if (!driver
) goto oom
;
203 driver
->fccType
= fccType
;
204 driver
->fccHandler
= fccHandler
;
208 case ICINSTALL_FUNCTION
:
209 driver
->proc
= (DRIVERPROC
)lParam
;
212 case ICINSTALL_DRIVER
:
214 len
= MultiByteToWideChar(CP_ACP
, 0, (char*)lParam
, -1, NULL
, 0);
215 driver
->name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
216 if (!driver
->name
) goto oom
;
217 MultiByteToWideChar(CP_ACP
, 0, (char*)lParam
, -1, driver
->name
, len
);
220 ERR("Invalid flags!\n");
221 HeapFree(GetProcessHeap(), 0, driver
);
225 /* Insert our driver in the list*/
226 driver
->next
= reg_driver_list
;
227 reg_driver_list
= driver
;
231 if (driver
) HeapFree(GetProcessHeap(), 0, driver
);
235 /***********************************************************************
236 * ICRemove [MSVFW32.@]
238 BOOL VFWAPI
ICRemove(DWORD fccType
, DWORD fccHandler
, UINT wFlags
)
240 reg_driver
** pdriver
;
242 TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), wFlags
);
244 /* Check if a driver is already registered */
245 for (pdriver
= ®_driver_list
; *pdriver
; pdriver
= &(*pdriver
)->next
)
247 if (!compare_fourcc(fccType
, (*pdriver
)->fccType
) &&
248 !compare_fourcc(fccHandler
, (*pdriver
)->fccHandler
))
254 /* Remove the driver from the list */
255 *pdriver
= (*pdriver
)->next
;
256 if ((*pdriver
)->name
)
257 HeapFree(GetProcessHeap(), 0, (*pdriver
)->name
);
258 HeapFree(GetProcessHeap(), 0, *pdriver
);
264 /***********************************************************************
266 * Opens an installable compressor. Return special handle.
268 HIC VFWAPI
ICOpen(DWORD fccType
, DWORD fccHandler
, UINT wMode
)
275 static WCHAR drv32W
[] = {'d','r','i','v','e','r','s','3','2','\0'};
278 TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), wMode
);
280 /* Check if there is a registered driver that matches */
281 driver
= reg_driver_list
;
283 if (!compare_fourcc(fccType
, driver
->fccType
) &&
284 !compare_fourcc(fccHandler
, driver
->fccHandler
))
287 driver
= driver
->next
;
289 if (driver
&& driver
->proc
)
290 /* The driver has been registered at runtime with its driverproc */
291 return MSVIDEO_OpenFunction(fccType
, fccHandler
, wMode
, (DRIVERPROC
)driver
->proc
, (DWORD
)NULL
);
293 /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the
294 * same layout as ICOPEN
296 icopen
.dwSize
= sizeof(ICOPEN
);
297 icopen
.fccType
= fccType
;
298 icopen
.fccHandler
= fccHandler
;
299 icopen
.dwVersion
= 0x00001000; /* FIXME */
300 icopen
.dwFlags
= wMode
;
302 icopen
.pV1Reserved
= NULL
;
303 icopen
.pV2Reserved
= NULL
;
304 icopen
.dnDevNode
= 0; /* FIXME */
307 /* The driver is registered in the registry */
308 codecname
[0] = LOBYTE(LOWORD(fccType
));
309 codecname
[1] = HIBYTE(LOWORD(fccType
));
310 codecname
[2] = LOBYTE(HIWORD(fccType
));
311 codecname
[3] = HIBYTE(HIWORD(fccType
));
313 codecname
[5] = LOBYTE(LOWORD(fccHandler
));
314 codecname
[6] = HIBYTE(LOWORD(fccHandler
));
315 codecname
[7] = LOBYTE(HIWORD(fccHandler
));
316 codecname
[8] = HIBYTE(HIWORD(fccHandler
));
319 hdrv
= OpenDriver(codecname
, drv32W
, (LPARAM
)&icopen
);
322 if (fccType
== streamtypeVIDEO
)
329 fccType
= ICTYPE_VIDEO
;
330 hdrv
= OpenDriver(codecname
, drv32W
, (LPARAM
)&icopen
);
336 /* The driver has been registered at runtime with its name */
337 hdrv
= OpenDriver(driver
->name
, NULL
, (LPARAM
)&icopen
);
341 bIs16
= GetDriverFlags(hdrv
) & 0x10000000; /* undocumented flag: WINE_GDF_16BIT */
343 if (bIs16
&& !pFnCallTo16
)
345 FIXME("Got a 16 bit driver, but no 16 bit support in msvfw\n");
348 whic
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC
));
351 CloseDriver(hdrv
, 0, 0);
355 /* FIXME: is the signature the real one ? */
356 whic
->driverproc
= bIs16
? (DRIVERPROC
)pFnCallTo16
: NULL
;
357 whic
->driverproc16
= 0;
358 whic
->type
= fccType
;
359 whic
->handler
= fccHandler
;
360 while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef
)) != NULL
) IC_HandleRef
++;
361 whic
->hic
= HIC_32(IC_HandleRef
++);
362 whic
->next
= MSVIDEO_FirstHic
;
363 MSVIDEO_FirstHic
= whic
;
365 TRACE("=> %p\n", whic
->hic
);
369 /***********************************************************************
370 * MSVIDEO_OpenFunction
372 HIC
MSVIDEO_OpenFunction(DWORD fccType
, DWORD fccHandler
, UINT wMode
,
373 DRIVERPROC lpfnHandler
, DWORD lpfnHandler16
)
378 TRACE("(%s,%s,%d,%p,%08lx)\n",
379 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), wMode
, lpfnHandler
, lpfnHandler16
);
381 icopen
.dwSize
= sizeof(ICOPEN
);
382 icopen
.fccType
= fccType
;
383 icopen
.fccHandler
= fccHandler
;
384 icopen
.dwVersion
= 0x00001000; /* FIXME */
385 icopen
.dwFlags
= wMode
;
387 icopen
.pV1Reserved
= NULL
;
388 icopen
.pV2Reserved
= NULL
;
389 icopen
.dnDevNode
= 0; /* FIXME */
391 whic
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC
));
394 whic
->driverproc
= lpfnHandler
;
395 whic
->driverproc16
= lpfnHandler16
;
396 while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef
)) != NULL
) IC_HandleRef
++;
397 whic
->hic
= HIC_32(IC_HandleRef
++);
398 whic
->next
= MSVIDEO_FirstHic
;
399 MSVIDEO_FirstHic
= whic
;
401 /* Now try opening/loading the driver. Taken from DRIVER_AddToList */
402 /* What if the function is used more than once? */
404 if (MSVIDEO_SendMessage(whic
, DRV_LOAD
, 0L, 0L) != DRV_SUCCESS
)
406 WARN("DRV_LOAD failed for hic %p\n", whic
->hic
);
407 MSVIDEO_FirstHic
= whic
->next
;
408 HeapFree(GetProcessHeap(), 0, whic
);
411 /* return value is not checked */
412 MSVIDEO_SendMessage(whic
, DRV_ENABLE
, 0L, 0L);
414 whic
->driverId
= (DWORD
)MSVIDEO_SendMessage(whic
, DRV_OPEN
, 0, (DWORD
)&icopen
);
415 /* FIXME: What should we put here? */
416 whic
->hdrv
= (HDRVR
)0;
418 if (whic
->driverId
== 0)
420 WARN("DRV_OPEN failed for hic %p\n", whic
->hic
);
421 MSVIDEO_FirstHic
= whic
->next
;
422 HeapFree(GetProcessHeap(), 0, whic
);
426 TRACE("=> %p\n", whic
->hic
);
430 /***********************************************************************
431 * ICOpenFunction [MSVFW32.@]
433 HIC VFWAPI
ICOpenFunction(DWORD fccType
, DWORD fccHandler
, UINT wMode
, FARPROC lpfnHandler
)
435 return MSVIDEO_OpenFunction(fccType
, fccHandler
, wMode
, (DRIVERPROC
)lpfnHandler
, 0);
438 /***********************************************************************
439 * ICGetInfo [MSVFW32.@]
441 LRESULT VFWAPI
ICGetInfo(HIC hic
, ICINFO
*picinfo
, DWORD cb
)
444 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
446 TRACE("(%p,%p,%ld)\n", hic
, picinfo
, cb
);
448 whic
= MSVIDEO_GetHicPtr(hic
);
449 if (!whic
) return ICERR_BADHANDLE
;
450 if (!picinfo
) return MMSYSERR_INVALPARAM
;
452 /* (WS) The field szDriver should be initialized because the driver
453 * is not obliged and often will not do it. Some applications, like
454 * VirtualDub, rely on this field and will occasionally crash if it
457 if (cb
>= sizeof(ICINFO
)) picinfo
->szDriver
[0] = '\0';
459 ret
= ICSendMessage(hic
, ICM_GETINFO
, (DWORD
)picinfo
, cb
);
461 /* (WS) When szDriver was not supplied by the driver itself, apparently
462 * Windows will set its value equal to the driver file name. This can
463 * be obtained from the registry as we do here.
465 if (cb
>= sizeof(ICINFO
) && picinfo
->szDriver
[0] == 0)
469 memset(&ii
, 0, sizeof(ii
));
470 ii
.dwSize
= sizeof(ii
);
471 ICInfo(picinfo
->fccType
, picinfo
->fccHandler
, &ii
);
472 lstrcpyW(picinfo
->szDriver
, ii
.szDriver
);
475 TRACE(" -> 0x%08lx\n", ret
);
479 /***********************************************************************
480 * ICLocate [MSVFW32.@]
482 HIC VFWAPI
ICLocate(DWORD fccType
, DWORD fccHandler
, LPBITMAPINFOHEADER lpbiIn
,
483 LPBITMAPINFOHEADER lpbiOut
, WORD wMode
)
489 TRACE("(%s,%s,%p,%p,0x%04x)\n",
490 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), lpbiIn
, lpbiOut
, wMode
);
494 case ICMODE_FASTCOMPRESS
:
495 case ICMODE_COMPRESS
:
496 querymsg
= ICM_COMPRESS_QUERY
;
498 case ICMODE_FASTDECOMPRESS
:
499 case ICMODE_DECOMPRESS
:
500 querymsg
= ICM_DECOMPRESS_QUERY
;
503 querymsg
= ICM_DRAW_QUERY
;
506 WARN("Unknown mode (%d)\n", wMode
);
510 /* Easy case: handler/type match, we just fire a query and return */
511 hic
= ICOpen(fccType
, fccHandler
, wMode
);
514 if (!ICSendMessage(hic
, querymsg
, (DWORD
)lpbiIn
, (DWORD
)lpbiOut
))
516 TRACE("=> %p\n", hic
);
522 /* Now try each driver in turn. 32 bit codecs only. */
523 /* FIXME: Move this to an init routine? */
525 pszBuffer
= (LPSTR
)HeapAlloc(GetProcessHeap(), 0, 1024);
526 if (GetPrivateProfileSectionA("drivers32", pszBuffer
, 1024, "system.ini"))
533 fcc
[0] = LOBYTE(LOWORD(fccType
));
534 fcc
[1] = HIBYTE(LOWORD(fccType
));
535 fcc
[2] = LOBYTE(HIWORD(fccType
));
536 fcc
[3] = HIBYTE(HIWORD(fccType
));
537 if (!strncasecmp(fcc
, s
, 4) && s
[4] == '.' && s
[9] == '=')
540 while (*s2
!= '\0' && *s2
!= '.') s2
++;
543 hic
= ICOpen(fccType
, mmioStringToFOURCCA(s2
, 0), wMode
);
546 if (!ICSendMessage(hic
, querymsg
, (DWORD
)lpbiIn
, (DWORD
)lpbiOut
))
548 HeapFree(GetProcessHeap(), 0, pszBuffer
);
549 TRACE("=> %p\n", hic
);
559 HeapFree(GetProcessHeap(), 0, pszBuffer
);
561 if (fccType
== streamtypeVIDEO
)
562 return ICLocate(ICTYPE_VIDEO
, fccHandler
, lpbiIn
, lpbiOut
, wMode
);
564 WARN("(%s,%s,%p,%p,0x%04x) not found!\n",
565 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), lpbiIn
, lpbiOut
, wMode
);
569 /***********************************************************************
570 * ICGetDisplayFormat [MSVFW32.@]
572 HIC VFWAPI
ICGetDisplayFormat(
573 HIC hic
,LPBITMAPINFOHEADER lpbiIn
,LPBITMAPINFOHEADER lpbiOut
,
574 INT depth
,INT dx
,INT dy
)
578 TRACE("(%p,%p,%p,%d,%d,%d)!\n",hic
,lpbiIn
,lpbiOut
,depth
,dx
,dy
);
581 tmphic
=ICLocate(ICTYPE_VIDEO
,0,lpbiIn
,NULL
,ICMODE_DECOMPRESS
);
585 if ((dy
== lpbiIn
->biHeight
) && (dx
== lpbiIn
->biWidth
))
586 dy
= dx
= 0; /* no resize needed */
588 /* Can we decompress it ? */
589 if (ICDecompressQuery(tmphic
,lpbiIn
,NULL
) != 0)
590 goto errout
; /* no, sorry */
592 ICDecompressGetFormat(tmphic
,lpbiIn
,lpbiOut
);
594 if (lpbiOut
->biCompression
!= 0) {
595 FIXME("Ooch, how come decompressor outputs compressed data (%ld)??\n",
596 lpbiOut
->biCompression
);
598 if (lpbiOut
->biSize
< sizeof(*lpbiOut
)) {
599 FIXME("Ooch, size of output BIH is too small (%ld)\n",
601 lpbiOut
->biSize
= sizeof(*lpbiOut
);
607 depth
= GetDeviceCaps(hdc
,BITSPIXEL
)*GetDeviceCaps(hdc
,PLANES
);
609 if (depth
==15) depth
= 16;
610 if (depth
<8) depth
= 8;
612 if (lpbiIn
->biBitCount
== 8)
615 TRACE("=> %p\n", tmphic
);
625 /***********************************************************************
626 * ICCompress [MSVFW32.@]
630 HIC hic
,DWORD dwFlags
,LPBITMAPINFOHEADER lpbiOutput
,LPVOID lpData
,
631 LPBITMAPINFOHEADER lpbiInput
,LPVOID lpBits
,LPDWORD lpckid
,
632 LPDWORD lpdwFlags
,LONG lFrameNum
,DWORD dwFrameSize
,DWORD dwQuality
,
633 LPBITMAPINFOHEADER lpbiPrev
,LPVOID lpPrev
)
637 TRACE("(%p,%ld,%p,%p,%p,%p,...)\n",hic
,dwFlags
,lpbiOutput
,lpData
,lpbiInput
,lpBits
);
639 iccmp
.dwFlags
= dwFlags
;
641 iccmp
.lpbiOutput
= lpbiOutput
;
642 iccmp
.lpOutput
= lpData
;
643 iccmp
.lpbiInput
= lpbiInput
;
644 iccmp
.lpInput
= lpBits
;
646 iccmp
.lpckid
= lpckid
;
647 iccmp
.lpdwFlags
= lpdwFlags
;
648 iccmp
.lFrameNum
= lFrameNum
;
649 iccmp
.dwFrameSize
= dwFrameSize
;
650 iccmp
.dwQuality
= dwQuality
;
651 iccmp
.lpbiPrev
= lpbiPrev
;
652 iccmp
.lpPrev
= lpPrev
;
653 return ICSendMessage(hic
,ICM_COMPRESS
,(DWORD
)&iccmp
,sizeof(iccmp
));
656 /***********************************************************************
657 * ICDecompress [MSVFW32.@]
659 DWORD VFWAPIV
ICDecompress(HIC hic
,DWORD dwFlags
,LPBITMAPINFOHEADER lpbiFormat
,
660 LPVOID lpData
,LPBITMAPINFOHEADER lpbi
,LPVOID lpBits
)
665 TRACE("(%p,%ld,%p,%p,%p,%p)\n",hic
,dwFlags
,lpbiFormat
,lpData
,lpbi
,lpBits
);
667 TRACE("lpBits[0] == %lx\n",((LPDWORD
)lpBits
)[0]);
669 icd
.dwFlags
= dwFlags
;
670 icd
.lpbiInput
= lpbiFormat
;
671 icd
.lpInput
= lpData
;
673 icd
.lpbiOutput
= lpbi
;
674 icd
.lpOutput
= lpBits
;
676 ret
= ICSendMessage(hic
,ICM_DECOMPRESS
,(DWORD
)&icd
,sizeof(ICDECOMPRESS
));
678 TRACE("lpBits[0] == %lx\n",((LPDWORD
)lpBits
)[0]);
680 TRACE("-> %ld\n",ret
);
686 /***********************************************************************
687 * ICCompressorChoose [MSVFW32.@]
689 BOOL VFWAPI
ICCompressorChoose(HWND hwnd
, UINT uiFlags
, LPVOID pvIn
,
690 LPVOID lpData
, PCOMPVARS pc
, LPSTR lpszTitle
)
692 FIXME("(%p,0x%X,%p,%p,%p,%s),stub!\n",hwnd
,uiFlags
,pvIn
,lpData
,pc
,lpszTitle
);
694 if (pc
== NULL
|| pc
->cbSize
!= sizeof(COMPVARS
))
697 if ((pc
->dwFlags
& ICMF_COMPVARS_VALID
) == 0) {
699 pc
->fccType
= pc
->fccHandler
= 0;
702 pc
->lpBitsOut
= pc
->lpBitsPrev
= pc
->lpState
= NULL
;
703 pc
->lQ
= ICQUALITY_DEFAULT
;
705 pc
->lDataRate
= 300; /* kB */
709 if (pc
->fccType
== 0)
710 pc
->fccType
= ICTYPE_VIDEO
;
718 /***********************************************************************
719 * ICCompressorFree [MSVFW32.@]
721 void VFWAPI
ICCompressorFree(PCOMPVARS pc
)
725 if (pc
!= NULL
&& pc
->cbSize
== sizeof(COMPVARS
)) {
726 if (pc
->hic
!= NULL
) {
730 if (pc
->lpbiOut
!= NULL
) {
731 GlobalFreePtr(pc
->lpbiOut
);
734 if (pc
->lpBitsOut
!= NULL
) {
735 GlobalFreePtr(pc
->lpBitsOut
);
736 pc
->lpBitsOut
= NULL
;
738 if (pc
->lpBitsPrev
!= NULL
) {
739 GlobalFreePtr(pc
->lpBitsPrev
);
740 pc
->lpBitsPrev
= NULL
;
742 if (pc
->lpState
!= NULL
) {
743 GlobalFreePtr(pc
->lpBitsPrev
);
751 /******************************************************************
752 * MSVIDEO_SendMessage
756 LRESULT
MSVIDEO_SendMessage(WINE_HIC
* whic
, UINT msg
, DWORD lParam1
, DWORD lParam2
)
760 #define XX(x) case x: TRACE("(%p,"#x",0x%08lx,0x%08lx)\n",whic,lParam1,lParam2); break;
775 XX(ICM_GETDEFAULTQUALITY
);
782 XX(ICM_COMPRESS_FRAMES_INFO
);
783 XX(ICM_COMPRESS_GET_FORMAT
);
784 XX(ICM_COMPRESS_GET_SIZE
);
785 XX(ICM_COMPRESS_QUERY
);
786 XX(ICM_COMPRESS_BEGIN
);
788 XX(ICM_COMPRESS_END
);
789 XX(ICM_DECOMPRESS_GET_FORMAT
);
790 XX(ICM_DECOMPRESS_QUERY
);
791 XX(ICM_DECOMPRESS_BEGIN
);
793 XX(ICM_DECOMPRESS_END
);
794 XX(ICM_DECOMPRESS_SET_PALETTE
);
795 XX(ICM_DECOMPRESS_GET_PALETTE
);
798 XX(ICM_DRAW_GET_PALETTE
);
802 XX(ICM_DRAW_GETTIME
);
805 XX(ICM_DRAW_SETTIME
);
806 XX(ICM_DRAW_REALIZE
);
808 XX(ICM_DRAW_RENDERBUFFER
);
809 XX(ICM_DRAW_START_PLAY
);
810 XX(ICM_DRAW_STOP_PLAY
);
811 XX(ICM_DRAW_SUGGESTFORMAT
);
812 XX(ICM_DRAW_CHANGEPALETTE
);
813 XX(ICM_GETBUFFERSWANTED
);
814 XX(ICM_GETDEFAULTKEYFRAMERATE
);
815 XX(ICM_DECOMPRESSEX_BEGIN
);
816 XX(ICM_DECOMPRESSEX_QUERY
);
817 XX(ICM_DECOMPRESSEX
);
818 XX(ICM_DECOMPRESSEX_END
);
819 XX(ICM_SET_STATUS_PROC
);
821 FIXME("(%p,0x%08lx,0x%08lx,0x%08lx) unknown message\n",whic
,(DWORD
)msg
,lParam1
,lParam2
);
826 if (whic
->driverproc
) {
827 /* dwDriverId parameter is the value returned by the DRV_OPEN */
828 ret
= whic
->driverproc(whic
->driverId
, whic
->hdrv
, msg
, lParam1
, lParam2
);
830 ret
= SendDriverMessage(whic
->hdrv
, msg
, lParam1
, lParam2
);
833 TRACE(" -> 0x%08lx\n", ret
);
837 /***********************************************************************
838 * ICSendMessage [MSVFW32.@]
840 LRESULT VFWAPI
ICSendMessage(HIC hic
, UINT msg
, DWORD lParam1
, DWORD lParam2
)
842 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
844 if (!whic
) return ICERR_BADHANDLE
;
845 return MSVIDEO_SendMessage(whic
, msg
, lParam1
, lParam2
);
848 /***********************************************************************
849 * ICDrawBegin [MSVFW32.@]
851 DWORD VFWAPIV
ICDrawBegin(
853 DWORD dwFlags
, /* [in] flags */
854 HPALETTE hpal
, /* [in] palette to draw with */
855 HWND hwnd
, /* [in] window to draw to */
856 HDC hdc
, /* [in] HDC to draw to */
857 INT xDst
, /* [in] destination rectangle */
859 INT dxDst
, /* [in] */
860 INT dyDst
, /* [in] */
861 LPBITMAPINFOHEADER lpbi
, /* [in] format of frame to draw */
862 INT xSrc
, /* [in] source rectangle */
864 INT dxSrc
, /* [in] */
865 INT dySrc
, /* [in] */
866 DWORD dwRate
, /* [in] frames/second = (dwRate/dwScale) */
867 DWORD dwScale
) /* [in] */
872 TRACE("(%p,%ld,%p,%p,%p,%u,%u,%u,%u,%p,%u,%u,%u,%u,%ld,%ld)\n",
873 hic
, dwFlags
, hpal
, hwnd
, hdc
, xDst
, yDst
, dxDst
, dyDst
,
874 lpbi
, xSrc
, ySrc
, dxSrc
, dySrc
, dwRate
, dwScale
);
876 icdb
.dwFlags
= dwFlags
;
889 icdb
.dwRate
= dwRate
;
890 icdb
.dwScale
= dwScale
;
891 return ICSendMessage(hic
,ICM_DRAW_BEGIN
,(DWORD
)&icdb
,sizeof(icdb
));
894 /***********************************************************************
897 DWORD VFWAPIV
ICDraw(HIC hic
, DWORD dwFlags
, LPVOID lpFormat
, LPVOID lpData
, DWORD cbData
, LONG lTime
) {
900 TRACE("(%p,%ld,%p,%p,%ld,%ld)\n",hic
,dwFlags
,lpFormat
,lpData
,cbData
,lTime
);
902 icd
.dwFlags
= dwFlags
;
903 icd
.lpFormat
= lpFormat
;
908 return ICSendMessage(hic
,ICM_DRAW
,(DWORD
)&icd
,sizeof(icd
));
911 /***********************************************************************
912 * ICClose [MSVFW32.@]
914 LRESULT WINAPI
ICClose(HIC hic
)
916 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
921 if (!whic
) return ICERR_BADHANDLE
;
923 if (whic
->driverproc
)
925 MSVIDEO_SendMessage(whic
, DRV_CLOSE
, 0, 0);
926 MSVIDEO_SendMessage(whic
, DRV_DISABLE
, 0, 0);
927 MSVIDEO_SendMessage(whic
, DRV_FREE
, 0, 0);
931 CloseDriver(whic
->hdrv
, 0, 0);
934 /* remove whic from list */
935 for (p
= &MSVIDEO_FirstHic
; *p
!= NULL
; p
= &((*p
)->next
))
944 HeapFree(GetProcessHeap(), 0, whic
);
950 /***********************************************************************
951 * ICImageCompress [MSVFW32.@]
953 HANDLE VFWAPI
ICImageCompress(
954 HIC hic
, UINT uiFlags
,
955 LPBITMAPINFO lpbiIn
, LPVOID lpBits
,
956 LPBITMAPINFO lpbiOut
, LONG lQuality
,
959 FIXME("(%p,%08x,%p,%p,%p,%ld,%p)\n",
960 hic
, uiFlags
, lpbiIn
, lpBits
, lpbiOut
, lQuality
, plSize
);
965 /***********************************************************************
966 * ICImageDecompress [MSVFW32.@]
969 HANDLE VFWAPI
ICImageDecompress(
970 HIC hic
, UINT uiFlags
, LPBITMAPINFO lpbiIn
,
971 LPVOID lpBits
, LPBITMAPINFO lpbiOut
)
975 BOOL bReleaseIC
= FALSE
;
978 BOOL bSucceeded
= FALSE
;
979 BOOL bInDecompress
= FALSE
;
982 TRACE("(%p,%08x,%p,%p,%p)\n",
983 hic
, uiFlags
, lpbiIn
, lpBits
, lpbiOut
);
987 hic
= ICDecompressOpen( ICTYPE_VIDEO
, 0, &lpbiIn
->bmiHeader
, (lpbiOut
!= NULL
) ? &lpbiOut
->bmiHeader
: NULL
);
990 WARN("no handler\n" );
997 FIXME( "unknown flag %08x\n", uiFlags
);
1000 if ( lpbiIn
== NULL
|| lpBits
== NULL
)
1002 WARN("invalid argument\n");
1006 if ( lpbiOut
!= NULL
)
1008 if ( lpbiOut
->bmiHeader
.biSize
!= sizeof(BITMAPINFOHEADER
) )
1010 cbHdr
= sizeof(BITMAPINFOHEADER
);
1011 if ( lpbiOut
->bmiHeader
.biCompression
== 3 )
1012 cbHdr
+= sizeof(DWORD
)*3;
1014 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 )
1016 if ( lpbiOut
->bmiHeader
.biClrUsed
== 0 )
1017 cbHdr
+= sizeof(RGBQUAD
) * (1<<lpbiOut
->bmiHeader
.biBitCount
);
1019 cbHdr
+= sizeof(RGBQUAD
) * lpbiOut
->bmiHeader
.biClrUsed
;
1024 TRACE( "get format\n" );
1026 cbHdr
= ICDecompressGetFormatSize(hic
,lpbiIn
);
1027 if ( cbHdr
< sizeof(BITMAPINFOHEADER
) )
1029 pHdr
= (BYTE
*)HeapAlloc(GetProcessHeap(),0,cbHdr
+sizeof(RGBQUAD
)*256);
1032 ZeroMemory( pHdr
, cbHdr
+sizeof(RGBQUAD
)*256 );
1033 if ( ICDecompressGetFormat( hic
, lpbiIn
, (BITMAPINFO
*)pHdr
) != ICERR_OK
)
1035 lpbiOut
= (BITMAPINFO
*)pHdr
;
1036 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 &&
1037 ICDecompressGetPalette( hic
, lpbiIn
, lpbiOut
) != ICERR_OK
&&
1038 lpbiIn
->bmiHeader
.biBitCount
== lpbiOut
->bmiHeader
.biBitCount
)
1040 if ( lpbiIn
->bmiHeader
.biClrUsed
== 0 )
1041 memcpy( lpbiOut
->bmiColors
, lpbiIn
->bmiColors
, sizeof(RGBQUAD
)*(1<<lpbiOut
->bmiHeader
.biBitCount
) );
1043 memcpy( lpbiOut
->bmiColors
, lpbiIn
->bmiColors
, sizeof(RGBQUAD
)*lpbiIn
->bmiHeader
.biClrUsed
);
1045 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 &&
1046 lpbiOut
->bmiHeader
.biClrUsed
== 0 )
1047 lpbiOut
->bmiHeader
.biClrUsed
= 1<<lpbiOut
->bmiHeader
.biBitCount
;
1049 lpbiOut
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1050 cbHdr
= sizeof(BITMAPINFOHEADER
) + sizeof(RGBQUAD
)*lpbiOut
->bmiHeader
.biClrUsed
;
1053 biSizeImage
= lpbiOut
->bmiHeader
.biSizeImage
;
1054 if ( biSizeImage
== 0 )
1055 biSizeImage
= ((((lpbiOut
->bmiHeader
.biWidth
* lpbiOut
->bmiHeader
.biBitCount
+ 7) >> 3) + 3) & (~3)) * abs(lpbiOut
->bmiHeader
.biHeight
);
1057 TRACE( "call ICDecompressBegin\n" );
1059 if ( ICDecompressBegin( hic
, lpbiIn
, lpbiOut
) != ICERR_OK
)
1061 bInDecompress
= TRUE
;
1063 TRACE( "cbHdr %ld, biSizeImage %ld\n", cbHdr
, biSizeImage
);
1065 hMem
= GlobalAlloc( GMEM_MOVEABLE
|GMEM_ZEROINIT
, cbHdr
+ biSizeImage
);
1068 WARN( "out of memory\n" );
1071 pMem
= (BYTE
*)GlobalLock( hMem
);
1074 memcpy( pMem
, lpbiOut
, cbHdr
);
1076 TRACE( "call ICDecompress\n" );
1077 if ( ICDecompress( hic
, 0, &lpbiIn
->bmiHeader
, lpBits
, &lpbiOut
->bmiHeader
, pMem
+cbHdr
) != ICERR_OK
)
1082 if ( bInDecompress
)
1083 ICDecompressEnd( hic
);
1087 HeapFree(GetProcessHeap(),0,pHdr
);
1089 GlobalUnlock( hMem
);
1090 if ( !bSucceeded
&& hMem
!= NULL
)
1092 GlobalFree(hMem
); hMem
= NULL
;
1095 return (HANDLE
)hMem
;
1098 static BOOL
GetFileNamePreview(LPVOID lpofn
,BOOL bSave
,BOOL bUnicode
)
1100 CHAR szFunctionName
[20];
1101 BOOL (*fnGetFileName
)(LPVOID
);
1105 FIXME("(%p,%d,%d), semi-stub!\n",lpofn
,bSave
,bUnicode
);
1107 lstrcpyA(szFunctionName
, (bSave
? "GetSaveFileName" : "GetOpenFileName"));
1108 lstrcatA(szFunctionName
, (bUnicode
? "W" : "A"));
1110 hComdlg32
= LoadLibraryA("COMDLG32.DLL");
1111 if (hComdlg32
== NULL
)
1114 fnGetFileName
= (LPVOID
)GetProcAddress(hComdlg32
, szFunctionName
);
1115 if (fnGetFileName
== NULL
)
1118 /* FIXME: need to add OFN_ENABLEHOOK and our own handler */
1119 ret
= fnGetFileName(lpofn
);
1121 FreeLibrary(hComdlg32
);
1125 /***********************************************************************
1126 * GetOpenFileNamePreviewA [MSVFW32.@]
1128 BOOL WINAPI
GetOpenFileNamePreviewA(LPOPENFILENAMEA lpofn
)
1130 FIXME("(%p), semi-stub!\n", lpofn
);
1132 return GetFileNamePreview(lpofn
, FALSE
, FALSE
);
1135 /***********************************************************************
1136 * GetOpenFileNamePreviewW [MSVFW32.@]
1138 BOOL WINAPI
GetOpenFileNamePreviewW(LPOPENFILENAMEW lpofn
)
1140 FIXME("(%p), semi-stub!\n", lpofn
);
1142 return GetFileNamePreview(lpofn
, FALSE
, TRUE
);
1145 /***********************************************************************
1146 * GetSaveFileNamePreviewA [MSVFW32.@]
1148 BOOL WINAPI
GetSaveFileNamePreviewA(LPOPENFILENAMEA lpofn
)
1150 FIXME("(%p), semi-stub!\n", lpofn
);
1152 return GetFileNamePreview(lpofn
, TRUE
, FALSE
);
1155 /***********************************************************************
1156 * GetSaveFileNamePreviewW [MSVFW32.@]
1158 BOOL WINAPI
GetSaveFileNamePreviewW(LPOPENFILENAMEW lpofn
)
1160 FIXME("(%p), semi-stub!\n", lpofn
);
1162 return GetFileNamePreview(lpofn
, TRUE
, TRUE
);