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 static int compare_fourcc(DWORD fcc1
, DWORD fcc2
)
69 fcc_str1
[0] = LOBYTE(LOWORD(fcc1
));
70 fcc_str1
[1] = HIBYTE(LOWORD(fcc1
));
71 fcc_str1
[2] = LOBYTE(HIWORD(fcc1
));
72 fcc_str1
[3] = HIBYTE(HIWORD(fcc1
));
74 fcc_str2
[0] = LOBYTE(LOWORD(fcc2
));
75 fcc_str2
[1] = HIBYTE(LOWORD(fcc2
));
76 fcc_str2
[2] = LOBYTE(HIWORD(fcc2
));
77 fcc_str2
[3] = HIBYTE(HIWORD(fcc2
));
80 return strcasecmp(fcc_str1
,fcc_str2
);
83 /******************************************************************
88 WINE_HIC
* MSVIDEO_GetHicPtr(HIC hic
)
92 for (whic
= MSVIDEO_FirstHic
; whic
&& whic
->hic
!= hic
; whic
= whic
->next
);
96 /***********************************************************************
97 * VideoForWindowsVersion [MSVFW32.2]
98 * VideoForWindowsVersion [MSVIDEO.2]
99 * Returns the version in major.minor form.
100 * In Windows95 this returns 0x040003b6 (4.950)
102 DWORD WINAPI
VideoForWindowsVersion(void)
104 return 0x040003B6; /* 4.950 */
107 /* system.ini: [drivers] */
109 /***********************************************************************
111 * Get information about an installable compressor. Return TRUE if there
115 DWORD fccType
, /* [in] type of compressor ('vidc') */
116 DWORD fccHandler
, /* [in] real fcc for handler or <n>th compressor */
117 ICINFO
*lpicinfo
) /* [out] information about compressor */
121 TRACE("(%s,%s/%08lx,%p)\n",
122 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), fccHandler
, lpicinfo
);
124 if (GetPrivateProfileSectionA("drivers32", buf
, sizeof(buf
), "system.ini"))
127 char fccHandlerStr
[4];
130 fccTypeStr
[0] = LOBYTE(LOWORD(fccType
));
131 fccTypeStr
[1] = HIBYTE(LOWORD(fccType
));
132 fccTypeStr
[2] = LOBYTE(HIWORD(fccType
));
133 fccTypeStr
[3] = HIBYTE(HIWORD(fccType
));
135 fccHandlerStr
[0] = LOBYTE(LOWORD(fccHandler
));
136 fccHandlerStr
[1] = HIBYTE(LOWORD(fccHandler
));
137 fccHandlerStr
[2] = LOBYTE(HIWORD(fccHandler
));
138 fccHandlerStr
[3] = HIBYTE(HIWORD(fccHandler
));
140 for (s
= buf
; *s
; s
+= strlen(s
) + 1)
142 if (!strncasecmp(fccTypeStr
, s
, 4) && s
[4] == '.' && s
[9] == '=' &&
143 (!fccHandler
-- || !strncasecmp(fccHandlerStr
, s
+ 5, 4)))
145 /* exact match of fccHandler or nth driver found ?? */
146 lpicinfo
->fccType
= fccType
;
147 lpicinfo
->fccHandler
= mmioStringToFOURCCA(s
+ 5, 0);
148 lpicinfo
->dwFlags
= 0;
149 lpicinfo
->dwVersion
= 0;
150 lpicinfo
->dwVersionICM
= 0x104;
151 lpicinfo
->szName
[0] = 0;
152 lpicinfo
->szDescription
[0] = 0;
153 MultiByteToWideChar(CP_ACP
, 0, s
+ 10, -1,
155 sizeof(lpicinfo
->szDriver
)/sizeof(WCHAR
));
163 static DWORD IC_HandleRef
= 1;
165 /***********************************************************************
166 * ICInstall [MSVFW32.@]
168 BOOL VFWAPI
ICInstall(DWORD fccType
, DWORD fccHandler
, LPARAM lParam
, LPSTR szDesc
, UINT wFlags
)
173 TRACE("(%s,%s,%p,%p,0x%08x)\n", wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), (void*)lParam
, szDesc
, wFlags
);
175 /* Check if a driver is already registered */
176 for (driver
= reg_driver_list
; driver
; driver
= driver
->next
)
178 if (!compare_fourcc(fccType
, driver
->fccType
) &&
179 !compare_fourcc(fccHandler
, driver
->fccHandler
))
182 if (driver
) return FALSE
;
184 /* Register the driver */
185 driver
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(reg_driver
));
186 if (!driver
) goto oom
;
187 driver
->fccType
= fccType
;
188 driver
->fccHandler
= fccHandler
;
192 case ICINSTALL_FUNCTION
:
193 driver
->proc
= (DRIVERPROC
)lParam
;
196 case ICINSTALL_DRIVER
:
198 len
= MultiByteToWideChar(CP_ACP
, 0, (char*)lParam
, -1, NULL
, 0);
199 driver
->name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
200 if (!driver
->name
) goto oom
;
201 MultiByteToWideChar(CP_ACP
, 0, (char*)lParam
, -1, driver
->name
, len
);
204 ERR("Invalid flags!\n");
205 HeapFree(GetProcessHeap(), 0, driver
);
209 /* Insert our driver in the list*/
210 driver
->next
= reg_driver_list
;
211 reg_driver_list
= driver
;
215 if (driver
) HeapFree(GetProcessHeap(), 0, driver
);
219 /***********************************************************************
220 * ICRemove [MSVFW32.@]
222 BOOL VFWAPI
ICRemove(DWORD fccType
, DWORD fccHandler
, UINT wFlags
)
224 reg_driver
** pdriver
;
226 TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), wFlags
);
228 /* Check if a driver is already registered */
229 for (pdriver
= ®_driver_list
; *pdriver
; pdriver
= &(*pdriver
)->next
)
231 if (!compare_fourcc(fccType
, (*pdriver
)->fccType
) &&
232 !compare_fourcc(fccHandler
, (*pdriver
)->fccHandler
))
238 /* Remove the driver from the list */
239 *pdriver
= (*pdriver
)->next
;
240 if ((*pdriver
)->name
)
241 HeapFree(GetProcessHeap(), 0, (*pdriver
)->name
);
242 HeapFree(GetProcessHeap(), 0, *pdriver
);
248 /***********************************************************************
250 * Opens an installable compressor. Return special handle.
252 HIC VFWAPI
ICOpen(DWORD fccType
, DWORD fccHandler
, UINT wMode
)
259 static WCHAR drv32W
[] = {'d','r','i','v','e','r','s','3','2','\0'};
262 TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), wMode
);
264 /* Check if there is a registered driver that matches */
265 driver
= reg_driver_list
;
267 if (!compare_fourcc(fccType
, driver
->fccType
) &&
268 !compare_fourcc(fccHandler
, driver
->fccHandler
))
271 driver
= driver
->next
;
273 if (driver
&& driver
->proc
)
274 /* The driver has been registered at runtime with its driverproc */
275 return MSVIDEO_OpenFunction(fccType
, fccHandler
, wMode
, (DRIVERPROC
)driver
->proc
, (DWORD
)NULL
);
277 /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the
278 * same layout as ICOPEN
280 icopen
.dwSize
= sizeof(ICOPEN
);
281 icopen
.fccType
= fccType
;
282 icopen
.fccHandler
= fccHandler
;
283 icopen
.dwVersion
= 0x00001000; /* FIXME */
284 icopen
.dwFlags
= wMode
;
286 icopen
.pV1Reserved
= NULL
;
287 icopen
.pV2Reserved
= NULL
;
288 icopen
.dnDevNode
= 0; /* FIXME */
291 /* The driver is registered in the registry */
292 codecname
[0] = LOBYTE(LOWORD(fccType
));
293 codecname
[1] = HIBYTE(LOWORD(fccType
));
294 codecname
[2] = LOBYTE(HIWORD(fccType
));
295 codecname
[3] = HIBYTE(HIWORD(fccType
));
297 codecname
[5] = LOBYTE(LOWORD(fccHandler
));
298 codecname
[6] = HIBYTE(LOWORD(fccHandler
));
299 codecname
[7] = LOBYTE(HIWORD(fccHandler
));
300 codecname
[8] = HIBYTE(HIWORD(fccHandler
));
303 hdrv
= OpenDriver(codecname
, drv32W
, (LPARAM
)&icopen
);
306 if (fccType
== streamtypeVIDEO
)
313 fccType
= ICTYPE_VIDEO
;
314 hdrv
= OpenDriver(codecname
, drv32W
, (LPARAM
)&icopen
);
320 /* The driver has been registered at runtime with its name */
321 hdrv
= OpenDriver(driver
->name
, NULL
, (LPARAM
)&icopen
);
325 bIs16
= GetDriverFlags(hdrv
) & 0x10000000; /* undocumented flag: WINE_GDF_16BIT */
327 if (bIs16
&& !pFnCallTo16
)
329 FIXME("Got a 16 bit driver, but no 16 bit support in msvfw\n");
332 whic
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC
));
335 CloseDriver(hdrv
, 0, 0);
339 /* FIXME: is the signature the real one ? */
340 whic
->driverproc
= bIs16
? (DRIVERPROC
)pFnCallTo16
: NULL
;
341 whic
->driverproc16
= 0;
342 whic
->type
= fccType
;
343 whic
->handler
= fccHandler
;
344 while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef
)) != NULL
) IC_HandleRef
++;
345 whic
->hic
= HIC_32(IC_HandleRef
++);
346 whic
->next
= MSVIDEO_FirstHic
;
347 MSVIDEO_FirstHic
= whic
;
349 TRACE("=> %p\n", whic
->hic
);
353 /***********************************************************************
354 * MSVIDEO_OpenFunction
356 HIC
MSVIDEO_OpenFunction(DWORD fccType
, DWORD fccHandler
, UINT wMode
,
357 DRIVERPROC lpfnHandler
, DWORD lpfnHandler16
)
362 TRACE("(%s,%s,%d,%p,%08lx)\n",
363 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), wMode
, lpfnHandler
, lpfnHandler16
);
365 icopen
.dwSize
= sizeof(ICOPEN
);
366 icopen
.fccType
= fccType
;
367 icopen
.fccHandler
= fccHandler
;
368 icopen
.dwVersion
= 0x00001000; /* FIXME */
369 icopen
.dwFlags
= wMode
;
371 icopen
.pV1Reserved
= NULL
;
372 icopen
.pV2Reserved
= NULL
;
373 icopen
.dnDevNode
= 0; /* FIXME */
375 whic
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC
));
378 whic
->driverproc
= lpfnHandler
;
379 whic
->driverproc16
= lpfnHandler16
;
380 while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef
)) != NULL
) IC_HandleRef
++;
381 whic
->hic
= HIC_32(IC_HandleRef
++);
382 whic
->next
= MSVIDEO_FirstHic
;
383 MSVIDEO_FirstHic
= whic
;
385 /* Now try opening/loading the driver. Taken from DRIVER_AddToList */
386 /* What if the function is used more than once? */
388 if (MSVIDEO_SendMessage(whic
, DRV_LOAD
, 0L, 0L) != DRV_SUCCESS
)
390 WARN("DRV_LOAD failed for hic %p\n", whic
->hic
);
391 MSVIDEO_FirstHic
= whic
->next
;
392 HeapFree(GetProcessHeap(), 0, whic
);
395 /* return value is not checked */
396 MSVIDEO_SendMessage(whic
, DRV_ENABLE
, 0L, 0L);
398 whic
->driverId
= (DWORD
)MSVIDEO_SendMessage(whic
, DRV_OPEN
, 0, (DWORD
)&icopen
);
399 /* FIXME: What should we put here? */
400 whic
->hdrv
= (HDRVR
)0;
402 if (whic
->driverId
== 0)
404 WARN("DRV_OPEN failed for hic %p\n", whic
->hic
);
405 MSVIDEO_FirstHic
= whic
->next
;
406 HeapFree(GetProcessHeap(), 0, whic
);
410 TRACE("=> %p\n", whic
->hic
);
414 /***********************************************************************
415 * ICOpenFunction [MSVFW32.@]
417 HIC VFWAPI
ICOpenFunction(DWORD fccType
, DWORD fccHandler
, UINT wMode
, FARPROC lpfnHandler
)
419 return MSVIDEO_OpenFunction(fccType
, fccHandler
, wMode
, (DRIVERPROC
)lpfnHandler
, 0);
422 /***********************************************************************
423 * ICGetInfo [MSVFW32.@]
425 LRESULT VFWAPI
ICGetInfo(HIC hic
, ICINFO
*picinfo
, DWORD cb
)
428 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
430 TRACE("(%p,%p,%ld)\n", hic
, picinfo
, cb
);
432 whic
= MSVIDEO_GetHicPtr(hic
);
433 if (!whic
) return ICERR_BADHANDLE
;
434 if (!picinfo
) return MMSYSERR_INVALPARAM
;
436 /* (WS) The field szDriver should be initialized because the driver
437 * is not obliged and often will not do it. Some applications, like
438 * VirtualDub, rely on this field and will occasionally crash if it
441 if (cb
>= sizeof(ICINFO
)) picinfo
->szDriver
[0] = '\0';
443 ret
= ICSendMessage(hic
, ICM_GETINFO
, (DWORD
)picinfo
, cb
);
445 /* (WS) When szDriver was not supplied by the driver itself, apparently
446 * Windows will set its value equal to the driver file name. This can
447 * be obtained from the registry as we do here.
449 if (cb
>= sizeof(ICINFO
) && picinfo
->szDriver
[0] == 0)
453 memset(&ii
, 0, sizeof(ii
));
454 ii
.dwSize
= sizeof(ii
);
455 ICInfo(picinfo
->fccType
, picinfo
->fccHandler
, &ii
);
456 lstrcpyW(picinfo
->szDriver
, ii
.szDriver
);
459 TRACE(" -> 0x%08lx\n", ret
);
463 /***********************************************************************
464 * ICLocate [MSVFW32.@]
466 HIC VFWAPI
ICLocate(DWORD fccType
, DWORD fccHandler
, LPBITMAPINFOHEADER lpbiIn
,
467 LPBITMAPINFOHEADER lpbiOut
, WORD wMode
)
473 TRACE("(%s,%s,%p,%p,0x%04x)\n",
474 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), lpbiIn
, lpbiOut
, wMode
);
478 case ICMODE_FASTCOMPRESS
:
479 case ICMODE_COMPRESS
:
480 querymsg
= ICM_COMPRESS_QUERY
;
482 case ICMODE_FASTDECOMPRESS
:
483 case ICMODE_DECOMPRESS
:
484 querymsg
= ICM_DECOMPRESS_QUERY
;
487 querymsg
= ICM_DRAW_QUERY
;
490 WARN("Unknown mode (%d)\n", wMode
);
494 /* Easy case: handler/type match, we just fire a query and return */
495 hic
= ICOpen(fccType
, fccHandler
, wMode
);
498 if (!ICSendMessage(hic
, querymsg
, (DWORD
)lpbiIn
, (DWORD
)lpbiOut
))
500 TRACE("=> %p\n", hic
);
506 /* Now try each driver in turn. 32 bit codecs only. */
507 /* FIXME: Move this to an init routine? */
509 pszBuffer
= (LPSTR
)HeapAlloc(GetProcessHeap(), 0, 1024);
510 if (GetPrivateProfileSectionA("drivers32", pszBuffer
, 1024, "system.ini"))
517 fcc
[0] = LOBYTE(LOWORD(fccType
));
518 fcc
[1] = HIBYTE(LOWORD(fccType
));
519 fcc
[2] = LOBYTE(HIWORD(fccType
));
520 fcc
[3] = HIBYTE(HIWORD(fccType
));
521 if (!strncasecmp(fcc
, s
, 4) && s
[4] == '.' && s
[9] == '=')
524 while (*s2
!= '\0' && *s2
!= '.') s2
++;
527 hic
= ICOpen(fccType
, mmioStringToFOURCCA(s2
, 0), wMode
);
530 if (!ICSendMessage(hic
, querymsg
, (DWORD
)lpbiIn
, (DWORD
)lpbiOut
))
532 HeapFree(GetProcessHeap(), 0, pszBuffer
);
533 TRACE("=> %p\n", hic
);
543 HeapFree(GetProcessHeap(), 0, pszBuffer
);
545 if (fccType
== streamtypeVIDEO
)
546 return ICLocate(ICTYPE_VIDEO
, fccHandler
, lpbiIn
, lpbiOut
, wMode
);
548 WARN("(%s,%s,%p,%p,0x%04x) not found!\n",
549 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), lpbiIn
, lpbiOut
, wMode
);
553 /***********************************************************************
554 * ICGetDisplayFormat [MSVFW32.@]
556 HIC VFWAPI
ICGetDisplayFormat(
557 HIC hic
,LPBITMAPINFOHEADER lpbiIn
,LPBITMAPINFOHEADER lpbiOut
,
558 INT depth
,INT dx
,INT dy
)
562 FIXME("(%p,%p,%p,%d,%d,%d),stub!\n",hic
,lpbiIn
,lpbiOut
,depth
,dx
,dy
);
564 tmphic
=ICLocate(ICTYPE_VIDEO
,0,lpbiIn
,NULL
,ICMODE_DECOMPRESS
);
568 if ((dy
== lpbiIn
->biHeight
) && (dx
== lpbiIn
->biWidth
))
569 dy
= dx
= 0; /* no resize needed */
571 /* Can we decompress it ? */
572 if (ICDecompressQuery(tmphic
,lpbiIn
,NULL
) != 0)
573 goto errout
; /* no, sorry */
575 ICDecompressGetFormat(tmphic
,lpbiIn
,lpbiOut
);
577 if (lpbiOut
->biCompression
!= 0) {
578 FIXME("Ooch, how come decompressor outputs compressed data (%ld)??\n",
579 lpbiOut
->biCompression
);
581 if (lpbiOut
->biSize
< sizeof(*lpbiOut
)) {
582 FIXME("Ooch, size of output BIH is too small (%ld)\n",
584 lpbiOut
->biSize
= sizeof(*lpbiOut
);
590 depth
= GetDeviceCaps(hdc
,BITSPIXEL
)*GetDeviceCaps(hdc
,PLANES
);
592 if (depth
==15) depth
= 16;
593 if (depth
<8) depth
= 8;
595 if (lpbiIn
->biBitCount
== 8)
598 TRACE("=> %p\n", tmphic
);
608 /***********************************************************************
609 * ICCompress [MSVFW32.@]
613 HIC hic
,DWORD dwFlags
,LPBITMAPINFOHEADER lpbiOutput
,LPVOID lpData
,
614 LPBITMAPINFOHEADER lpbiInput
,LPVOID lpBits
,LPDWORD lpckid
,
615 LPDWORD lpdwFlags
,LONG lFrameNum
,DWORD dwFrameSize
,DWORD dwQuality
,
616 LPBITMAPINFOHEADER lpbiPrev
,LPVOID lpPrev
)
620 TRACE("(%p,%ld,%p,%p,%p,%p,...)\n",hic
,dwFlags
,lpbiOutput
,lpData
,lpbiInput
,lpBits
);
622 iccmp
.dwFlags
= dwFlags
;
624 iccmp
.lpbiOutput
= lpbiOutput
;
625 iccmp
.lpOutput
= lpData
;
626 iccmp
.lpbiInput
= lpbiInput
;
627 iccmp
.lpInput
= lpBits
;
629 iccmp
.lpckid
= lpckid
;
630 iccmp
.lpdwFlags
= lpdwFlags
;
631 iccmp
.lFrameNum
= lFrameNum
;
632 iccmp
.dwFrameSize
= dwFrameSize
;
633 iccmp
.dwQuality
= dwQuality
;
634 iccmp
.lpbiPrev
= lpbiPrev
;
635 iccmp
.lpPrev
= lpPrev
;
636 return ICSendMessage(hic
,ICM_COMPRESS
,(DWORD
)&iccmp
,sizeof(iccmp
));
639 /***********************************************************************
640 * ICDecompress [MSVFW32.@]
642 DWORD VFWAPIV
ICDecompress(HIC hic
,DWORD dwFlags
,LPBITMAPINFOHEADER lpbiFormat
,
643 LPVOID lpData
,LPBITMAPINFOHEADER lpbi
,LPVOID lpBits
)
648 TRACE("(%p,%ld,%p,%p,%p,%p)\n",hic
,dwFlags
,lpbiFormat
,lpData
,lpbi
,lpBits
);
650 TRACE("lpBits[0] == %lx\n",((LPDWORD
)lpBits
)[0]);
652 icd
.dwFlags
= dwFlags
;
653 icd
.lpbiInput
= lpbiFormat
;
654 icd
.lpInput
= lpData
;
656 icd
.lpbiOutput
= lpbi
;
657 icd
.lpOutput
= lpBits
;
659 ret
= ICSendMessage(hic
,ICM_DECOMPRESS
,(DWORD
)&icd
,sizeof(ICDECOMPRESS
));
661 TRACE("lpBits[0] == %lx\n",((LPDWORD
)lpBits
)[0]);
663 TRACE("-> %ld\n",ret
);
669 /***********************************************************************
670 * ICCompressorChoose [MSVFW32.@]
672 BOOL VFWAPI
ICCompressorChoose(HWND hwnd
, UINT uiFlags
, LPVOID pvIn
,
673 LPVOID lpData
, PCOMPVARS pc
, LPSTR lpszTitle
)
675 FIXME("(%p,0x%X,%p,%p,%p,%s),stub!\n",hwnd
,uiFlags
,pvIn
,lpData
,pc
,lpszTitle
);
677 if (pc
== NULL
|| pc
->cbSize
!= sizeof(COMPVARS
))
680 if ((pc
->dwFlags
& ICMF_COMPVARS_VALID
) == 0) {
682 pc
->fccType
= pc
->fccHandler
= 0;
685 pc
->lpBitsOut
= pc
->lpBitsPrev
= pc
->lpState
= NULL
;
686 pc
->lQ
= ICQUALITY_DEFAULT
;
688 pc
->lDataRate
= 300; /* kB */
692 if (pc
->fccType
== 0)
693 pc
->fccType
= ICTYPE_VIDEO
;
701 /***********************************************************************
702 * ICCompressorFree [MSVFW32.@]
704 void VFWAPI
ICCompressorFree(PCOMPVARS pc
)
708 if (pc
!= NULL
&& pc
->cbSize
== sizeof(COMPVARS
)) {
709 if (pc
->hic
!= NULL
) {
713 if (pc
->lpbiOut
!= NULL
) {
714 GlobalFreePtr(pc
->lpbiOut
);
717 if (pc
->lpBitsOut
!= NULL
) {
718 GlobalFreePtr(pc
->lpBitsOut
);
719 pc
->lpBitsOut
= NULL
;
721 if (pc
->lpBitsPrev
!= NULL
) {
722 GlobalFreePtr(pc
->lpBitsPrev
);
723 pc
->lpBitsPrev
= NULL
;
725 if (pc
->lpState
!= NULL
) {
726 GlobalFreePtr(pc
->lpBitsPrev
);
734 /******************************************************************
735 * MSVIDEO_SendMessage
739 LRESULT
MSVIDEO_SendMessage(WINE_HIC
* whic
, UINT msg
, DWORD lParam1
, DWORD lParam2
)
743 #define XX(x) case x: TRACE("(%p,"#x",0x%08lx,0x%08lx)\n",whic,lParam1,lParam2); break;
758 XX(ICM_GETDEFAULTQUALITY
);
765 XX(ICM_COMPRESS_FRAMES_INFO
);
766 XX(ICM_COMPRESS_GET_FORMAT
);
767 XX(ICM_COMPRESS_GET_SIZE
);
768 XX(ICM_COMPRESS_QUERY
);
769 XX(ICM_COMPRESS_BEGIN
);
771 XX(ICM_COMPRESS_END
);
772 XX(ICM_DECOMPRESS_GET_FORMAT
);
773 XX(ICM_DECOMPRESS_QUERY
);
774 XX(ICM_DECOMPRESS_BEGIN
);
776 XX(ICM_DECOMPRESS_END
);
777 XX(ICM_DECOMPRESS_SET_PALETTE
);
778 XX(ICM_DECOMPRESS_GET_PALETTE
);
781 XX(ICM_DRAW_GET_PALETTE
);
785 XX(ICM_DRAW_GETTIME
);
788 XX(ICM_DRAW_SETTIME
);
789 XX(ICM_DRAW_REALIZE
);
791 XX(ICM_DRAW_RENDERBUFFER
);
792 XX(ICM_DRAW_START_PLAY
);
793 XX(ICM_DRAW_STOP_PLAY
);
794 XX(ICM_DRAW_SUGGESTFORMAT
);
795 XX(ICM_DRAW_CHANGEPALETTE
);
796 XX(ICM_GETBUFFERSWANTED
);
797 XX(ICM_GETDEFAULTKEYFRAMERATE
);
798 XX(ICM_DECOMPRESSEX_BEGIN
);
799 XX(ICM_DECOMPRESSEX_QUERY
);
800 XX(ICM_DECOMPRESSEX
);
801 XX(ICM_DECOMPRESSEX_END
);
802 XX(ICM_SET_STATUS_PROC
);
804 FIXME("(%p,0x%08lx,0x%08lx,0x%08lx) unknown message\n",whic
,(DWORD
)msg
,lParam1
,lParam2
);
809 if (whic
->driverproc
) {
810 /* dwDriverId parameter is the value returned by the DRV_OPEN */
811 ret
= whic
->driverproc(whic
->driverId
, whic
->hdrv
, msg
, lParam1
, lParam2
);
813 ret
= SendDriverMessage(whic
->hdrv
, msg
, lParam1
, lParam2
);
816 TRACE(" -> 0x%08lx\n", ret
);
820 /***********************************************************************
821 * ICSendMessage [MSVFW32.@]
823 LRESULT VFWAPI
ICSendMessage(HIC hic
, UINT msg
, DWORD lParam1
, DWORD lParam2
)
825 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
827 if (!whic
) return ICERR_BADHANDLE
;
828 return MSVIDEO_SendMessage(whic
, msg
, lParam1
, lParam2
);
831 /***********************************************************************
832 * ICDrawBegin [MSVFW32.@]
834 DWORD VFWAPIV
ICDrawBegin(
836 DWORD dwFlags
, /* [in] flags */
837 HPALETTE hpal
, /* [in] palette to draw with */
838 HWND hwnd
, /* [in] window to draw to */
839 HDC hdc
, /* [in] HDC to draw to */
840 INT xDst
, /* [in] destination rectangle */
842 INT dxDst
, /* [in] */
843 INT dyDst
, /* [in] */
844 LPBITMAPINFOHEADER lpbi
, /* [in] format of frame to draw */
845 INT xSrc
, /* [in] source rectangle */
847 INT dxSrc
, /* [in] */
848 INT dySrc
, /* [in] */
849 DWORD dwRate
, /* [in] frames/second = (dwRate/dwScale) */
850 DWORD dwScale
) /* [in] */
855 TRACE("(%p,%ld,%p,%p,%p,%u,%u,%u,%u,%p,%u,%u,%u,%u,%ld,%ld)\n",
856 hic
, dwFlags
, hpal
, hwnd
, hdc
, xDst
, yDst
, dxDst
, dyDst
,
857 lpbi
, xSrc
, ySrc
, dxSrc
, dySrc
, dwRate
, dwScale
);
859 icdb
.dwFlags
= dwFlags
;
872 icdb
.dwRate
= dwRate
;
873 icdb
.dwScale
= dwScale
;
874 return ICSendMessage(hic
,ICM_DRAW_BEGIN
,(DWORD
)&icdb
,sizeof(icdb
));
877 /***********************************************************************
880 DWORD VFWAPIV
ICDraw(HIC hic
, DWORD dwFlags
, LPVOID lpFormat
, LPVOID lpData
, DWORD cbData
, LONG lTime
) {
883 TRACE("(%p,%ld,%p,%p,%ld,%ld)\n",hic
,dwFlags
,lpFormat
,lpData
,cbData
,lTime
);
885 icd
.dwFlags
= dwFlags
;
886 icd
.lpFormat
= lpFormat
;
891 return ICSendMessage(hic
,ICM_DRAW
,(DWORD
)&icd
,sizeof(icd
));
894 /***********************************************************************
895 * ICClose [MSVFW32.@]
897 LRESULT WINAPI
ICClose(HIC hic
)
899 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
904 if (!whic
) return ICERR_BADHANDLE
;
906 if (whic
->driverproc
)
908 MSVIDEO_SendMessage(whic
, DRV_CLOSE
, 0, 0);
909 MSVIDEO_SendMessage(whic
, DRV_DISABLE
, 0, 0);
910 MSVIDEO_SendMessage(whic
, DRV_FREE
, 0, 0);
914 CloseDriver(whic
->hdrv
, 0, 0);
917 /* remove whic from list */
918 for (p
= &MSVIDEO_FirstHic
; *p
!= NULL
; p
= &((*p
)->next
))
927 HeapFree(GetProcessHeap(), 0, whic
);
933 /***********************************************************************
934 * ICImageCompress [MSVFW32.@]
936 HANDLE VFWAPI
ICImageCompress(
937 HIC hic
, UINT uiFlags
,
938 LPBITMAPINFO lpbiIn
, LPVOID lpBits
,
939 LPBITMAPINFO lpbiOut
, LONG lQuality
,
942 FIXME("(%p,%08x,%p,%p,%p,%ld,%p)\n",
943 hic
, uiFlags
, lpbiIn
, lpBits
, lpbiOut
, lQuality
, plSize
);
948 /***********************************************************************
949 * ICImageDecompress [MSVFW32.@]
952 HANDLE VFWAPI
ICImageDecompress(
953 HIC hic
, UINT uiFlags
, LPBITMAPINFO lpbiIn
,
954 LPVOID lpBits
, LPBITMAPINFO lpbiOut
)
958 BOOL bReleaseIC
= FALSE
;
961 BOOL bSucceeded
= FALSE
;
962 BOOL bInDecompress
= FALSE
;
965 TRACE("(%p,%08x,%p,%p,%p)\n",
966 hic
, uiFlags
, lpbiIn
, lpBits
, lpbiOut
);
970 hic
= ICDecompressOpen( ICTYPE_VIDEO
, 0, &lpbiIn
->bmiHeader
, (lpbiOut
!= NULL
) ? &lpbiOut
->bmiHeader
: NULL
);
973 WARN("no handler\n" );
980 FIXME( "unknown flag %08x\n", uiFlags
);
983 if ( lpbiIn
== NULL
|| lpBits
== NULL
)
985 WARN("invalid argument\n");
989 if ( lpbiOut
!= NULL
)
991 if ( lpbiOut
->bmiHeader
.biSize
!= sizeof(BITMAPINFOHEADER
) )
993 cbHdr
= sizeof(BITMAPINFOHEADER
);
994 if ( lpbiOut
->bmiHeader
.biCompression
== 3 )
995 cbHdr
+= sizeof(DWORD
)*3;
997 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 )
999 if ( lpbiOut
->bmiHeader
.biClrUsed
== 0 )
1000 cbHdr
+= sizeof(RGBQUAD
) * (1<<lpbiOut
->bmiHeader
.biBitCount
);
1002 cbHdr
+= sizeof(RGBQUAD
) * lpbiOut
->bmiHeader
.biClrUsed
;
1007 TRACE( "get format\n" );
1009 cbHdr
= ICDecompressGetFormatSize(hic
,lpbiIn
);
1010 if ( cbHdr
< sizeof(BITMAPINFOHEADER
) )
1012 pHdr
= (BYTE
*)HeapAlloc(GetProcessHeap(),0,cbHdr
+sizeof(RGBQUAD
)*256);
1015 ZeroMemory( pHdr
, cbHdr
+sizeof(RGBQUAD
)*256 );
1016 if ( ICDecompressGetFormat( hic
, lpbiIn
, (BITMAPINFO
*)pHdr
) != ICERR_OK
)
1018 lpbiOut
= (BITMAPINFO
*)pHdr
;
1019 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 &&
1020 ICDecompressGetPalette( hic
, lpbiIn
, lpbiOut
) != ICERR_OK
&&
1021 lpbiIn
->bmiHeader
.biBitCount
== lpbiOut
->bmiHeader
.biBitCount
)
1023 if ( lpbiIn
->bmiHeader
.biClrUsed
== 0 )
1024 memcpy( lpbiOut
->bmiColors
, lpbiIn
->bmiColors
, sizeof(RGBQUAD
)*(1<<lpbiOut
->bmiHeader
.biBitCount
) );
1026 memcpy( lpbiOut
->bmiColors
, lpbiIn
->bmiColors
, sizeof(RGBQUAD
)*lpbiIn
->bmiHeader
.biClrUsed
);
1028 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 &&
1029 lpbiOut
->bmiHeader
.biClrUsed
== 0 )
1030 lpbiOut
->bmiHeader
.biClrUsed
= 1<<lpbiOut
->bmiHeader
.biBitCount
;
1032 lpbiOut
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1033 cbHdr
= sizeof(BITMAPINFOHEADER
) + sizeof(RGBQUAD
)*lpbiOut
->bmiHeader
.biClrUsed
;
1036 biSizeImage
= lpbiOut
->bmiHeader
.biSizeImage
;
1037 if ( biSizeImage
== 0 )
1038 biSizeImage
= ((((lpbiOut
->bmiHeader
.biWidth
* lpbiOut
->bmiHeader
.biBitCount
+ 7) >> 3) + 3) & (~3)) * abs(lpbiOut
->bmiHeader
.biHeight
);
1040 TRACE( "call ICDecompressBegin\n" );
1042 if ( ICDecompressBegin( hic
, lpbiIn
, lpbiOut
) != ICERR_OK
)
1044 bInDecompress
= TRUE
;
1046 TRACE( "cbHdr %ld, biSizeImage %ld\n", cbHdr
, biSizeImage
);
1048 hMem
= GlobalAlloc( GMEM_MOVEABLE
|GMEM_ZEROINIT
, cbHdr
+ biSizeImage
);
1051 WARN( "out of memory\n" );
1054 pMem
= (BYTE
*)GlobalLock( hMem
);
1057 memcpy( pMem
, lpbiOut
, cbHdr
);
1059 TRACE( "call ICDecompress\n" );
1060 if ( ICDecompress( hic
, 0, &lpbiIn
->bmiHeader
, lpBits
, &lpbiOut
->bmiHeader
, pMem
+cbHdr
) != ICERR_OK
)
1065 if ( bInDecompress
)
1066 ICDecompressEnd( hic
);
1070 HeapFree(GetProcessHeap(),0,pHdr
);
1072 GlobalUnlock( hMem
);
1073 if ( !bSucceeded
&& hMem
!= NULL
)
1075 GlobalFree(hMem
); hMem
= NULL
;
1078 return (HANDLE
)hMem
;
1081 static BOOL
GetFileNamePreview(LPVOID lpofn
,BOOL bSave
,BOOL bUnicode
)
1083 CHAR szFunctionName
[20];
1084 BOOL (*fnGetFileName
)(LPVOID
);
1088 FIXME("(%p,%d,%d), semi-stub!\n",lpofn
,bSave
,bUnicode
);
1090 lstrcpyA(szFunctionName
, (bSave
? "GetSaveFileName" : "GetOpenFileName"));
1091 lstrcatA(szFunctionName
, (bUnicode
? "W" : "A"));
1093 hComdlg32
= LoadLibraryA("COMDLG32.DLL");
1094 if (hComdlg32
== NULL
)
1097 fnGetFileName
= (LPVOID
)GetProcAddress(hComdlg32
, szFunctionName
);
1098 if (fnGetFileName
== NULL
)
1101 /* FIXME: need to add OFN_ENABLEHOOK and our own handler */
1102 ret
= fnGetFileName(lpofn
);
1104 FreeLibrary(hComdlg32
);
1108 /***********************************************************************
1109 * GetOpenFileNamePreviewA [MSVFW32.@]
1111 BOOL WINAPI
GetOpenFileNamePreviewA(LPOPENFILENAMEA lpofn
)
1113 FIXME("(%p), semi-stub!\n", lpofn
);
1115 return GetFileNamePreview(lpofn
, FALSE
, FALSE
);
1118 /***********************************************************************
1119 * GetOpenFileNamePreviewW [MSVFW32.@]
1121 BOOL WINAPI
GetOpenFileNamePreviewW(LPOPENFILENAMEW lpofn
)
1123 FIXME("(%p), semi-stub!\n", lpofn
);
1125 return GetFileNamePreview(lpofn
, FALSE
, TRUE
);
1128 /***********************************************************************
1129 * GetSaveFileNamePreviewA [MSVFW32.@]
1131 BOOL WINAPI
GetSaveFileNamePreviewA(LPOPENFILENAMEA lpofn
)
1133 FIXME("(%p), semi-stub!\n", lpofn
);
1135 return GetFileNamePreview(lpofn
, TRUE
, FALSE
);
1138 /***********************************************************************
1139 * GetSaveFileNamePreviewW [MSVFW32.@]
1141 BOOL WINAPI
GetSaveFileNamePreviewW(LPOPENFILENAMEW lpofn
)
1143 FIXME("(%p), semi-stub!\n", lpofn
);
1145 return GetFileNamePreview(lpofn
, TRUE
, TRUE
);