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.
42 #include "msvideo_private.h"
43 #include "wine/debug.h"
44 #include "wine/heap.h"
45 #include "wine/list.h"
47 /* Drivers32 settings */
48 #define HKLM_DRIVERS32 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32"
50 WINE_DEFAULT_DEBUG_CHANNEL(msvideo
);
52 /* This one is a macro in order to work for both ASCII and Unicode */
53 #define fourcc_to_string(str, fcc) do { \
54 (str)[0] = LOBYTE(LOWORD(fcc)); \
55 (str)[1] = HIBYTE(LOWORD(fcc)); \
56 (str)[2] = LOBYTE(HIWORD(fcc)); \
57 (str)[3] = HIBYTE(HIWORD(fcc)); \
60 static inline const char *wine_dbgstr_fcc( DWORD fcc
)
63 fourcc_to_string(fcc_str
, fcc
);
65 /* Last byte may be ' ' in some cases like "DIB " */
66 if (isalnum(fcc_str
[0]) && isalnum(fcc_str
[1]) && isalnum(fcc_str
[2])
67 && (isalnum(fcc_str
[3]) || isspace(fcc_str
[3])))
68 return wine_dbg_sprintf("%s", fcc_str
);
69 return wine_dbg_sprintf("0x%08lx", fcc
);
72 static const char *wine_dbgstr_icerr( int ret
)
75 if (ret
<= ICERR_CUSTOM
)
76 return wine_dbg_sprintf("ICERR_CUSTOM (%d)", ret
);
77 #define XX(x) case (x): str = #x; break
83 XX(ICERR_GOTOKEYFRAME
);
84 XX(ICERR_STOPDRAWING
);
85 XX(ICERR_UNSUPPORTED
);
96 XX(ICERR_BADBITDEPTH
);
97 XX(ICERR_BADIMAGESIZE
);
98 default: str
= wine_dbg_sprintf("UNKNOWN (%d)", ret
);
104 static WINE_HIC
* MSVIDEO_FirstHic
/* = NULL */;
114 static struct list reg_driver_list
= LIST_INIT(reg_driver_list
);
116 HMODULE MSVFW32_hModule
;
118 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
120 TRACE("%p,%lx,%p\n", hinst
, reason
, reserved
);
124 case DLL_PROCESS_ATTACH
:
125 DisableThreadLibraryCalls(hinst
);
126 MSVFW32_hModule
= hinst
;
132 /******************************************************************
133 * MSVIDEO_SendMessage
137 static LRESULT
MSVIDEO_SendMessage(WINE_HIC
* whic
, UINT msg
, DWORD_PTR lParam1
, DWORD_PTR lParam2
)
141 #define XX(x) case x: TRACE("(%p,"#x",0x%08Ix,0x%08Ix)\n",whic,lParam1,lParam2); break
156 XX(ICM_GETDEFAULTQUALITY
);
163 XX(ICM_COMPRESS_FRAMES_INFO
);
164 XX(ICM_COMPRESS_GET_FORMAT
);
165 XX(ICM_COMPRESS_GET_SIZE
);
166 XX(ICM_COMPRESS_QUERY
);
167 XX(ICM_COMPRESS_BEGIN
);
169 XX(ICM_COMPRESS_END
);
170 XX(ICM_DECOMPRESS_GET_FORMAT
);
171 XX(ICM_DECOMPRESS_QUERY
);
172 XX(ICM_DECOMPRESS_BEGIN
);
174 XX(ICM_DECOMPRESS_END
);
175 XX(ICM_DECOMPRESS_SET_PALETTE
);
176 XX(ICM_DECOMPRESS_GET_PALETTE
);
179 XX(ICM_DRAW_GET_PALETTE
);
183 XX(ICM_DRAW_GETTIME
);
186 XX(ICM_DRAW_SETTIME
);
187 XX(ICM_DRAW_REALIZE
);
189 XX(ICM_DRAW_RENDERBUFFER
);
190 XX(ICM_DRAW_START_PLAY
);
191 XX(ICM_DRAW_STOP_PLAY
);
192 XX(ICM_DRAW_SUGGESTFORMAT
);
193 XX(ICM_DRAW_CHANGEPALETTE
);
194 XX(ICM_GETBUFFERSWANTED
);
195 XX(ICM_GETDEFAULTKEYFRAMERATE
);
196 XX(ICM_DECOMPRESSEX_BEGIN
);
197 XX(ICM_DECOMPRESSEX_QUERY
);
198 XX(ICM_DECOMPRESSEX
);
199 XX(ICM_DECOMPRESSEX_END
);
200 XX(ICM_SET_STATUS_PROC
);
202 FIXME("(%p,0x%08x,0x%08Ix,0x%08Ix) unknown message\n",whic
,msg
,lParam1
,lParam2
);
207 if (whic
->driverproc
) {
208 /* dwDriverId parameter is the value returned by the DRV_OPEN */
209 ret
= whic
->driverproc(whic
->driverId
, whic
->hdrv
, msg
, lParam1
, lParam2
);
211 ret
= SendDriverMessage(whic
->hdrv
, msg
, lParam1
, lParam2
);
214 TRACE(" -> %s\n", wine_dbgstr_icerr(ret
));
218 static int compare_fourcc(DWORD fcc1
, DWORD fcc2
)
222 fourcc_to_string(fcc_str1
, fcc1
);
223 fourcc_to_string(fcc_str2
, fcc2
);
224 return _strnicmp(fcc_str1
, fcc_str2
, 4);
227 static DWORD
get_size_image(LONG width
, LONG height
, WORD depth
)
229 DWORD ret
= width
* depth
;
230 ret
= (ret
+ 7) / 8; /* divide by byte size, rounding up */
231 ret
= (ret
+ 3) & ~3; /* align to 4 bytes */
236 /******************************************************************
241 static WINE_HIC
* MSVIDEO_GetHicPtr(HIC hic
)
245 for (whic
= MSVIDEO_FirstHic
; whic
&& whic
->hic
!= hic
; whic
= whic
->next
);
249 /***********************************************************************
250 * VideoForWindowsVersion [MSVFW32.2]
251 * VideoForWindowsVersion [MSVIDEO.2]
252 * Returns the version in major.minor form.
253 * In Windows95 this returns 0x040003b6 (4.950)
255 DWORD WINAPI
VideoForWindowsVersion(void)
257 return 0x040003B6; /* 4.950 */
260 /***********************************************************************
262 * Get information about an installable compressor. Return TRUE if there
266 * fccType [I] type of compressor (e.g. 'vidc')
267 * fccHandler [I] real fcc for handler or <n>th compressor
268 * lpicinfo [O] information about compressor
270 BOOL VFWAPI
ICInfo(DWORD type
, DWORD handler
, ICINFO
*info
)
272 char name_buf
[10], buf
[2048];
273 DWORD ret_type
, ret_handler
;
274 struct reg_driver
*driver
;
279 TRACE("type %s, handler %s, info %p.\n",
280 wine_dbgstr_fcc(type
), wine_dbgstr_fcc(handler
), info
);
282 memset(info
, 0, sizeof(*info
));
283 info
->dwSize
= sizeof(*info
);
284 info
->dwVersionICM
= ICVERSION
;
286 if (!RegOpenKeyExA(HKEY_LOCAL_MACHINE
, HKLM_DRIVERS32
, 0, KEY_QUERY_VALUE
, &key
))
291 DWORD name_len
= ARRAY_SIZE(name_buf
), driver_len
= ARRAY_SIZE(info
->szDriver
);
293 res
= RegEnumValueA(key
, i
++, name_buf
, &name_len
, 0, 0, (BYTE
*)buf
, &driver_len
);
294 if (res
== ERROR_NO_MORE_ITEMS
) break;
296 if (name_len
!= 9 || name_buf
[4] != '.') continue;
297 ret_type
= mmioStringToFOURCCA(name_buf
, 0);
298 ret_handler
= mmioStringToFOURCCA(name_buf
+ 5, 0);
299 if (type
&& compare_fourcc(type
, ret_type
)) continue;
300 if (compare_fourcc(handler
, ret_handler
) && handler
!= count
++) continue;
302 info
->fccType
= ret_type
;
303 info
->fccHandler
= ret_handler
;
304 MultiByteToWideChar(CP_ACP
, 0, buf
, -1, info
->szDriver
, ARRAY_SIZE(info
->szDriver
));
305 TRACE("Returning codec %s, driver %s.\n", debugstr_a(name_buf
), debugstr_a(buf
));
311 if (GetPrivateProfileSectionA("drivers32", buf
, sizeof(buf
), "system.ini"))
314 for (s
= buf
; *s
; s
+= strlen(s
) + 1)
316 if (s
[4] != '.' || s
[9] != '=') continue;
317 ret_type
= mmioStringToFOURCCA(s
, 0);
318 ret_handler
= mmioStringToFOURCCA(s
+ 5, 0);
319 if (type
&& compare_fourcc(type
, ret_type
)) continue;
320 if (compare_fourcc(handler
, ret_handler
) && handler
!= count
++) continue;
322 info
->fccType
= ret_type
;
323 info
->fccHandler
= ret_handler
;
324 MultiByteToWideChar(CP_ACP
, 0, s
+ 10, -1, info
->szDriver
, ARRAY_SIZE(info
->szDriver
));
325 TRACE("Returning codec %s, driver %s.\n", debugstr_an(s
, 9), debugstr_a(s
+ 10));
330 LIST_FOR_EACH_ENTRY(driver
, ®_driver_list
, struct reg_driver
, entry
)
332 if (type
&& compare_fourcc(type
, driver
->fccType
)) continue;
333 if (compare_fourcc(handler
, driver
->fccHandler
) && handler
!= count
++) continue;
334 if (driver
->proc(0, NULL
, ICM_GETINFO
, (DWORD_PTR
)info
, sizeof(*info
)) == sizeof(*info
))
338 info
->fccType
= type
;
339 info
->fccHandler
= handler
;
340 WARN("No driver found for codec %s.%s.\n", wine_dbgstr_fcc(type
), wine_dbgstr_fcc(handler
));
344 static DWORD IC_HandleRef
= 1;
346 /***********************************************************************
347 * ICInstall [MSVFW32.@]
349 BOOL VFWAPI
ICInstall(DWORD type
, DWORD handler
, LPARAM lparam
, char *desc
, UINT flags
)
351 struct reg_driver
*driver
;
353 TRACE("type %s, handler %s, lparam %#Ix, desc %s, flags %#x.\n",
354 wine_dbgstr_fcc(type
), wine_dbgstr_fcc(handler
), lparam
, debugstr_a(desc
), flags
);
356 LIST_FOR_EACH_ENTRY(driver
, ®_driver_list
, struct reg_driver
, entry
)
358 if (!compare_fourcc(type
, driver
->fccType
)
359 && !compare_fourcc(handler
, driver
->fccHandler
))
367 case ICINSTALL_FUNCTION
:
368 if (!(driver
= heap_alloc_zero(sizeof(*driver
))))
370 driver
->fccType
= type
;
371 driver
->fccHandler
= handler
;
372 driver
->proc
= (DRIVERPROC
)lparam
;
373 list_add_tail(®_driver_list
, &driver
->entry
);
375 case ICINSTALL_DRIVER
:
377 const char *driver
= (const char *)lparam
;
382 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, HKLM_DRIVERS32
, 0, KEY_SET_VALUE
, &key
))
384 fourcc_to_string(value
, type
);
386 fourcc_to_string(value
+ 5, handler
);
388 res
= RegSetValueExA(key
, value
, 0, REG_SZ
, (const BYTE
*)driver
, strlen(driver
) + 1);
393 FIXME("Unhandled flags %#x.\n", flags
);
398 /***********************************************************************
399 * ICRemove [MSVFW32.@]
401 BOOL VFWAPI
ICRemove(DWORD type
, DWORD handler
, UINT flags
)
403 struct reg_driver
*driver
;
408 TRACE("type %s, handler %s, flags %#x.\n",
409 wine_dbgstr_fcc(type
), wine_dbgstr_fcc(handler
), flags
);
411 LIST_FOR_EACH_ENTRY(driver
, ®_driver_list
, struct reg_driver
, entry
)
413 if (!compare_fourcc(type
, driver
->fccType
)
414 && !compare_fourcc(handler
, driver
->fccHandler
))
416 list_remove(&driver
->entry
);
422 if (!RegOpenKeyExA(HKEY_LOCAL_MACHINE
, HKLM_DRIVERS32
, 0, KEY_SET_VALUE
, &key
))
424 fourcc_to_string(value
, type
);
426 fourcc_to_string(value
+ 5, handler
);
428 res
= RegDeleteValueA(key
, value
);
437 /***********************************************************************
439 * Opens an installable compressor. Return special handle.
441 HIC VFWAPI
ICOpen(DWORD fccType
, DWORD fccHandler
, UINT wMode
)
446 static const WCHAR drv32W
[] = {'d','r','i','v','e','r','s','3','2','\0'};
447 struct reg_driver
*driver
;
450 TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), wMode
);
452 if (!fccHandler
) /* No specific handler, return the first valid for wMode */
457 info
.dwSize
= sizeof(info
);
458 while(ICInfo(fccType
, loop
++, &info
))
460 /* Ensure fccHandler is not 0x0 because we will recurse on ICOpen */
463 local
= ICOpen(fccType
, info
.fccHandler
, wMode
);
466 TRACE("Returning %s as default handler for %s\n",
467 wine_dbgstr_fcc(info
.fccHandler
), wine_dbgstr_fcc(fccType
));
473 LIST_FOR_EACH_ENTRY(driver
, ®_driver_list
, struct reg_driver
, entry
)
475 if (!compare_fourcc(fccType
, driver
->fccType
)
476 && !compare_fourcc(fccHandler
, driver
->fccHandler
))
478 return ICOpenFunction(driver
->fccType
, driver
->fccHandler
, wMode
, driver
->proc
);
482 /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the
483 * same layout as ICOPEN
485 icopen
.dwSize
= sizeof(ICOPEN
);
486 icopen
.fccType
= fccType
;
487 icopen
.fccHandler
= fccHandler
;
488 icopen
.dwVersion
= 0x00001000; /* FIXME */
489 icopen
.dwFlags
= wMode
;
491 icopen
.pV1Reserved
= NULL
;
492 icopen
.pV2Reserved
= NULL
;
493 icopen
.dnDevNode
= 0; /* FIXME */
497 /* normalize to lower case as in 'vidc' */
498 ((char*)&fccType
)[0] = tolower(((char*)&fccType
)[0]);
499 ((char*)&fccType
)[1] = tolower(((char*)&fccType
)[1]);
500 ((char*)&fccType
)[2] = tolower(((char*)&fccType
)[2]);
501 ((char*)&fccType
)[3] = tolower(((char*)&fccType
)[3]);
502 icopen
.fccType
= fccType
;
503 /* Seek the driver in the registry */
504 fourcc_to_string(codecname
, fccType
);
506 fourcc_to_string(codecname
+ 5, fccHandler
);
509 hdrv
= OpenDriver(codecname
, drv32W
, (LPARAM
)&icopen
);
514 if (!(whic
= heap_alloc(sizeof(*whic
))))
516 CloseDriver(hdrv
, 0, 0);
520 whic
->driverproc
= NULL
;
521 whic
->type
= fccType
;
522 whic
->handler
= fccHandler
;
523 while (MSVIDEO_GetHicPtr((HIC
)(ULONG_PTR
)IC_HandleRef
) != NULL
) IC_HandleRef
++;
524 whic
->hic
= (HIC
)(ULONG_PTR
)IC_HandleRef
++;
525 whic
->next
= MSVIDEO_FirstHic
;
526 MSVIDEO_FirstHic
= whic
;
528 TRACE("=> %p\n", whic
->hic
);
532 /***********************************************************************
533 * ICOpenFunction [MSVFW32.@]
535 HIC VFWAPI
ICOpenFunction(DWORD fccType
, DWORD fccHandler
, UINT wMode
, DRIVERPROC lpfnHandler
)
540 TRACE("(%s,%s,%d,%p)\n",
541 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), wMode
, lpfnHandler
);
543 icopen
.dwSize
= sizeof(ICOPEN
);
544 icopen
.fccType
= fccType
;
545 icopen
.fccHandler
= fccHandler
;
546 icopen
.dwVersion
= ICVERSION
;
547 icopen
.dwFlags
= wMode
;
549 icopen
.pV1Reserved
= NULL
;
550 icopen
.pV2Reserved
= NULL
;
551 icopen
.dnDevNode
= 0; /* FIXME */
553 if (!(whic
= heap_alloc(sizeof(*whic
))))
556 whic
->driverproc
= lpfnHandler
;
557 while (MSVIDEO_GetHicPtr((HIC
)(ULONG_PTR
)IC_HandleRef
) != NULL
) IC_HandleRef
++;
558 whic
->hic
= (HIC
)(ULONG_PTR
)IC_HandleRef
++;
559 whic
->next
= MSVIDEO_FirstHic
;
560 MSVIDEO_FirstHic
= whic
;
562 /* Now try opening/loading the driver. Taken from DRIVER_AddToList */
563 /* What if the function is used more than once? */
565 if (MSVIDEO_SendMessage(whic
, DRV_LOAD
, 0L, 0L) != DRV_SUCCESS
)
567 WARN("DRV_LOAD failed for hic %p\n", whic
->hic
);
568 MSVIDEO_FirstHic
= whic
->next
;
572 /* return value is not checked */
573 MSVIDEO_SendMessage(whic
, DRV_ENABLE
, 0L, 0L);
575 whic
->driverId
= (DWORD
)MSVIDEO_SendMessage(whic
, DRV_OPEN
, 0, (DWORD_PTR
)&icopen
);
576 /* FIXME: What should we put here? */
579 if (whic
->driverId
== 0)
581 WARN("DRV_OPEN failed for hic %p\n", whic
->hic
);
582 MSVIDEO_FirstHic
= whic
->next
;
587 TRACE("=> %p\n", whic
->hic
);
591 /***********************************************************************
592 * ICGetInfo [MSVFW32.@]
594 LRESULT VFWAPI
ICGetInfo(HIC hic
, ICINFO
*picinfo
, DWORD cb
)
597 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
599 TRACE("(%p,%p,%ld)\n", hic
, picinfo
, cb
);
601 if (!whic
) return ICERR_BADHANDLE
;
602 if (!picinfo
) return MMSYSERR_INVALPARAM
;
604 /* (WS) The field szDriver should be initialized because the driver
605 * is not obliged and often will not do it. Some applications, like
606 * VirtualDub, rely on this field and will occasionally crash if it
607 * goes uninitialized.
609 if (cb
>= sizeof(ICINFO
)) picinfo
->szDriver
[0] = '\0';
611 ret
= ICSendMessage(hic
, ICM_GETINFO
, (DWORD_PTR
)picinfo
, cb
);
613 /* (WS) When szDriver was not supplied by the driver itself, apparently
614 * Windows will set its value equal to the driver file name. This can
615 * be obtained from the registry as we do here.
617 if (cb
>= sizeof(ICINFO
) && picinfo
->szDriver
[0] == 0)
621 memset(&ii
, 0, sizeof(ii
));
622 ii
.dwSize
= sizeof(ii
);
623 ICInfo(picinfo
->fccType
, picinfo
->fccHandler
, &ii
);
624 lstrcpyW(picinfo
->szDriver
, ii
.szDriver
);
630 /***********************************************************************
631 * ICLocate [MSVFW32.@]
633 HIC VFWAPI
ICLocate(DWORD type
, DWORD handler
, BITMAPINFOHEADER
*in
,
634 BITMAPINFOHEADER
*out
, WORD mode
)
636 ICINFO info
= {sizeof(info
)};
641 TRACE("type %s, handler %s, in %p, out %p, mode %u.\n",
642 wine_dbgstr_fcc(type
), wine_dbgstr_fcc(handler
), in
, out
, mode
);
646 case ICMODE_FASTCOMPRESS
:
647 case ICMODE_COMPRESS
:
648 msg
= ICM_COMPRESS_QUERY
;
650 case ICMODE_FASTDECOMPRESS
:
651 case ICMODE_DECOMPRESS
:
652 msg
= ICM_DECOMPRESS_QUERY
;
655 msg
= ICM_DRAW_QUERY
;
658 FIXME("Unhandled mode %#x.\n", mode
);
662 if ((hic
= ICOpen(type
, handler
, mode
)))
664 if (!ICSendMessage(hic
, msg
, (DWORD_PTR
)in
, (DWORD_PTR
)out
))
666 TRACE("Found codec %s.%s.\n", wine_dbgstr_fcc(type
),
667 wine_dbgstr_fcc(handler
));
673 for (i
= 0; ICInfo(type
, i
, &info
); ++i
)
675 if ((hic
= ICOpen(info
.fccType
, info
.fccHandler
, mode
)))
677 if (!ICSendMessage(hic
, msg
, (DWORD_PTR
)in
, (DWORD_PTR
)out
))
679 TRACE("Found codec %s.%s.\n", wine_dbgstr_fcc(info
.fccType
),
680 wine_dbgstr_fcc(info
.fccHandler
));
687 if (type
== streamtypeVIDEO
)
688 return ICLocate(ICTYPE_VIDEO
, handler
, in
, out
, mode
);
690 WARN("Could not find a driver for codec %s.%s.\n",
691 wine_dbgstr_fcc(type
), wine_dbgstr_fcc(handler
));
696 /***********************************************************************
697 * ICGetDisplayFormat [MSVFW32.@]
699 HIC VFWAPI
ICGetDisplayFormat(HIC hic
, BITMAPINFOHEADER
*in
, BITMAPINFOHEADER
*out
,
700 int depth
, int width
, int height
)
704 TRACE("(%p, %p, %p, %d, %d, %d)\n", hic
, in
, out
, depth
, width
, height
);
708 tmphic
= ICLocate(ICTYPE_VIDEO
, 0, in
, NULL
, ICMODE_DECOMPRESS
);
713 if (ICDecompressQuery(tmphic
, in
, NULL
))
716 if (width
<= 0 || height
<= 0)
719 height
= in
->biHeight
;
726 out
->biSize
= sizeof(*out
);
727 out
->biWidth
= width
;
728 out
->biHeight
= height
;
729 out
->biCompression
= BI_RGB
;
730 out
->biSizeImage
= get_size_image(width
, height
, depth
);
732 /* first try the given depth */
733 out
->biBitCount
= depth
;
734 out
->biSizeImage
= get_size_image(width
, height
, out
->biBitCount
);
735 if (!ICDecompressQuery(tmphic
, in
, out
))
738 ICDecompressGetPalette(tmphic
, in
, out
);
742 /* then try 16, both with BI_RGB and BI_BITFIELDS */
745 out
->biBitCount
= 16;
746 out
->biSizeImage
= get_size_image(width
, height
, out
->biBitCount
);
747 if (!ICDecompressQuery(tmphic
, in
, out
))
750 out
->biCompression
= BI_BITFIELDS
;
751 if (!ICDecompressQuery(tmphic
, in
, out
))
753 out
->biCompression
= BI_RGB
;
759 out
->biBitCount
= 24;
760 out
->biSizeImage
= get_size_image(width
, height
, out
->biBitCount
);
761 if (!ICDecompressQuery(tmphic
, in
, out
))
768 out
->biBitCount
= 32;
769 out
->biSizeImage
= get_size_image(width
, height
, out
->biBitCount
);
770 if (!ICDecompressQuery(tmphic
, in
, out
))
774 /* as a last resort, try 32 bpp with the original width and height */
775 out
->biWidth
= in
->biWidth
;
776 out
->biHeight
= in
->biHeight
;
777 out
->biBitCount
= 32;
778 out
->biSizeImage
= get_size_image(out
->biWidth
, out
->biHeight
, out
->biBitCount
);
779 if (!ICDecompressQuery(tmphic
, in
, out
))
782 /* finally, ask the compressor for its default output format */
783 if (!ICSendMessage(tmphic
, ICM_DECOMPRESS_GET_FORMAT
, (DWORD_PTR
)in
, (DWORD_PTR
)out
))
793 /***********************************************************************
794 * ICCompress [MSVFW32.@]
798 HIC hic
,DWORD dwFlags
,LPBITMAPINFOHEADER lpbiOutput
,LPVOID lpData
,
799 LPBITMAPINFOHEADER lpbiInput
,LPVOID lpBits
,LPDWORD lpckid
,
800 LPDWORD lpdwFlags
,LONG lFrameNum
,DWORD dwFrameSize
,DWORD dwQuality
,
801 LPBITMAPINFOHEADER lpbiPrev
,LPVOID lpPrev
)
805 TRACE("(%p,%ld,%p,%p,%p,%p,...)\n",hic
,dwFlags
,lpbiOutput
,lpData
,lpbiInput
,lpBits
);
807 iccmp
.dwFlags
= dwFlags
;
809 iccmp
.lpbiOutput
= lpbiOutput
;
810 iccmp
.lpOutput
= lpData
;
811 iccmp
.lpbiInput
= lpbiInput
;
812 iccmp
.lpInput
= lpBits
;
814 iccmp
.lpckid
= lpckid
;
815 iccmp
.lpdwFlags
= lpdwFlags
;
816 iccmp
.lFrameNum
= lFrameNum
;
817 iccmp
.dwFrameSize
= dwFrameSize
;
818 iccmp
.dwQuality
= dwQuality
;
819 iccmp
.lpbiPrev
= lpbiPrev
;
820 iccmp
.lpPrev
= lpPrev
;
821 return ICSendMessage(hic
,ICM_COMPRESS
,(DWORD_PTR
)&iccmp
,sizeof(iccmp
));
824 /***********************************************************************
825 * ICDecompress [MSVFW32.@]
827 DWORD VFWAPIV
ICDecompress(HIC hic
,DWORD dwFlags
,LPBITMAPINFOHEADER lpbiFormat
,
828 LPVOID lpData
,LPBITMAPINFOHEADER lpbi
,LPVOID lpBits
)
833 TRACE("(%p,%ld,%p,%p,%p,%p)\n",hic
,dwFlags
,lpbiFormat
,lpData
,lpbi
,lpBits
);
835 icd
.dwFlags
= dwFlags
;
836 icd
.lpbiInput
= lpbiFormat
;
837 icd
.lpInput
= lpData
;
839 icd
.lpbiOutput
= lpbi
;
840 icd
.lpOutput
= lpBits
;
842 ret
= ICSendMessage(hic
,ICM_DECOMPRESS
,(DWORD_PTR
)&icd
,sizeof(ICDECOMPRESS
));
848 struct choose_compressor
861 static BOOL
enum_compressors(HWND list
, COMPVARS
*pcv
, BOOL enum_all
)
868 while (ICInfo(pcv
->fccType
, id
, &icinfo
))
870 struct codec_info
*ic
;
876 hic
= ICOpen(icinfo
.fccType
, icinfo
.fccHandler
, ICMODE_COMPRESS
);
880 /* for unknown reason fccHandler reported by the driver
881 * doesn't always work, use the one returned by ICInfo instead.
883 DWORD fccHandler
= icinfo
.fccHandler
;
885 if (!enum_all
&& pcv
->lpbiIn
)
887 if (ICCompressQuery(hic
, pcv
->lpbiIn
, NULL
) != ICERR_OK
)
889 TRACE("fccHandler %s doesn't support input DIB format %ld\n",
890 wine_dbgstr_fcc(icinfo
.fccHandler
), pcv
->lpbiIn
->bmiHeader
.biCompression
);
896 ICGetInfo(hic
, &icinfo
, sizeof(icinfo
));
897 icinfo
.fccHandler
= fccHandler
;
899 idx
= SendMessageW(list
, CB_ADDSTRING
, 0, (LPARAM
)icinfo
.szDescription
);
901 ic
= heap_alloc(sizeof(*ic
));
904 SendMessageW(list
, CB_SETITEMDATA
, idx
, (LPARAM
)ic
);
912 static INT_PTR CALLBACK
icm_choose_compressor_dlgproc(HWND hdlg
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
918 struct codec_info
*ic
;
920 struct choose_compressor
*choose_comp
= (struct choose_compressor
*)lparam
;
922 SetWindowLongPtrW(hdlg
, DWLP_USER
, lparam
);
925 choose_comp
->flags
&= ~(ICMF_CHOOSE_DATARATE
| ICMF_CHOOSE_KEYFRAME
);
927 if (choose_comp
->title
)
928 SetWindowTextA(hdlg
, choose_comp
->title
);
930 if (!(choose_comp
->flags
& ICMF_CHOOSE_DATARATE
))
932 ShowWindow(GetDlgItem(hdlg
, IDC_DATARATE_CHECKBOX
), SW_HIDE
);
933 ShowWindow(GetDlgItem(hdlg
, IDC_DATARATE
), SW_HIDE
);
934 ShowWindow(GetDlgItem(hdlg
, IDC_DATARATE_KB
), SW_HIDE
);
937 if (!(choose_comp
->flags
& ICMF_CHOOSE_KEYFRAME
))
939 ShowWindow(GetDlgItem(hdlg
, IDC_KEYFRAME_CHECKBOX
), SW_HIDE
);
940 ShowWindow(GetDlgItem(hdlg
, IDC_KEYFRAME
), SW_HIDE
);
941 ShowWindow(GetDlgItem(hdlg
, IDC_KEYFRAME_FRAMES
), SW_HIDE
);
945 EnableWindow(GetDlgItem(hdlg
, IDC_QUALITY_SCROLL
), FALSE
);
946 EnableWindow(GetDlgItem(hdlg
, IDC_QUALITY_TXT
), FALSE
);
948 /*if (!(choose_comp->flags & ICMF_CHOOSE_PREVIEW))
949 ShowWindow(GetDlgItem(hdlg, IDC_PREVIEW), SW_HIDE);*/
951 LoadStringW(MSVFW32_hModule
, IDS_FULLFRAMES
, buf
, 128);
952 SendDlgItemMessageW(hdlg
, IDC_COMP_LIST
, CB_ADDSTRING
, 0, (LPARAM
)buf
);
954 ic
= heap_alloc(sizeof(*ic
));
955 ic
->icinfo
.fccType
= streamtypeVIDEO
;
956 ic
->icinfo
.fccHandler
= comptypeDIB
;
958 SendDlgItemMessageW(hdlg
, IDC_COMP_LIST
, CB_SETITEMDATA
, 0, (LPARAM
)ic
);
960 enum_compressors(GetDlgItem(hdlg
, IDC_COMP_LIST
), &choose_comp
->cv
, choose_comp
->flags
& ICMF_CHOOSE_ALLCOMPRESSORS
);
962 SendDlgItemMessageW(hdlg
, IDC_COMP_LIST
, CB_SETCURSEL
, 0, 0);
963 SetFocus(GetDlgItem(hdlg
, IDC_COMP_LIST
));
965 SetWindowLongPtrW(hdlg
, DWLP_USER
, (ULONG_PTR
)choose_comp
);
970 switch (LOWORD(wparam
))
975 struct codec_info
*ic
;
976 BOOL can_configure
= FALSE
, can_about
= FALSE
;
977 struct choose_compressor
*choose_comp
;
979 if (HIWORD(wparam
) != CBN_SELCHANGE
&& HIWORD(wparam
) != CBN_SETFOCUS
)
982 choose_comp
= (struct choose_compressor
*)GetWindowLongPtrW(hdlg
, DWLP_USER
);
984 cur_sel
= SendMessageW((HWND
)lparam
, CB_GETCURSEL
, 0, 0);
986 ic
= (struct codec_info
*)SendMessageW((HWND
)lparam
, CB_GETITEMDATA
, cur_sel
, 0);
989 if (ICQueryConfigure(ic
->hic
) == DRVCNF_OK
)
990 can_configure
= TRUE
;
991 if (ICQueryAbout(ic
->hic
) == DRVCNF_OK
)
994 EnableWindow(GetDlgItem(hdlg
, IDC_CONFIGURE
), can_configure
);
995 EnableWindow(GetDlgItem(hdlg
, IDC_ABOUT
), can_about
);
997 if (choose_comp
->flags
& ICMF_CHOOSE_DATARATE
)
1001 if (choose_comp
->flags
& ICMF_CHOOSE_KEYFRAME
)
1012 HWND list
= GetDlgItem(hdlg
, IDC_COMP_LIST
);
1014 struct codec_info
*ic
;
1016 if (HIWORD(wparam
) != BN_CLICKED
)
1019 cur_sel
= SendMessageW(list
, CB_GETCURSEL
, 0, 0);
1021 ic
= (struct codec_info
*)SendMessageW(list
, CB_GETITEMDATA
, cur_sel
, 0);
1024 if (LOWORD(wparam
) == IDC_CONFIGURE
)
1025 ICConfigure(ic
->hic
, hdlg
);
1027 ICAbout(ic
->hic
, hdlg
);
1035 HWND list
= GetDlgItem(hdlg
, IDC_COMP_LIST
);
1037 struct codec_info
*ic
;
1039 if (HIWORD(wparam
) != BN_CLICKED
)
1042 cur_sel
= SendMessageW(list
, CB_GETCURSEL
, 0, 0);
1043 ic
= (struct codec_info
*)SendMessageW(list
, CB_GETITEMDATA
, cur_sel
, 0);
1046 struct choose_compressor
*choose_comp
= (struct choose_compressor
*)GetWindowLongPtrW(hdlg
, DWLP_USER
);
1048 choose_comp
->cv
.hic
= ic
->hic
;
1049 choose_comp
->cv
.fccType
= ic
->icinfo
.fccType
;
1050 choose_comp
->cv
.fccHandler
= ic
->icinfo
.fccHandler
;
1051 /* FIXME: fill everything else */
1053 /* prevent closing the codec handle below */
1060 HWND list
= GetDlgItem(hdlg
, IDC_COMP_LIST
);
1063 if (HIWORD(wparam
) != BN_CLICKED
)
1068 struct codec_info
*ic
;
1070 ic
= (struct codec_info
*)SendMessageW(list
, CB_GETITEMDATA
, idx
++, 0);
1072 if (!ic
|| (LONG_PTR
)ic
== CB_ERR
) break;
1074 if (ic
->hic
) ICClose(ic
->hic
);
1078 EndDialog(hdlg
, LOWORD(wparam
) == IDOK
);
1094 /***********************************************************************
1095 * ICCompressorChoose [MSVFW32.@]
1097 BOOL VFWAPI
ICCompressorChoose(HWND hwnd
, UINT uiFlags
, LPVOID pvIn
,
1098 LPVOID lpData
, PCOMPVARS pc
, LPSTR lpszTitle
)
1100 struct choose_compressor choose_comp
;
1103 TRACE("(%p,%08x,%p,%p,%p,%s)\n", hwnd
, uiFlags
, pvIn
, lpData
, pc
, lpszTitle
);
1105 if (!pc
|| pc
->cbSize
!= sizeof(COMPVARS
))
1108 if (!(pc
->dwFlags
& ICMF_COMPVARS_VALID
))
1111 pc
->fccType
= pc
->fccHandler
= 0;
1115 pc
->lpBitsOut
= pc
->lpBitsPrev
= pc
->lpState
= NULL
;
1116 pc
->lQ
= ICQUALITY_DEFAULT
;
1118 pc
->lDataRate
= 300; /* kB */
1122 if (pc
->fccType
== 0)
1123 pc
->fccType
= ICTYPE_VIDEO
;
1125 choose_comp
.cv
= *pc
;
1126 choose_comp
.flags
= uiFlags
;
1127 choose_comp
.title
= lpszTitle
;
1129 ret
= DialogBoxParamW(MSVFW32_hModule
, MAKEINTRESOURCEW(ICM_CHOOSE_COMPRESSOR
), hwnd
,
1130 icm_choose_compressor_dlgproc
, (LPARAM
)&choose_comp
);
1134 *pc
= choose_comp
.cv
;
1135 pc
->dwFlags
|= ICMF_COMPVARS_VALID
;
1142 /***********************************************************************
1143 * ICCompressorFree [MSVFW32.@]
1145 void VFWAPI
ICCompressorFree(PCOMPVARS pc
)
1147 TRACE("(%p)\n", pc
);
1149 if (pc
&& pc
->cbSize
== sizeof(COMPVARS
))
1156 heap_free(pc
->lpbiIn
);
1158 heap_free(pc
->lpBitsOut
);
1159 pc
->lpBitsOut
= NULL
;
1160 heap_free(pc
->lpBitsPrev
);
1161 pc
->lpBitsPrev
= NULL
;
1162 heap_free(pc
->lpState
);
1168 /***********************************************************************
1169 * ICSendMessage [MSVFW32.@]
1171 LRESULT VFWAPI
ICSendMessage(HIC hic
, UINT msg
, DWORD_PTR lParam1
, DWORD_PTR lParam2
)
1173 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
1175 if (!whic
) return ICERR_BADHANDLE
;
1176 return MSVIDEO_SendMessage(whic
, msg
, lParam1
, lParam2
);
1179 /***********************************************************************
1180 * ICDrawBegin [MSVFW32.@]
1182 DWORD VFWAPIV
ICDrawBegin(
1184 DWORD dwFlags
, /* [in] flags */
1185 HPALETTE hpal
, /* [in] palette to draw with */
1186 HWND hwnd
, /* [in] window to draw to */
1187 HDC hdc
, /* [in] HDC to draw to */
1188 INT xDst
, /* [in] destination rectangle */
1189 INT yDst
, /* [in] */
1190 INT dxDst
, /* [in] */
1191 INT dyDst
, /* [in] */
1192 LPBITMAPINFOHEADER lpbi
, /* [in] format of frame to draw */
1193 INT xSrc
, /* [in] source rectangle */
1194 INT ySrc
, /* [in] */
1195 INT dxSrc
, /* [in] */
1196 INT dySrc
, /* [in] */
1197 DWORD dwRate
, /* [in] frames/second = (dwRate/dwScale) */
1198 DWORD dwScale
) /* [in] */
1203 TRACE("(%p,%ld,%p,%p,%p,%u,%u,%u,%u,%p,%u,%u,%u,%u,%ld,%ld)\n",
1204 hic
, dwFlags
, hpal
, hwnd
, hdc
, xDst
, yDst
, dxDst
, dyDst
,
1205 lpbi
, xSrc
, ySrc
, dxSrc
, dySrc
, dwRate
, dwScale
);
1207 icdb
.dwFlags
= dwFlags
;
1220 icdb
.dwRate
= dwRate
;
1221 icdb
.dwScale
= dwScale
;
1222 return ICSendMessage(hic
,ICM_DRAW_BEGIN
,(DWORD_PTR
)&icdb
,sizeof(icdb
));
1225 /***********************************************************************
1226 * ICDraw [MSVFW32.@]
1228 DWORD VFWAPIV
ICDraw(HIC hic
, DWORD dwFlags
, LPVOID lpFormat
, LPVOID lpData
, DWORD cbData
, LONG lTime
) {
1231 TRACE("(%p,%ld,%p,%p,%ld,%ld)\n",hic
,dwFlags
,lpFormat
,lpData
,cbData
,lTime
);
1233 icd
.dwFlags
= dwFlags
;
1234 icd
.lpFormat
= lpFormat
;
1235 icd
.lpData
= lpData
;
1236 icd
.cbData
= cbData
;
1239 return ICSendMessage(hic
,ICM_DRAW
,(DWORD_PTR
)&icd
,sizeof(icd
));
1242 /***********************************************************************
1243 * ICClose [MSVFW32.@]
1245 LRESULT WINAPI
ICClose(HIC hic
)
1247 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
1250 TRACE("(%p)\n",hic
);
1252 if (!whic
) return ICERR_BADHANDLE
;
1254 if (whic
->driverproc
)
1256 MSVIDEO_SendMessage(whic
, DRV_CLOSE
, 0, 0);
1257 MSVIDEO_SendMessage(whic
, DRV_DISABLE
, 0, 0);
1258 MSVIDEO_SendMessage(whic
, DRV_FREE
, 0, 0);
1262 CloseDriver(whic
->hdrv
, 0, 0);
1265 /* remove whic from list */
1266 for (p
= &MSVIDEO_FirstHic
; *p
!= NULL
; p
= &((*p
)->next
))
1281 /***********************************************************************
1282 * ICImageCompress [MSVFW32.@]
1284 HANDLE VFWAPI
ICImageCompress(
1285 HIC hic
, UINT uiFlags
,
1286 LPBITMAPINFO lpbiIn
, LPVOID lpBits
,
1287 LPBITMAPINFO lpbiOut
, LONG lQuality
,
1290 FIXME("(%p,%08x,%p,%p,%p,%ld,%p)\n",
1291 hic
, uiFlags
, lpbiIn
, lpBits
, lpbiOut
, lQuality
, plSize
);
1296 /***********************************************************************
1297 * ICImageDecompress [MSVFW32.@]
1300 HANDLE VFWAPI
ICImageDecompress(
1301 HIC hic
, UINT uiFlags
, LPBITMAPINFO lpbiIn
,
1302 LPVOID lpBits
, LPBITMAPINFO lpbiOut
)
1304 HGLOBAL hMem
= NULL
;
1306 BOOL bReleaseIC
= FALSE
;
1309 BOOL bSucceeded
= FALSE
;
1310 BOOL bInDecompress
= FALSE
;
1313 TRACE("(%p,%08x,%p,%p,%p)\n",
1314 hic
, uiFlags
, lpbiIn
, lpBits
, lpbiOut
);
1318 hic
= ICDecompressOpen( ICTYPE_VIDEO
, 0, &lpbiIn
->bmiHeader
, (lpbiOut
!= NULL
) ? &lpbiOut
->bmiHeader
: NULL
);
1321 WARN("no handler\n" );
1328 FIXME( "unknown flag %08x\n", uiFlags
);
1331 if ( lpbiIn
== NULL
|| lpBits
== NULL
)
1333 WARN("invalid argument\n");
1337 if ( lpbiOut
!= NULL
)
1339 if ( lpbiOut
->bmiHeader
.biSize
!= sizeof(BITMAPINFOHEADER
) )
1341 cbHdr
= sizeof(BITMAPINFOHEADER
);
1342 if ( lpbiOut
->bmiHeader
.biCompression
== 3 )
1343 cbHdr
+= sizeof(DWORD
)*3;
1345 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 )
1347 if ( lpbiOut
->bmiHeader
.biClrUsed
== 0 )
1348 cbHdr
+= sizeof(RGBQUAD
) * (1<<lpbiOut
->bmiHeader
.biBitCount
);
1350 cbHdr
+= sizeof(RGBQUAD
) * lpbiOut
->bmiHeader
.biClrUsed
;
1355 TRACE( "get format\n" );
1357 cbHdr
= ICDecompressGetFormatSize(hic
,lpbiIn
);
1358 if ( cbHdr
< sizeof(BITMAPINFOHEADER
) )
1360 if (!(pHdr
= heap_alloc_zero(cbHdr
+ sizeof(RGBQUAD
) * 256)))
1362 if ( ICDecompressGetFormat( hic
, lpbiIn
, pHdr
) != ICERR_OK
)
1364 lpbiOut
= (BITMAPINFO
*)pHdr
;
1365 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 &&
1366 ICDecompressGetPalette( hic
, lpbiIn
, lpbiOut
) != ICERR_OK
&&
1367 lpbiIn
->bmiHeader
.biBitCount
== lpbiOut
->bmiHeader
.biBitCount
)
1369 if ( lpbiIn
->bmiHeader
.biClrUsed
== 0 )
1370 memcpy( lpbiOut
->bmiColors
, lpbiIn
->bmiColors
, sizeof(RGBQUAD
)*(1<<lpbiOut
->bmiHeader
.biBitCount
) );
1372 memcpy( lpbiOut
->bmiColors
, lpbiIn
->bmiColors
, sizeof(RGBQUAD
)*lpbiIn
->bmiHeader
.biClrUsed
);
1374 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 &&
1375 lpbiOut
->bmiHeader
.biClrUsed
== 0 )
1376 lpbiOut
->bmiHeader
.biClrUsed
= 1<<lpbiOut
->bmiHeader
.biBitCount
;
1378 lpbiOut
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1379 cbHdr
= sizeof(BITMAPINFOHEADER
) + sizeof(RGBQUAD
)*lpbiOut
->bmiHeader
.biClrUsed
;
1382 biSizeImage
= lpbiOut
->bmiHeader
.biSizeImage
;
1383 if ( biSizeImage
== 0 )
1384 biSizeImage
= get_size_image(lpbiOut
->bmiHeader
.biWidth
, lpbiOut
->bmiHeader
.biHeight
, lpbiOut
->bmiHeader
.biBitCount
);
1386 TRACE( "call ICDecompressBegin\n" );
1388 if ( ICDecompressBegin( hic
, lpbiIn
, lpbiOut
) != ICERR_OK
)
1390 bInDecompress
= TRUE
;
1392 TRACE( "cbHdr %ld, biSizeImage %ld\n", cbHdr
, biSizeImage
);
1394 hMem
= GlobalAlloc( GMEM_MOVEABLE
|GMEM_ZEROINIT
, cbHdr
+ biSizeImage
);
1397 WARN( "out of memory\n" );
1400 pMem
= GlobalLock( hMem
);
1403 memcpy( pMem
, lpbiOut
, cbHdr
);
1405 TRACE( "call ICDecompress\n" );
1406 if ( ICDecompress( hic
, 0, &lpbiIn
->bmiHeader
, lpBits
, &lpbiOut
->bmiHeader
, pMem
+cbHdr
) != ICERR_OK
)
1411 if ( bInDecompress
)
1412 ICDecompressEnd( hic
);
1417 GlobalUnlock( hMem
);
1418 if ( !bSucceeded
&& hMem
!= NULL
)
1420 GlobalFree(hMem
); hMem
= NULL
;
1426 /***********************************************************************
1427 * ICSeqCompressFrame [MSVFW32.@]
1429 LPVOID VFWAPI
ICSeqCompressFrame(PCOMPVARS pc
, UINT uiFlags
, LPVOID lpBits
, BOOL
*pfKey
, LONG
*plSize
)
1431 ICCOMPRESS
* icComp
= pc
->lpState
;
1433 TRACE("(%p, 0x%08x, %p, %p, %p)\n", pc
, uiFlags
, lpBits
, pfKey
, plSize
);
1435 if (pc
->cbState
!= sizeof(ICCOMPRESS
))
1437 ERR("Invalid cbState %li\n", pc
->cbState
);
1441 if (!pc
->lKeyCount
++)
1442 icComp
->dwFlags
= ICCOMPRESS_KEYFRAME
;
1445 if (pc
->lKey
&& pc
->lKeyCount
== (pc
->lKey
- 1))
1446 /* No key frames if pc->lKey == 0 */
1448 icComp
->dwFlags
= 0;
1451 icComp
->lpInput
= lpBits
;
1452 icComp
->lFrameNum
= pc
->lFrame
++;
1453 icComp
->lpOutput
= pc
->lpBitsOut
;
1454 icComp
->lpPrev
= pc
->lpBitsPrev
;
1455 ret
= ICSendMessage(pc
->hic
, ICM_COMPRESS
, (DWORD_PTR
)icComp
, sizeof(*icComp
));
1457 if (ret
== ICERR_OK
)
1459 LPVOID oldprev
, oldout
;
1461 if (icComp
->dwFlags
& AVIIF_KEYFRAME
)
1465 TRACE("Key frame\n");
1470 *plSize
= icComp
->lpbiOutput
->biSizeImage
;
1472 /* We shift Prev and Out, so we don't have to allocate and release memory */
1473 oldprev
= pc
->lpBitsPrev
;
1474 oldout
= pc
->lpBitsOut
;
1475 pc
->lpBitsPrev
= oldout
;
1476 pc
->lpBitsOut
= oldprev
;
1478 TRACE("returning: %p, compressed frame size %lu\n", icComp
->lpOutput
, *plSize
);
1479 return icComp
->lpOutput
;
1484 static void clear_compvars(PCOMPVARS pc
)
1486 heap_free(pc
->lpbiIn
);
1487 heap_free(pc
->lpBitsPrev
);
1488 heap_free(pc
->lpBitsOut
);
1489 heap_free(pc
->lpState
);
1490 pc
->lpbiIn
= pc
->lpBitsPrev
= pc
->lpBitsOut
= pc
->lpState
= NULL
;
1491 if (pc
->dwFlags
& 0x80000000)
1493 heap_free(pc
->lpbiOut
);
1495 pc
->dwFlags
&= ~0x80000000;
1499 /***********************************************************************
1500 * ICSeqCompressFrameEnd [MSVFW32.@]
1502 void VFWAPI
ICSeqCompressFrameEnd(PCOMPVARS pc
)
1504 TRACE("(%p)\n", pc
);
1505 ICSendMessage(pc
->hic
, ICM_COMPRESS_END
, 0, 0);
1509 static BITMAPINFO
*copy_bitmapinfo(const BITMAPINFO
*src
)
1515 if (src
->bmiHeader
.biClrUsed
)
1516 num_colors
= min(src
->bmiHeader
.biClrUsed
, 256);
1518 num_colors
= src
->bmiHeader
.biBitCount
> 8 ? 0 : 1 << src
->bmiHeader
.biBitCount
;
1520 size
= FIELD_OFFSET(BITMAPINFO
, bmiColors
[num_colors
]);
1521 if (src
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1522 size
+= 3 * sizeof(DWORD
);
1524 if (!(dst
= heap_alloc(size
)))
1527 memcpy(dst
, src
, size
);
1531 /***********************************************************************
1532 * ICSeqCompressFrameStart [MSVFW32.@]
1534 BOOL VFWAPI
ICSeqCompressFrameStart(PCOMPVARS pc
, LPBITMAPINFO lpbiIn
)
1536 /* I'm ignoring bmiColors as I don't know what to do with it,
1537 * it doesn't appear to be used though
1542 if (!(pc
->lpbiIn
= copy_bitmapinfo(lpbiIn
)))
1545 if (!(pc
->lpState
= heap_alloc(sizeof(ICCOMPRESS
) + sizeof(*icComp
->lpckid
) + sizeof(*icComp
->lpdwFlags
))))
1548 pc
->cbState
= sizeof(ICCOMPRESS
);
1552 /* Ask compressor for needed header size */
1553 int size
= ICSendMessage(pc
->hic
, ICM_COMPRESS_GET_FORMAT
,
1554 (DWORD_PTR
)pc
->lpbiIn
, 0);
1558 if (!(pc
->lpbiOut
= heap_alloc_zero(size
)))
1560 /* Flag to show that we allocated lpbiOut for proper cleanup */
1561 pc
->dwFlags
|= 0x80000000;
1563 ret
= ICSendMessage(pc
->hic
, ICM_COMPRESS_GET_FORMAT
,
1564 (DWORD_PTR
)pc
->lpbiIn
, (DWORD_PTR
)pc
->lpbiOut
);
1565 if (ret
!= ICERR_OK
)
1567 ERR("Could not get output format from compressor\n");
1570 if (!pc
->lpbiOut
->bmiHeader
.biSizeImage
)
1572 /* If we can't know the output frame size for sure at least allocate
1573 * the same size of the input frame and also at least 8Kb to be sure
1574 * that poor compressors will have enough memory to work if the input
1575 * frame is too small.
1577 pc
->lpbiOut
->bmiHeader
.biSizeImage
= max(8192, pc
->lpbiIn
->bmiHeader
.biSizeImage
);
1578 ERR("Bad codec! Invalid output frame size, guessing from input\n");
1582 TRACE("Input: %lux%lu, fcc %s, bpp %u, size %lu\n",
1583 pc
->lpbiIn
->bmiHeader
.biWidth
, pc
->lpbiIn
->bmiHeader
.biHeight
,
1584 wine_dbgstr_fcc(pc
->lpbiIn
->bmiHeader
.biCompression
),
1585 pc
->lpbiIn
->bmiHeader
.biBitCount
,
1586 pc
->lpbiIn
->bmiHeader
.biSizeImage
);
1587 TRACE("Output: %lux%lu, fcc %s, bpp %u, size %lu\n",
1588 pc
->lpbiOut
->bmiHeader
.biWidth
, pc
->lpbiOut
->bmiHeader
.biHeight
,
1589 wine_dbgstr_fcc(pc
->lpbiOut
->bmiHeader
.biCompression
),
1590 pc
->lpbiOut
->bmiHeader
.biBitCount
,
1591 pc
->lpbiOut
->bmiHeader
.biSizeImage
);
1593 /* Buffer for compressed frame data */
1594 if (!(pc
->lpBitsOut
= heap_alloc(pc
->lpbiOut
->bmiHeader
.biSizeImage
)))
1597 /* Buffer for previous compressed frame data */
1598 if (!(pc
->lpBitsPrev
= heap_alloc(pc
->lpbiOut
->bmiHeader
.biSizeImage
)))
1608 "\tkey/data/quality: %li/%li/%li\n",
1609 pc
->cbSize
, pc
->dwFlags
, pc
->hic
, wine_dbgstr_fcc(pc
->fccType
),
1610 wine_dbgstr_fcc(pc
->fccHandler
), pc
->lpbiIn
, pc
->lpbiOut
, pc
->lKey
,
1611 pc
->lDataRate
, pc
->lQ
);
1613 ret
= ICSendMessage(pc
->hic
, ICM_COMPRESS_BEGIN
, (DWORD_PTR
)pc
->lpbiIn
, (DWORD_PTR
)pc
->lpbiOut
);
1614 if (ret
== ICERR_OK
)
1616 icComp
= pc
->lpState
;
1617 /* Initialise some variables */
1618 pc
->lFrame
= 0; pc
->lKeyCount
= 0;
1620 icComp
->lpbiOutput
= &pc
->lpbiOut
->bmiHeader
;
1621 icComp
->lpbiInput
= &pc
->lpbiIn
->bmiHeader
;
1622 icComp
->lpckid
= (DWORD
*)(icComp
+ 1);
1623 *icComp
->lpckid
= 0;
1624 icComp
->lpdwFlags
= (DWORD
*)((char *)(icComp
+ 1) + sizeof(*icComp
->lpckid
));
1625 *icComp
->lpdwFlags
= 0;
1626 icComp
->dwFrameSize
= 0;
1627 icComp
->dwQuality
= pc
->lQ
;
1628 icComp
->lpbiPrev
= &pc
->lpbiIn
->bmiHeader
;
1636 /***********************************************************************
1637 * GetFileNamePreview [MSVFW32.@]
1639 static BOOL
GetFileNamePreview(LPVOID lpofn
,BOOL bSave
,BOOL bUnicode
)
1641 CHAR szFunctionName
[20];
1642 BOOL (*fnGetFileName
)(LPVOID
);
1646 FIXME("(%p,%d,%d), semi-stub!\n",lpofn
,bSave
,bUnicode
);
1648 lstrcpyA(szFunctionName
, (bSave
? "GetSaveFileName" : "GetOpenFileName"));
1649 lstrcatA(szFunctionName
, (bUnicode
? "W" : "A"));
1651 hComdlg32
= LoadLibraryA("COMDLG32.DLL");
1652 if (hComdlg32
== NULL
)
1655 fnGetFileName
= (LPVOID
)GetProcAddress(hComdlg32
, szFunctionName
);
1656 if (fnGetFileName
== NULL
)
1658 FreeLibrary(hComdlg32
);
1662 /* FIXME: need to add OFN_ENABLEHOOK and our own handler */
1663 ret
= fnGetFileName(lpofn
);
1665 FreeLibrary(hComdlg32
);
1669 /***********************************************************************
1670 * GetOpenFileNamePreviewA [MSVFW32.@]
1672 BOOL WINAPI
GetOpenFileNamePreviewA(LPOPENFILENAMEA lpofn
)
1674 FIXME("(%p), semi-stub!\n", lpofn
);
1676 return GetFileNamePreview(lpofn
, FALSE
, FALSE
);
1679 /***********************************************************************
1680 * GetOpenFileNamePreviewW [MSVFW32.@]
1682 BOOL WINAPI
GetOpenFileNamePreviewW(LPOPENFILENAMEW lpofn
)
1684 FIXME("(%p), semi-stub!\n", lpofn
);
1686 return GetFileNamePreview(lpofn
, FALSE
, TRUE
);
1689 /***********************************************************************
1690 * GetSaveFileNamePreviewA [MSVFW32.@]
1692 BOOL WINAPI
GetSaveFileNamePreviewA(LPOPENFILENAMEA lpofn
)
1694 FIXME("(%p), semi-stub!\n", lpofn
);
1696 return GetFileNamePreview(lpofn
, TRUE
, FALSE
);
1699 /***********************************************************************
1700 * GetSaveFileNamePreviewW [MSVFW32.@]
1702 BOOL WINAPI
GetSaveFileNamePreviewW(LPOPENFILENAMEW lpofn
)
1704 FIXME("(%p), semi-stub!\n", lpofn
);
1706 return GetFileNamePreview(lpofn
, TRUE
, TRUE
);