2 * Copyright 1998 Marcus Meissner
3 * Copyright 2000 Bradley Baetz
4 * Copyright 2003 Michael Günnewig
5 * Copyright 2005 Dmitry Timoshkov
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * FIXME: This all assumes 32 bit codecs
22 * Win95 appears to prefer 32 bit codecs, even from 16 bit code.
23 * There is the ICOpenFunction16 to worry about still, though.
41 #include "msvideo_private.h"
42 #include "wine/debug.h"
44 /* Drivers32 settings */
45 #define HKLM_DRIVERS32 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32"
47 WINE_DEFAULT_DEBUG_CHANNEL(msvideo
);
49 /* This one is a macro in order to work for both ASCII and Unicode */
50 #define fourcc_to_string(str, fcc) do { \
51 (str)[0] = LOBYTE(LOWORD(fcc)); \
52 (str)[1] = HIBYTE(LOWORD(fcc)); \
53 (str)[2] = LOBYTE(HIWORD(fcc)); \
54 (str)[3] = HIBYTE(HIWORD(fcc)); \
57 static inline const char *wine_dbgstr_fcc( DWORD fcc
)
60 fourcc_to_string(fcc_str
, fcc
);
62 /* Last byte may be ' ' in some cases like "DIB " */
63 if (isalnum(fcc_str
[0]) && isalnum(fcc_str
[1]) && isalnum(fcc_str
[2])
64 && (isalnum(fcc_str
[3]) || isspace(fcc_str
[3])))
65 return wine_dbg_sprintf("%s", fcc_str
);
66 return wine_dbg_sprintf("0x%08x", fcc
);
69 static const char *wine_dbgstr_icerr( int ret
)
72 if (ret
<= ICERR_CUSTOM
)
73 return wine_dbg_sprintf("ICERR_CUSTOM (%d)", ret
);
74 #define XX(x) case (x): str = #x; break
80 XX(ICERR_GOTOKEYFRAME
);
81 XX(ICERR_STOPDRAWING
);
82 XX(ICERR_UNSUPPORTED
);
93 XX(ICERR_BADBITDEPTH
);
94 XX(ICERR_BADIMAGESIZE
);
95 default: str
= wine_dbg_sprintf("UNKNOWN (%d)", ret
);
101 static WINE_HIC
* MSVIDEO_FirstHic
/* = NULL */;
103 typedef struct _reg_driver reg_driver
;
113 static reg_driver
* reg_driver_list
= NULL
;
115 HMODULE MSVFW32_hModule
;
117 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
119 TRACE("%p,%x,%p\n", hinst
, reason
, reserved
);
123 case DLL_PROCESS_ATTACH
:
124 DisableThreadLibraryCalls(hinst
);
125 MSVFW32_hModule
= hinst
;
131 /******************************************************************
132 * MSVIDEO_SendMessage
136 static LRESULT
MSVIDEO_SendMessage(WINE_HIC
* whic
, UINT msg
, DWORD_PTR lParam1
, DWORD_PTR lParam2
)
140 #define XX(x) case x: TRACE("(%p,"#x",0x%08lx,0x%08lx)\n",whic,lParam1,lParam2); break
155 XX(ICM_GETDEFAULTQUALITY
);
162 XX(ICM_COMPRESS_FRAMES_INFO
);
163 XX(ICM_COMPRESS_GET_FORMAT
);
164 XX(ICM_COMPRESS_GET_SIZE
);
165 XX(ICM_COMPRESS_QUERY
);
166 XX(ICM_COMPRESS_BEGIN
);
168 XX(ICM_COMPRESS_END
);
169 XX(ICM_DECOMPRESS_GET_FORMAT
);
170 XX(ICM_DECOMPRESS_QUERY
);
171 XX(ICM_DECOMPRESS_BEGIN
);
173 XX(ICM_DECOMPRESS_END
);
174 XX(ICM_DECOMPRESS_SET_PALETTE
);
175 XX(ICM_DECOMPRESS_GET_PALETTE
);
178 XX(ICM_DRAW_GET_PALETTE
);
182 XX(ICM_DRAW_GETTIME
);
185 XX(ICM_DRAW_SETTIME
);
186 XX(ICM_DRAW_REALIZE
);
188 XX(ICM_DRAW_RENDERBUFFER
);
189 XX(ICM_DRAW_START_PLAY
);
190 XX(ICM_DRAW_STOP_PLAY
);
191 XX(ICM_DRAW_SUGGESTFORMAT
);
192 XX(ICM_DRAW_CHANGEPALETTE
);
193 XX(ICM_GETBUFFERSWANTED
);
194 XX(ICM_GETDEFAULTKEYFRAMERATE
);
195 XX(ICM_DECOMPRESSEX_BEGIN
);
196 XX(ICM_DECOMPRESSEX_QUERY
);
197 XX(ICM_DECOMPRESSEX
);
198 XX(ICM_DECOMPRESSEX_END
);
199 XX(ICM_SET_STATUS_PROC
);
201 FIXME("(%p,0x%08x,0x%08lx,0x%08lx) unknown message\n",whic
,msg
,lParam1
,lParam2
);
206 if (whic
->driverproc
) {
207 /* dwDriverId parameter is the value returned by the DRV_OPEN */
208 ret
= whic
->driverproc(whic
->driverId
, whic
->hdrv
, msg
, lParam1
, lParam2
);
210 ret
= SendDriverMessage(whic
->hdrv
, msg
, lParam1
, lParam2
);
213 TRACE(" -> %s\n", wine_dbgstr_icerr(ret
));
217 static int compare_fourcc(DWORD fcc1
, DWORD fcc2
)
221 fourcc_to_string(fcc_str1
, fcc1
);
222 fourcc_to_string(fcc_str2
, fcc2
);
223 return strncasecmp(fcc_str1
, fcc_str2
, 4);
226 static DWORD
get_size_image(LONG width
, LONG height
, WORD depth
)
228 DWORD ret
= width
* depth
;
229 ret
= (ret
+ 7) / 8; /* divide by byte size, rounding up */
230 ret
= (ret
+ 3) & ~3; /* align to 4 bytes */
235 typedef BOOL (*enum_handler_t
)(const char *name
, const char *driver
, unsigned int index
, void *param
);
237 static BOOL
enum_drivers(DWORD fccType
, enum_handler_t handler
, void* param
)
243 DWORD i
, cnt
= 0, lRet
;
247 fourcc_to_string(fccTypeStr
, fccType
);
249 /* first, go through the registry entries */
250 lRet
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
, HKLM_DRIVERS32
, 0, KEY_QUERY_VALUE
, &hKey
);
251 if (lRet
== ERROR_SUCCESS
)
256 DWORD name_len
= 10, driver_len
= 128;
257 lRet
= RegEnumValueA(hKey
, i
++, name_buf
, &name_len
, 0, 0, (BYTE
*)buf
, &driver_len
);
258 if (lRet
== ERROR_NO_MORE_ITEMS
) break;
259 if (name_len
!= 9 || name_buf
[4] != '.') continue;
260 if (fccType
&& strncasecmp(name_buf
, fccTypeStr
, 4)) continue;
261 if ((result
= handler(name_buf
, buf
, cnt
++, param
))) break;
265 if (result
) return result
;
267 /* if that didn't work, go through the values in system.ini */
268 if (GetPrivateProfileSectionA("drivers32", buf
, sizeof(buf
), "system.ini"))
271 for (s
= buf
; *s
; s
+= strlen(s
) + 1)
273 if (s
[4] != '.' || s
[9] != '=') continue;
274 if (fccType
&& strncasecmp(s
, fccTypeStr
, 4)) continue;
275 if ((result
= handler(s
, s
+ 10, cnt
++, param
))) break;
282 /******************************************************************
287 static WINE_HIC
* MSVIDEO_GetHicPtr(HIC hic
)
291 for (whic
= MSVIDEO_FirstHic
; whic
&& whic
->hic
!= hic
; whic
= whic
->next
);
295 /***********************************************************************
296 * VideoForWindowsVersion [MSVFW32.2]
297 * VideoForWindowsVersion [MSVIDEO.2]
298 * Returns the version in major.minor form.
299 * In Windows95 this returns 0x040003b6 (4.950)
301 DWORD WINAPI
VideoForWindowsVersion(void)
303 return 0x040003B6; /* 4.950 */
306 static BOOL
ICInfo_enum_handler(const char *name
, const char *driver
, unsigned int nr
, void *param
)
308 ICINFO
*lpicinfo
= param
;
309 DWORD fccType
= mmioStringToFOURCCA(name
, 0);
310 DWORD fccHandler
= mmioStringToFOURCCA(name
+ 5, 0);
312 if (lpicinfo
->fccHandler
!= nr
&& compare_fourcc(lpicinfo
->fccHandler
, fccHandler
))
315 lpicinfo
->fccType
= fccType
;
316 lpicinfo
->fccHandler
= fccHandler
;
317 lpicinfo
->dwFlags
= 0;
318 lpicinfo
->dwVersion
= 0;
319 lpicinfo
->dwVersionICM
= ICVERSION
;
320 lpicinfo
->szName
[0] = 0;
321 lpicinfo
->szDescription
[0] = 0;
322 MultiByteToWideChar(CP_ACP
, 0, driver
, -1, lpicinfo
->szDriver
, ARRAY_SIZE(lpicinfo
->szDriver
));
327 /***********************************************************************
329 * Get information about an installable compressor. Return TRUE if there
333 * fccType [I] type of compressor (e.g. 'vidc')
334 * fccHandler [I] real fcc for handler or <n>th compressor
335 * lpicinfo [O] information about compressor
337 BOOL VFWAPI
ICInfo( DWORD fccType
, DWORD fccHandler
, ICINFO
*lpicinfo
)
339 TRACE("(%s,%s,%p)\n",
340 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), lpicinfo
);
342 lpicinfo
->fccType
= fccType
;
343 lpicinfo
->fccHandler
= fccHandler
;
344 return enum_drivers(fccType
, ICInfo_enum_handler
, lpicinfo
);
347 static DWORD IC_HandleRef
= 1;
349 /***********************************************************************
350 * ICInstall [MSVFW32.@]
352 BOOL VFWAPI
ICInstall(DWORD fccType
, DWORD fccHandler
, LPARAM lParam
, LPSTR szDesc
, UINT wFlags
)
357 TRACE("(%s,%s,%p,%p,0x%08x)\n", wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), (void*)lParam
, szDesc
, wFlags
);
359 /* Check if a driver is already registered */
360 for (driver
= reg_driver_list
; driver
; driver
= driver
->next
)
362 if (!compare_fourcc(fccType
, driver
->fccType
) &&
363 !compare_fourcc(fccHandler
, driver
->fccHandler
))
366 if (driver
) return FALSE
;
368 /* Register the driver */
369 driver
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(reg_driver
));
370 if (!driver
) goto oom
;
371 driver
->fccType
= fccType
;
372 driver
->fccHandler
= fccHandler
;
376 case ICINSTALL_FUNCTION
:
377 driver
->proc
= (DRIVERPROC
)lParam
;
380 case ICINSTALL_DRIVER
:
382 len
= MultiByteToWideChar(CP_ACP
, 0, (char*)lParam
, -1, NULL
, 0);
383 driver
->name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
384 if (!driver
->name
) goto oom
;
385 MultiByteToWideChar(CP_ACP
, 0, (char*)lParam
, -1, driver
->name
, len
);
388 ERR("Invalid flags!\n");
389 HeapFree(GetProcessHeap(), 0, driver
);
393 /* Insert our driver in the list*/
394 driver
->next
= reg_driver_list
;
395 reg_driver_list
= driver
;
399 HeapFree(GetProcessHeap(), 0, driver
);
403 /***********************************************************************
404 * ICRemove [MSVFW32.@]
406 BOOL VFWAPI
ICRemove(DWORD fccType
, DWORD fccHandler
, UINT wFlags
)
408 reg_driver
** pdriver
;
411 TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), wFlags
);
413 /* Check if a driver is already registered */
414 for (pdriver
= ®_driver_list
; *pdriver
; pdriver
= &(*pdriver
)->next
)
416 if (!compare_fourcc(fccType
, (*pdriver
)->fccType
) &&
417 !compare_fourcc(fccHandler
, (*pdriver
)->fccHandler
))
423 /* Remove the driver from the list */
425 *pdriver
= (*pdriver
)->next
;
426 HeapFree(GetProcessHeap(), 0, drv
->name
);
427 HeapFree(GetProcessHeap(), 0, drv
);
433 /***********************************************************************
435 * Opens an installable compressor. Return special handle.
437 HIC VFWAPI
ICOpen(DWORD fccType
, DWORD fccHandler
, UINT wMode
)
443 static const WCHAR drv32W
[] = {'d','r','i','v','e','r','s','3','2','\0'};
446 TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), wMode
);
448 if (!fccHandler
) /* No specific handler, return the first valid for wMode */
453 info
.dwSize
= sizeof(info
);
454 while(ICInfo(fccType
, loop
++, &info
))
456 /* Ensure fccHandler is not 0x0 because we will recurse on ICOpen */
459 local
= ICOpen(fccType
, info
.fccHandler
, wMode
);
462 TRACE("Returning %s as default handler for %s\n",
463 wine_dbgstr_fcc(info
.fccHandler
), wine_dbgstr_fcc(fccType
));
469 /* Check if there is a registered driver that matches */
470 driver
= reg_driver_list
;
472 if (!compare_fourcc(fccType
, driver
->fccType
) &&
473 !compare_fourcc(fccHandler
, driver
->fccHandler
)) {
474 fccType
= driver
->fccType
;
475 fccHandler
= driver
->fccHandler
;
478 driver
= driver
->next
;
480 if (driver
&& driver
->proc
)
481 /* The driver has been registered at runtime with its driverproc */
482 return ICOpenFunction(fccType
, fccHandler
, wMode
, driver
->proc
);
484 /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the
485 * same layout as ICOPEN
487 icopen
.dwSize
= sizeof(ICOPEN
);
488 icopen
.fccType
= fccType
;
489 icopen
.fccHandler
= fccHandler
;
490 icopen
.dwVersion
= 0x00001000; /* FIXME */
491 icopen
.dwFlags
= wMode
;
493 icopen
.pV1Reserved
= NULL
;
494 icopen
.pV2Reserved
= NULL
;
495 icopen
.dnDevNode
= 0; /* FIXME */
498 /* normalize to lower case as in 'vidc' */
499 ((char*)&fccType
)[0] = tolower(((char*)&fccType
)[0]);
500 ((char*)&fccType
)[1] = tolower(((char*)&fccType
)[1]);
501 ((char*)&fccType
)[2] = tolower(((char*)&fccType
)[2]);
502 ((char*)&fccType
)[3] = tolower(((char*)&fccType
)[3]);
503 icopen
.fccType
= fccType
;
504 /* Seek the driver in the registry */
505 fourcc_to_string(codecname
, fccType
);
507 fourcc_to_string(codecname
+ 5, fccHandler
);
510 hdrv
= OpenDriver(codecname
, drv32W
, (LPARAM
)&icopen
);
514 /* The driver has been registered at runtime with its name */
515 hdrv
= OpenDriver(driver
->name
, NULL
, (LPARAM
)&icopen
);
520 whic
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC
));
523 CloseDriver(hdrv
, 0, 0);
527 whic
->driverproc
= NULL
;
528 whic
->type
= fccType
;
529 whic
->handler
= fccHandler
;
530 while (MSVIDEO_GetHicPtr((HIC
)(ULONG_PTR
)IC_HandleRef
) != NULL
) IC_HandleRef
++;
531 whic
->hic
= (HIC
)(ULONG_PTR
)IC_HandleRef
++;
532 whic
->next
= MSVIDEO_FirstHic
;
533 MSVIDEO_FirstHic
= whic
;
535 TRACE("=> %p\n", whic
->hic
);
539 /***********************************************************************
540 * ICOpenFunction [MSVFW32.@]
542 HIC VFWAPI
ICOpenFunction(DWORD fccType
, DWORD fccHandler
, UINT wMode
, DRIVERPROC lpfnHandler
)
547 TRACE("(%s,%s,%d,%p)\n",
548 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), wMode
, lpfnHandler
);
550 icopen
.dwSize
= sizeof(ICOPEN
);
551 icopen
.fccType
= fccType
;
552 icopen
.fccHandler
= fccHandler
;
553 icopen
.dwVersion
= ICVERSION
;
554 icopen
.dwFlags
= wMode
;
556 icopen
.pV1Reserved
= NULL
;
557 icopen
.pV2Reserved
= NULL
;
558 icopen
.dnDevNode
= 0; /* FIXME */
560 whic
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC
));
563 whic
->driverproc
= lpfnHandler
;
564 while (MSVIDEO_GetHicPtr((HIC
)(ULONG_PTR
)IC_HandleRef
) != NULL
) IC_HandleRef
++;
565 whic
->hic
= (HIC
)(ULONG_PTR
)IC_HandleRef
++;
566 whic
->next
= MSVIDEO_FirstHic
;
567 MSVIDEO_FirstHic
= whic
;
569 /* Now try opening/loading the driver. Taken from DRIVER_AddToList */
570 /* What if the function is used more than once? */
572 if (MSVIDEO_SendMessage(whic
, DRV_LOAD
, 0L, 0L) != DRV_SUCCESS
)
574 WARN("DRV_LOAD failed for hic %p\n", whic
->hic
);
575 MSVIDEO_FirstHic
= whic
->next
;
576 HeapFree(GetProcessHeap(), 0, whic
);
579 /* return value is not checked */
580 MSVIDEO_SendMessage(whic
, DRV_ENABLE
, 0L, 0L);
582 whic
->driverId
= (DWORD
)MSVIDEO_SendMessage(whic
, DRV_OPEN
, 0, (DWORD_PTR
)&icopen
);
583 /* FIXME: What should we put here? */
586 if (whic
->driverId
== 0)
588 WARN("DRV_OPEN failed for hic %p\n", whic
->hic
);
589 MSVIDEO_FirstHic
= whic
->next
;
590 HeapFree(GetProcessHeap(), 0, whic
);
594 TRACE("=> %p\n", whic
->hic
);
598 /***********************************************************************
599 * ICGetInfo [MSVFW32.@]
601 LRESULT VFWAPI
ICGetInfo(HIC hic
, ICINFO
*picinfo
, DWORD cb
)
604 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
606 TRACE("(%p,%p,%d)\n", hic
, picinfo
, cb
);
608 if (!whic
) return ICERR_BADHANDLE
;
609 if (!picinfo
) return MMSYSERR_INVALPARAM
;
611 /* (WS) The field szDriver should be initialized because the driver
612 * is not obliged and often will not do it. Some applications, like
613 * VirtualDub, rely on this field and will occasionally crash if it
614 * goes uninitialized.
616 if (cb
>= sizeof(ICINFO
)) picinfo
->szDriver
[0] = '\0';
618 ret
= ICSendMessage(hic
, ICM_GETINFO
, (DWORD_PTR
)picinfo
, cb
);
620 /* (WS) When szDriver was not supplied by the driver itself, apparently
621 * Windows will set its value equal to the driver file name. This can
622 * be obtained from the registry as we do here.
624 if (cb
>= sizeof(ICINFO
) && picinfo
->szDriver
[0] == 0)
628 memset(&ii
, 0, sizeof(ii
));
629 ii
.dwSize
= sizeof(ii
);
630 ICInfo(picinfo
->fccType
, picinfo
->fccHandler
, &ii
);
631 lstrcpyW(picinfo
->szDriver
, ii
.szDriver
);
640 LPBITMAPINFOHEADER lpbiIn
;
641 LPBITMAPINFOHEADER lpbiOut
;
647 static HIC
try_driver(driver_info_t
*info
)
651 if ((hic
= ICOpen(info
->fccType
, info
->fccHandler
, info
->wMode
)))
653 if (!ICSendMessage(hic
, info
->querymsg
, (DWORD_PTR
)info
->lpbiIn
, (DWORD_PTR
)info
->lpbiOut
))
660 static BOOL
ICLocate_enum_handler(const char *name
, const char *driver
, unsigned int nr
, void *param
)
662 driver_info_t
*info
= param
;
663 info
->fccHandler
= mmioStringToFOURCCA(name
+ 5, 0);
664 info
->hic
= try_driver(info
);
665 return info
->hic
!= 0;
668 /***********************************************************************
669 * ICLocate [MSVFW32.@]
671 HIC VFWAPI
ICLocate(DWORD fccType
, DWORD fccHandler
, LPBITMAPINFOHEADER lpbiIn
,
672 LPBITMAPINFOHEADER lpbiOut
, WORD wMode
)
676 TRACE("(%s,%s,%p,%p,0x%04x)\n",
677 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), lpbiIn
, lpbiOut
, wMode
);
679 info
.fccType
= fccType
;
680 info
.fccHandler
= fccHandler
;
681 info
.lpbiIn
= lpbiIn
;
682 info
.lpbiOut
= lpbiOut
;
687 case ICMODE_FASTCOMPRESS
:
688 case ICMODE_COMPRESS
:
689 info
.querymsg
= ICM_COMPRESS_QUERY
;
691 case ICMODE_FASTDECOMPRESS
:
692 case ICMODE_DECOMPRESS
:
693 info
.querymsg
= ICM_DECOMPRESS_QUERY
;
696 info
.querymsg
= ICM_DRAW_QUERY
;
699 WARN("Unknown mode (%d)\n", wMode
);
703 /* Easy case: handler/type match, we just fire a query and return */
704 info
.hic
= try_driver(&info
);
705 /* If it didn't work, try each driver in turn. 32 bit codecs only. */
706 /* FIXME: Move this to an init routine? */
707 if (!info
.hic
) enum_drivers(fccType
, ICLocate_enum_handler
, &info
);
711 TRACE("=> %p\n", info
.hic
);
715 if (fccType
== streamtypeVIDEO
)
716 return ICLocate(ICTYPE_VIDEO
, fccHandler
, lpbiIn
, lpbiOut
, wMode
);
718 ERR("Required media codec '%s %s' not found!\n",
719 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
));
723 /***********************************************************************
724 * ICGetDisplayFormat [MSVFW32.@]
726 HIC VFWAPI
ICGetDisplayFormat(HIC hic
, BITMAPINFOHEADER
*in
, BITMAPINFOHEADER
*out
,
727 int depth
, int width
, int height
)
731 TRACE("(%p, %p, %p, %d, %d, %d)\n", hic
, in
, out
, depth
, width
, height
);
735 tmphic
= ICLocate(ICTYPE_VIDEO
, 0, in
, NULL
, ICMODE_DECOMPRESS
);
740 if (ICDecompressQuery(tmphic
, in
, NULL
))
743 if (width
<= 0 || height
<= 0)
746 height
= in
->biHeight
;
753 out
->biSize
= sizeof(*out
);
754 out
->biWidth
= width
;
755 out
->biHeight
= height
;
756 out
->biCompression
= BI_RGB
;
757 out
->biSizeImage
= get_size_image(width
, height
, depth
);
759 /* first try the given depth */
760 out
->biBitCount
= depth
;
761 out
->biSizeImage
= get_size_image(width
, height
, out
->biBitCount
);
762 if (!ICDecompressQuery(tmphic
, in
, out
))
765 ICDecompressGetPalette(tmphic
, in
, out
);
769 /* then try 16, both with BI_RGB and BI_BITFIELDS */
772 out
->biBitCount
= 16;
773 out
->biSizeImage
= get_size_image(width
, height
, out
->biBitCount
);
774 if (!ICDecompressQuery(tmphic
, in
, out
))
777 out
->biCompression
= BI_BITFIELDS
;
778 if (!ICDecompressQuery(tmphic
, in
, out
))
780 out
->biCompression
= BI_RGB
;
786 out
->biBitCount
= 24;
787 out
->biSizeImage
= get_size_image(width
, height
, out
->biBitCount
);
788 if (!ICDecompressQuery(tmphic
, in
, out
))
795 out
->biBitCount
= 32;
796 out
->biSizeImage
= get_size_image(width
, height
, out
->biBitCount
);
797 if (!ICDecompressQuery(tmphic
, in
, out
))
801 /* as a last resort, try 32 bpp with the original width and height */
802 out
->biWidth
= in
->biWidth
;
803 out
->biHeight
= in
->biHeight
;
804 out
->biBitCount
= 32;
805 out
->biSizeImage
= get_size_image(out
->biWidth
, out
->biHeight
, out
->biBitCount
);
806 if (!ICDecompressQuery(tmphic
, in
, out
))
809 /* finally, ask the compressor for its default output format */
810 if (!ICSendMessage(tmphic
, ICM_DECOMPRESS_GET_FORMAT
, (DWORD_PTR
)in
, (DWORD_PTR
)out
))
820 /***********************************************************************
821 * ICCompress [MSVFW32.@]
825 HIC hic
,DWORD dwFlags
,LPBITMAPINFOHEADER lpbiOutput
,LPVOID lpData
,
826 LPBITMAPINFOHEADER lpbiInput
,LPVOID lpBits
,LPDWORD lpckid
,
827 LPDWORD lpdwFlags
,LONG lFrameNum
,DWORD dwFrameSize
,DWORD dwQuality
,
828 LPBITMAPINFOHEADER lpbiPrev
,LPVOID lpPrev
)
832 TRACE("(%p,%d,%p,%p,%p,%p,...)\n",hic
,dwFlags
,lpbiOutput
,lpData
,lpbiInput
,lpBits
);
834 iccmp
.dwFlags
= dwFlags
;
836 iccmp
.lpbiOutput
= lpbiOutput
;
837 iccmp
.lpOutput
= lpData
;
838 iccmp
.lpbiInput
= lpbiInput
;
839 iccmp
.lpInput
= lpBits
;
841 iccmp
.lpckid
= lpckid
;
842 iccmp
.lpdwFlags
= lpdwFlags
;
843 iccmp
.lFrameNum
= lFrameNum
;
844 iccmp
.dwFrameSize
= dwFrameSize
;
845 iccmp
.dwQuality
= dwQuality
;
846 iccmp
.lpbiPrev
= lpbiPrev
;
847 iccmp
.lpPrev
= lpPrev
;
848 return ICSendMessage(hic
,ICM_COMPRESS
,(DWORD_PTR
)&iccmp
,sizeof(iccmp
));
851 /***********************************************************************
852 * ICDecompress [MSVFW32.@]
854 DWORD VFWAPIV
ICDecompress(HIC hic
,DWORD dwFlags
,LPBITMAPINFOHEADER lpbiFormat
,
855 LPVOID lpData
,LPBITMAPINFOHEADER lpbi
,LPVOID lpBits
)
860 TRACE("(%p,%d,%p,%p,%p,%p)\n",hic
,dwFlags
,lpbiFormat
,lpData
,lpbi
,lpBits
);
862 icd
.dwFlags
= dwFlags
;
863 icd
.lpbiInput
= lpbiFormat
;
864 icd
.lpInput
= lpData
;
866 icd
.lpbiOutput
= lpbi
;
867 icd
.lpOutput
= lpBits
;
869 ret
= ICSendMessage(hic
,ICM_DECOMPRESS
,(DWORD_PTR
)&icd
,sizeof(ICDECOMPRESS
));
875 struct choose_compressor
888 static BOOL
enum_compressors(HWND list
, COMPVARS
*pcv
, BOOL enum_all
)
895 while (ICInfo(pcv
->fccType
, id
, &icinfo
))
897 struct codec_info
*ic
;
903 hic
= ICOpen(icinfo
.fccType
, icinfo
.fccHandler
, ICMODE_COMPRESS
);
907 /* for unknown reason fccHandler reported by the driver
908 * doesn't always work, use the one returned by ICInfo instead.
910 DWORD fccHandler
= icinfo
.fccHandler
;
912 if (!enum_all
&& pcv
->lpbiIn
)
914 if (ICCompressQuery(hic
, pcv
->lpbiIn
, NULL
) != ICERR_OK
)
916 TRACE("fccHandler %s doesn't support input DIB format %d\n",
917 wine_dbgstr_fcc(icinfo
.fccHandler
), pcv
->lpbiIn
->bmiHeader
.biCompression
);
923 ICGetInfo(hic
, &icinfo
, sizeof(icinfo
));
924 icinfo
.fccHandler
= fccHandler
;
926 idx
= SendMessageW(list
, CB_ADDSTRING
, 0, (LPARAM
)icinfo
.szDescription
);
928 ic
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct codec_info
));
931 SendMessageW(list
, CB_SETITEMDATA
, idx
, (LPARAM
)ic
);
939 static INT_PTR CALLBACK
icm_choose_compressor_dlgproc(HWND hdlg
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
945 struct codec_info
*ic
;
947 struct choose_compressor
*choose_comp
= (struct choose_compressor
*)lparam
;
949 SetWindowLongPtrW(hdlg
, DWLP_USER
, lparam
);
952 choose_comp
->flags
&= ~(ICMF_CHOOSE_DATARATE
| ICMF_CHOOSE_KEYFRAME
);
954 if (choose_comp
->title
)
955 SetWindowTextA(hdlg
, choose_comp
->title
);
957 if (!(choose_comp
->flags
& ICMF_CHOOSE_DATARATE
))
959 ShowWindow(GetDlgItem(hdlg
, IDC_DATARATE_CHECKBOX
), SW_HIDE
);
960 ShowWindow(GetDlgItem(hdlg
, IDC_DATARATE
), SW_HIDE
);
961 ShowWindow(GetDlgItem(hdlg
, IDC_DATARATE_KB
), SW_HIDE
);
964 if (!(choose_comp
->flags
& ICMF_CHOOSE_KEYFRAME
))
966 ShowWindow(GetDlgItem(hdlg
, IDC_KEYFRAME_CHECKBOX
), SW_HIDE
);
967 ShowWindow(GetDlgItem(hdlg
, IDC_KEYFRAME
), SW_HIDE
);
968 ShowWindow(GetDlgItem(hdlg
, IDC_KEYFRAME_FRAMES
), SW_HIDE
);
972 EnableWindow(GetDlgItem(hdlg
, IDC_QUALITY_SCROLL
), FALSE
);
973 EnableWindow(GetDlgItem(hdlg
, IDC_QUALITY_TXT
), FALSE
);
975 /*if (!(choose_comp->flags & ICMF_CHOOSE_PREVIEW))
976 ShowWindow(GetDlgItem(hdlg, IDC_PREVIEW), SW_HIDE);*/
978 LoadStringW(MSVFW32_hModule
, IDS_FULLFRAMES
, buf
, 128);
979 SendDlgItemMessageW(hdlg
, IDC_COMP_LIST
, CB_ADDSTRING
, 0, (LPARAM
)buf
);
981 ic
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct codec_info
));
982 ic
->icinfo
.fccType
= streamtypeVIDEO
;
983 ic
->icinfo
.fccHandler
= comptypeDIB
;
985 SendDlgItemMessageW(hdlg
, IDC_COMP_LIST
, CB_SETITEMDATA
, 0, (LPARAM
)ic
);
987 enum_compressors(GetDlgItem(hdlg
, IDC_COMP_LIST
), &choose_comp
->cv
, choose_comp
->flags
& ICMF_CHOOSE_ALLCOMPRESSORS
);
989 SendDlgItemMessageW(hdlg
, IDC_COMP_LIST
, CB_SETCURSEL
, 0, 0);
990 SetFocus(GetDlgItem(hdlg
, IDC_COMP_LIST
));
992 SetWindowLongPtrW(hdlg
, DWLP_USER
, (ULONG_PTR
)choose_comp
);
997 switch (LOWORD(wparam
))
1002 struct codec_info
*ic
;
1003 BOOL can_configure
= FALSE
, can_about
= FALSE
;
1004 struct choose_compressor
*choose_comp
;
1006 if (HIWORD(wparam
) != CBN_SELCHANGE
&& HIWORD(wparam
) != CBN_SETFOCUS
)
1009 choose_comp
= (struct choose_compressor
*)GetWindowLongPtrW(hdlg
, DWLP_USER
);
1011 cur_sel
= SendMessageW((HWND
)lparam
, CB_GETCURSEL
, 0, 0);
1013 ic
= (struct codec_info
*)SendMessageW((HWND
)lparam
, CB_GETITEMDATA
, cur_sel
, 0);
1016 if (ICQueryConfigure(ic
->hic
) == DRVCNF_OK
)
1017 can_configure
= TRUE
;
1018 if (ICQueryAbout(ic
->hic
) == DRVCNF_OK
)
1021 EnableWindow(GetDlgItem(hdlg
, IDC_CONFIGURE
), can_configure
);
1022 EnableWindow(GetDlgItem(hdlg
, IDC_ABOUT
), can_about
);
1024 if (choose_comp
->flags
& ICMF_CHOOSE_DATARATE
)
1028 if (choose_comp
->flags
& ICMF_CHOOSE_KEYFRAME
)
1039 HWND list
= GetDlgItem(hdlg
, IDC_COMP_LIST
);
1041 struct codec_info
*ic
;
1043 if (HIWORD(wparam
) != BN_CLICKED
)
1046 cur_sel
= SendMessageW(list
, CB_GETCURSEL
, 0, 0);
1048 ic
= (struct codec_info
*)SendMessageW(list
, CB_GETITEMDATA
, cur_sel
, 0);
1051 if (LOWORD(wparam
) == IDC_CONFIGURE
)
1052 ICConfigure(ic
->hic
, hdlg
);
1054 ICAbout(ic
->hic
, hdlg
);
1062 HWND list
= GetDlgItem(hdlg
, IDC_COMP_LIST
);
1064 struct codec_info
*ic
;
1066 if (HIWORD(wparam
) != BN_CLICKED
)
1069 cur_sel
= SendMessageW(list
, CB_GETCURSEL
, 0, 0);
1070 ic
= (struct codec_info
*)SendMessageW(list
, CB_GETITEMDATA
, cur_sel
, 0);
1073 struct choose_compressor
*choose_comp
= (struct choose_compressor
*)GetWindowLongPtrW(hdlg
, DWLP_USER
);
1075 choose_comp
->cv
.hic
= ic
->hic
;
1076 choose_comp
->cv
.fccType
= ic
->icinfo
.fccType
;
1077 choose_comp
->cv
.fccHandler
= ic
->icinfo
.fccHandler
;
1078 /* FIXME: fill everything else */
1080 /* prevent closing the codec handle below */
1087 HWND list
= GetDlgItem(hdlg
, IDC_COMP_LIST
);
1090 if (HIWORD(wparam
) != BN_CLICKED
)
1095 struct codec_info
*ic
;
1097 ic
= (struct codec_info
*)SendMessageW(list
, CB_GETITEMDATA
, idx
++, 0);
1099 if (!ic
|| (LONG_PTR
)ic
== CB_ERR
) break;
1101 if (ic
->hic
) ICClose(ic
->hic
);
1102 HeapFree(GetProcessHeap(), 0, ic
);
1105 EndDialog(hdlg
, LOWORD(wparam
) == IDOK
);
1121 /***********************************************************************
1122 * ICCompressorChoose [MSVFW32.@]
1124 BOOL VFWAPI
ICCompressorChoose(HWND hwnd
, UINT uiFlags
, LPVOID pvIn
,
1125 LPVOID lpData
, PCOMPVARS pc
, LPSTR lpszTitle
)
1127 struct choose_compressor choose_comp
;
1130 TRACE("(%p,%08x,%p,%p,%p,%s)\n", hwnd
, uiFlags
, pvIn
, lpData
, pc
, lpszTitle
);
1132 if (!pc
|| pc
->cbSize
!= sizeof(COMPVARS
))
1135 if (!(pc
->dwFlags
& ICMF_COMPVARS_VALID
))
1138 pc
->fccType
= pc
->fccHandler
= 0;
1142 pc
->lpBitsOut
= pc
->lpBitsPrev
= pc
->lpState
= NULL
;
1143 pc
->lQ
= ICQUALITY_DEFAULT
;
1145 pc
->lDataRate
= 300; /* kB */
1149 if (pc
->fccType
== 0)
1150 pc
->fccType
= ICTYPE_VIDEO
;
1152 choose_comp
.cv
= *pc
;
1153 choose_comp
.flags
= uiFlags
;
1154 choose_comp
.title
= lpszTitle
;
1156 ret
= DialogBoxParamW(MSVFW32_hModule
, MAKEINTRESOURCEW(ICM_CHOOSE_COMPRESSOR
), hwnd
,
1157 icm_choose_compressor_dlgproc
, (LPARAM
)&choose_comp
);
1161 *pc
= choose_comp
.cv
;
1162 pc
->dwFlags
|= ICMF_COMPVARS_VALID
;
1169 /***********************************************************************
1170 * ICCompressorFree [MSVFW32.@]
1172 void VFWAPI
ICCompressorFree(PCOMPVARS pc
)
1176 if (pc
!= NULL
&& pc
->cbSize
== sizeof(COMPVARS
)) {
1177 if (pc
->hic
!= NULL
) {
1181 HeapFree(GetProcessHeap(), 0, pc
->lpbiIn
);
1183 HeapFree(GetProcessHeap(), 0, pc
->lpBitsOut
);
1184 pc
->lpBitsOut
= NULL
;
1185 HeapFree(GetProcessHeap(), 0, pc
->lpBitsPrev
);
1186 pc
->lpBitsPrev
= NULL
;
1187 HeapFree(GetProcessHeap(), 0, pc
->lpState
);
1193 /***********************************************************************
1194 * ICSendMessage [MSVFW32.@]
1196 LRESULT VFWAPI
ICSendMessage(HIC hic
, UINT msg
, DWORD_PTR lParam1
, DWORD_PTR lParam2
)
1198 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
1200 if (!whic
) return ICERR_BADHANDLE
;
1201 return MSVIDEO_SendMessage(whic
, msg
, lParam1
, lParam2
);
1204 /***********************************************************************
1205 * ICDrawBegin [MSVFW32.@]
1207 DWORD VFWAPIV
ICDrawBegin(
1209 DWORD dwFlags
, /* [in] flags */
1210 HPALETTE hpal
, /* [in] palette to draw with */
1211 HWND hwnd
, /* [in] window to draw to */
1212 HDC hdc
, /* [in] HDC to draw to */
1213 INT xDst
, /* [in] destination rectangle */
1214 INT yDst
, /* [in] */
1215 INT dxDst
, /* [in] */
1216 INT dyDst
, /* [in] */
1217 LPBITMAPINFOHEADER lpbi
, /* [in] format of frame to draw */
1218 INT xSrc
, /* [in] source rectangle */
1219 INT ySrc
, /* [in] */
1220 INT dxSrc
, /* [in] */
1221 INT dySrc
, /* [in] */
1222 DWORD dwRate
, /* [in] frames/second = (dwRate/dwScale) */
1223 DWORD dwScale
) /* [in] */
1228 TRACE("(%p,%d,%p,%p,%p,%u,%u,%u,%u,%p,%u,%u,%u,%u,%d,%d)\n",
1229 hic
, dwFlags
, hpal
, hwnd
, hdc
, xDst
, yDst
, dxDst
, dyDst
,
1230 lpbi
, xSrc
, ySrc
, dxSrc
, dySrc
, dwRate
, dwScale
);
1232 icdb
.dwFlags
= dwFlags
;
1245 icdb
.dwRate
= dwRate
;
1246 icdb
.dwScale
= dwScale
;
1247 return ICSendMessage(hic
,ICM_DRAW_BEGIN
,(DWORD_PTR
)&icdb
,sizeof(icdb
));
1250 /***********************************************************************
1251 * ICDraw [MSVFW32.@]
1253 DWORD VFWAPIV
ICDraw(HIC hic
, DWORD dwFlags
, LPVOID lpFormat
, LPVOID lpData
, DWORD cbData
, LONG lTime
) {
1256 TRACE("(%p,%d,%p,%p,%d,%d)\n",hic
,dwFlags
,lpFormat
,lpData
,cbData
,lTime
);
1258 icd
.dwFlags
= dwFlags
;
1259 icd
.lpFormat
= lpFormat
;
1260 icd
.lpData
= lpData
;
1261 icd
.cbData
= cbData
;
1264 return ICSendMessage(hic
,ICM_DRAW
,(DWORD_PTR
)&icd
,sizeof(icd
));
1267 /***********************************************************************
1268 * ICClose [MSVFW32.@]
1270 LRESULT WINAPI
ICClose(HIC hic
)
1272 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
1275 TRACE("(%p)\n",hic
);
1277 if (!whic
) return ICERR_BADHANDLE
;
1279 if (whic
->driverproc
)
1281 MSVIDEO_SendMessage(whic
, DRV_CLOSE
, 0, 0);
1282 MSVIDEO_SendMessage(whic
, DRV_DISABLE
, 0, 0);
1283 MSVIDEO_SendMessage(whic
, DRV_FREE
, 0, 0);
1287 CloseDriver(whic
->hdrv
, 0, 0);
1290 /* remove whic from list */
1291 for (p
= &MSVIDEO_FirstHic
; *p
!= NULL
; p
= &((*p
)->next
))
1300 HeapFree(GetProcessHeap(), 0, whic
);
1306 /***********************************************************************
1307 * ICImageCompress [MSVFW32.@]
1309 HANDLE VFWAPI
ICImageCompress(
1310 HIC hic
, UINT uiFlags
,
1311 LPBITMAPINFO lpbiIn
, LPVOID lpBits
,
1312 LPBITMAPINFO lpbiOut
, LONG lQuality
,
1315 FIXME("(%p,%08x,%p,%p,%p,%d,%p)\n",
1316 hic
, uiFlags
, lpbiIn
, lpBits
, lpbiOut
, lQuality
, plSize
);
1321 /***********************************************************************
1322 * ICImageDecompress [MSVFW32.@]
1325 HANDLE VFWAPI
ICImageDecompress(
1326 HIC hic
, UINT uiFlags
, LPBITMAPINFO lpbiIn
,
1327 LPVOID lpBits
, LPBITMAPINFO lpbiOut
)
1329 HGLOBAL hMem
= NULL
;
1331 BOOL bReleaseIC
= FALSE
;
1334 BOOL bSucceeded
= FALSE
;
1335 BOOL bInDecompress
= FALSE
;
1338 TRACE("(%p,%08x,%p,%p,%p)\n",
1339 hic
, uiFlags
, lpbiIn
, lpBits
, lpbiOut
);
1343 hic
= ICDecompressOpen( ICTYPE_VIDEO
, 0, &lpbiIn
->bmiHeader
, (lpbiOut
!= NULL
) ? &lpbiOut
->bmiHeader
: NULL
);
1346 WARN("no handler\n" );
1353 FIXME( "unknown flag %08x\n", uiFlags
);
1356 if ( lpbiIn
== NULL
|| lpBits
== NULL
)
1358 WARN("invalid argument\n");
1362 if ( lpbiOut
!= NULL
)
1364 if ( lpbiOut
->bmiHeader
.biSize
!= sizeof(BITMAPINFOHEADER
) )
1366 cbHdr
= sizeof(BITMAPINFOHEADER
);
1367 if ( lpbiOut
->bmiHeader
.biCompression
== 3 )
1368 cbHdr
+= sizeof(DWORD
)*3;
1370 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 )
1372 if ( lpbiOut
->bmiHeader
.biClrUsed
== 0 )
1373 cbHdr
+= sizeof(RGBQUAD
) * (1<<lpbiOut
->bmiHeader
.biBitCount
);
1375 cbHdr
+= sizeof(RGBQUAD
) * lpbiOut
->bmiHeader
.biClrUsed
;
1380 TRACE( "get format\n" );
1382 cbHdr
= ICDecompressGetFormatSize(hic
,lpbiIn
);
1383 if ( cbHdr
< sizeof(BITMAPINFOHEADER
) )
1385 pHdr
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,cbHdr
+sizeof(RGBQUAD
)*256);
1388 if ( ICDecompressGetFormat( hic
, lpbiIn
, pHdr
) != ICERR_OK
)
1390 lpbiOut
= (BITMAPINFO
*)pHdr
;
1391 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 &&
1392 ICDecompressGetPalette( hic
, lpbiIn
, lpbiOut
) != ICERR_OK
&&
1393 lpbiIn
->bmiHeader
.biBitCount
== lpbiOut
->bmiHeader
.biBitCount
)
1395 if ( lpbiIn
->bmiHeader
.biClrUsed
== 0 )
1396 memcpy( lpbiOut
->bmiColors
, lpbiIn
->bmiColors
, sizeof(RGBQUAD
)*(1<<lpbiOut
->bmiHeader
.biBitCount
) );
1398 memcpy( lpbiOut
->bmiColors
, lpbiIn
->bmiColors
, sizeof(RGBQUAD
)*lpbiIn
->bmiHeader
.biClrUsed
);
1400 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 &&
1401 lpbiOut
->bmiHeader
.biClrUsed
== 0 )
1402 lpbiOut
->bmiHeader
.biClrUsed
= 1<<lpbiOut
->bmiHeader
.biBitCount
;
1404 lpbiOut
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1405 cbHdr
= sizeof(BITMAPINFOHEADER
) + sizeof(RGBQUAD
)*lpbiOut
->bmiHeader
.biClrUsed
;
1408 biSizeImage
= lpbiOut
->bmiHeader
.biSizeImage
;
1409 if ( biSizeImage
== 0 )
1410 biSizeImage
= get_size_image(lpbiOut
->bmiHeader
.biWidth
, lpbiOut
->bmiHeader
.biHeight
, lpbiOut
->bmiHeader
.biBitCount
);
1412 TRACE( "call ICDecompressBegin\n" );
1414 if ( ICDecompressBegin( hic
, lpbiIn
, lpbiOut
) != ICERR_OK
)
1416 bInDecompress
= TRUE
;
1418 TRACE( "cbHdr %d, biSizeImage %d\n", cbHdr
, biSizeImage
);
1420 hMem
= GlobalAlloc( GMEM_MOVEABLE
|GMEM_ZEROINIT
, cbHdr
+ biSizeImage
);
1423 WARN( "out of memory\n" );
1426 pMem
= GlobalLock( hMem
);
1429 memcpy( pMem
, lpbiOut
, cbHdr
);
1431 TRACE( "call ICDecompress\n" );
1432 if ( ICDecompress( hic
, 0, &lpbiIn
->bmiHeader
, lpBits
, &lpbiOut
->bmiHeader
, pMem
+cbHdr
) != ICERR_OK
)
1437 if ( bInDecompress
)
1438 ICDecompressEnd( hic
);
1441 HeapFree(GetProcessHeap(),0,pHdr
);
1443 GlobalUnlock( hMem
);
1444 if ( !bSucceeded
&& hMem
!= NULL
)
1446 GlobalFree(hMem
); hMem
= NULL
;
1452 /***********************************************************************
1453 * ICSeqCompressFrame [MSVFW32.@]
1455 LPVOID VFWAPI
ICSeqCompressFrame(PCOMPVARS pc
, UINT uiFlags
, LPVOID lpBits
, BOOL
*pfKey
, LONG
*plSize
)
1457 ICCOMPRESS
* icComp
= pc
->lpState
;
1459 TRACE("(%p, 0x%08x, %p, %p, %p)\n", pc
, uiFlags
, lpBits
, pfKey
, plSize
);
1461 if (pc
->cbState
!= sizeof(ICCOMPRESS
))
1463 ERR("Invalid cbState %i\n", pc
->cbState
);
1467 if (!pc
->lKeyCount
++)
1468 icComp
->dwFlags
= ICCOMPRESS_KEYFRAME
;
1471 if (pc
->lKey
&& pc
->lKeyCount
== (pc
->lKey
- 1))
1472 /* No key frames if pc->lKey == 0 */
1474 icComp
->dwFlags
= 0;
1477 icComp
->lpInput
= lpBits
;
1478 icComp
->lFrameNum
= pc
->lFrame
++;
1479 icComp
->lpOutput
= pc
->lpBitsOut
;
1480 icComp
->lpPrev
= pc
->lpBitsPrev
;
1481 ret
= ICSendMessage(pc
->hic
, ICM_COMPRESS
, (DWORD_PTR
)icComp
, sizeof(*icComp
));
1483 if (ret
== ICERR_OK
)
1485 LPVOID oldprev
, oldout
;
1487 if (icComp
->dwFlags
& AVIIF_KEYFRAME
)
1491 TRACE("Key frame\n");
1496 *plSize
= icComp
->lpbiOutput
->biSizeImage
;
1498 /* We shift Prev and Out, so we don't have to allocate and release memory */
1499 oldprev
= pc
->lpBitsPrev
;
1500 oldout
= pc
->lpBitsOut
;
1501 pc
->lpBitsPrev
= oldout
;
1502 pc
->lpBitsOut
= oldprev
;
1504 TRACE("returning: %p, compressed frame size %u\n", icComp
->lpOutput
, *plSize
);
1505 return icComp
->lpOutput
;
1510 static void clear_compvars(PCOMPVARS pc
)
1512 HeapFree(GetProcessHeap(), 0, pc
->lpbiIn
);
1513 HeapFree(GetProcessHeap(), 0, pc
->lpBitsPrev
);
1514 HeapFree(GetProcessHeap(), 0, pc
->lpBitsOut
);
1515 HeapFree(GetProcessHeap(), 0, pc
->lpState
);
1516 pc
->lpbiIn
= pc
->lpBitsPrev
= pc
->lpBitsOut
= pc
->lpState
= NULL
;
1517 if (pc
->dwFlags
& 0x80000000)
1519 HeapFree(GetProcessHeap(), 0, pc
->lpbiOut
);
1521 pc
->dwFlags
&= ~0x80000000;
1525 /***********************************************************************
1526 * ICSeqCompressFrameEnd [MSVFW32.@]
1528 void VFWAPI
ICSeqCompressFrameEnd(PCOMPVARS pc
)
1530 TRACE("(%p)\n", pc
);
1531 ICSendMessage(pc
->hic
, ICM_COMPRESS_END
, 0, 0);
1535 /***********************************************************************
1536 * ICSeqCompressFrameStart [MSVFW32.@]
1538 BOOL VFWAPI
ICSeqCompressFrameStart(PCOMPVARS pc
, LPBITMAPINFO lpbiIn
)
1540 /* I'm ignoring bmiColors as I don't know what to do with it,
1541 * it doesn't appear to be used though
1545 pc
->lpbiIn
= HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFO
));
1549 *pc
->lpbiIn
= *lpbiIn
;
1551 pc
->lpState
= HeapAlloc(GetProcessHeap(), 0, sizeof(ICCOMPRESS
)
1552 + sizeof(*icComp
->lpckid
) + sizeof(*icComp
->lpdwFlags
));
1556 pc
->cbState
= sizeof(ICCOMPRESS
);
1560 /* Ask compressor for needed header size */
1561 int size
= ICSendMessage(pc
->hic
, ICM_COMPRESS_GET_FORMAT
,
1562 (DWORD_PTR
)pc
->lpbiIn
, 0);
1566 pc
->lpbiOut
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1569 /* Flag to show that we allocated lpbiOut for proper cleanup */
1570 pc
->dwFlags
|= 0x80000000;
1572 ret
= ICSendMessage(pc
->hic
, ICM_COMPRESS_GET_FORMAT
,
1573 (DWORD_PTR
)pc
->lpbiIn
, (DWORD_PTR
)pc
->lpbiOut
);
1574 if (ret
!= ICERR_OK
)
1576 ERR("Could not get output format from compressor\n");
1579 if (!pc
->lpbiOut
->bmiHeader
.biSizeImage
)
1581 /* If we can't know the output frame size for sure at least allocate
1582 * the same size of the input frame and also at least 8Kb to be sure
1583 * that poor compressors will have enough memory to work if the input
1584 * frame is too small.
1586 pc
->lpbiOut
->bmiHeader
.biSizeImage
= max(8192, pc
->lpbiIn
->bmiHeader
.biSizeImage
);
1587 ERR("Bad codec! Invalid output frame size, guessing from input\n");
1591 TRACE("Input: %ux%u, fcc %s, bpp %u, size %u\n",
1592 pc
->lpbiIn
->bmiHeader
.biWidth
, pc
->lpbiIn
->bmiHeader
.biHeight
,
1593 wine_dbgstr_fcc(pc
->lpbiIn
->bmiHeader
.biCompression
),
1594 pc
->lpbiIn
->bmiHeader
.biBitCount
,
1595 pc
->lpbiIn
->bmiHeader
.biSizeImage
);
1596 TRACE("Output: %ux%u, fcc %s, bpp %u, size %u\n",
1597 pc
->lpbiOut
->bmiHeader
.biWidth
, pc
->lpbiOut
->bmiHeader
.biHeight
,
1598 wine_dbgstr_fcc(pc
->lpbiOut
->bmiHeader
.biCompression
),
1599 pc
->lpbiOut
->bmiHeader
.biBitCount
,
1600 pc
->lpbiOut
->bmiHeader
.biSizeImage
);
1602 /* Buffer for compressed frame data */
1603 pc
->lpBitsOut
= HeapAlloc(GetProcessHeap(), 0, pc
->lpbiOut
->bmiHeader
.biSizeImage
);
1607 /* Buffer for previous compressed frame data */
1608 pc
->lpBitsPrev
= HeapAlloc(GetProcessHeap(), 0, pc
->lpbiOut
->bmiHeader
.biSizeImage
);
1609 if (!pc
->lpBitsPrev
)
1619 "\tkey/data/quality: %i/%i/%i\n",
1620 pc
->cbSize
, pc
->dwFlags
, pc
->hic
, wine_dbgstr_fcc(pc
->fccType
),
1621 wine_dbgstr_fcc(pc
->fccHandler
), pc
->lpbiIn
, pc
->lpbiOut
, pc
->lKey
,
1622 pc
->lDataRate
, pc
->lQ
);
1624 ret
= ICSendMessage(pc
->hic
, ICM_COMPRESS_BEGIN
, (DWORD_PTR
)pc
->lpbiIn
, (DWORD_PTR
)pc
->lpbiOut
);
1625 if (ret
== ICERR_OK
)
1627 icComp
= pc
->lpState
;
1628 /* Initialise some variables */
1629 pc
->lFrame
= 0; pc
->lKeyCount
= 0;
1631 icComp
->lpbiOutput
= &pc
->lpbiOut
->bmiHeader
;
1632 icComp
->lpbiInput
= &pc
->lpbiIn
->bmiHeader
;
1633 icComp
->lpckid
= (DWORD
*)(icComp
+ 1);
1634 *icComp
->lpckid
= 0;
1635 icComp
->lpdwFlags
= (DWORD
*)((char *)(icComp
+ 1) + sizeof(*icComp
->lpckid
));
1636 *icComp
->lpdwFlags
= 0;
1637 icComp
->dwFrameSize
= 0;
1638 icComp
->dwQuality
= pc
->lQ
;
1639 icComp
->lpbiPrev
= &pc
->lpbiIn
->bmiHeader
;
1647 /***********************************************************************
1648 * GetFileNamePreview [MSVFW32.@]
1650 static BOOL
GetFileNamePreview(LPVOID lpofn
,BOOL bSave
,BOOL bUnicode
)
1652 CHAR szFunctionName
[20];
1653 BOOL (*fnGetFileName
)(LPVOID
);
1657 FIXME("(%p,%d,%d), semi-stub!\n",lpofn
,bSave
,bUnicode
);
1659 lstrcpyA(szFunctionName
, (bSave
? "GetSaveFileName" : "GetOpenFileName"));
1660 lstrcatA(szFunctionName
, (bUnicode
? "W" : "A"));
1662 hComdlg32
= LoadLibraryA("COMDLG32.DLL");
1663 if (hComdlg32
== NULL
)
1666 fnGetFileName
= (LPVOID
)GetProcAddress(hComdlg32
, szFunctionName
);
1667 if (fnGetFileName
== NULL
)
1669 FreeLibrary(hComdlg32
);
1673 /* FIXME: need to add OFN_ENABLEHOOK and our own handler */
1674 ret
= fnGetFileName(lpofn
);
1676 FreeLibrary(hComdlg32
);
1680 /***********************************************************************
1681 * GetOpenFileNamePreviewA [MSVFW32.@]
1683 BOOL WINAPI
GetOpenFileNamePreviewA(LPOPENFILENAMEA lpofn
)
1685 FIXME("(%p), semi-stub!\n", lpofn
);
1687 return GetFileNamePreview(lpofn
, FALSE
, FALSE
);
1690 /***********************************************************************
1691 * GetOpenFileNamePreviewW [MSVFW32.@]
1693 BOOL WINAPI
GetOpenFileNamePreviewW(LPOPENFILENAMEW lpofn
)
1695 FIXME("(%p), semi-stub!\n", lpofn
);
1697 return GetFileNamePreview(lpofn
, FALSE
, TRUE
);
1700 /***********************************************************************
1701 * GetSaveFileNamePreviewA [MSVFW32.@]
1703 BOOL WINAPI
GetSaveFileNamePreviewA(LPOPENFILENAMEA lpofn
)
1705 FIXME("(%p), semi-stub!\n", lpofn
);
1707 return GetFileNamePreview(lpofn
, TRUE
, FALSE
);
1710 /***********************************************************************
1711 * GetSaveFileNamePreviewW [MSVFW32.@]
1713 BOOL WINAPI
GetSaveFileNamePreviewW(LPOPENFILENAMEW lpofn
)
1715 FIXME("(%p), semi-stub!\n", lpofn
);
1717 return GetFileNamePreview(lpofn
, TRUE
, TRUE
);