WINE_DEFAULT_DEBUG_CHANNEL(msvideo);
+/* This one is a macro in order to work for both ASCII and Unicode */
+#define fourcc_to_string(str, fcc) do { \
+ (str)[0] = LOBYTE(LOWORD(fcc)); \
+ (str)[1] = HIBYTE(LOWORD(fcc)); \
+ (str)[2] = LOBYTE(HIWORD(fcc)); \
+ (str)[3] = HIBYTE(HIWORD(fcc)); \
+ } while(0)
+
static inline const char *wine_dbgstr_fcc( DWORD fcc )
{
- return wine_dbg_sprintf("%c%c%c%c",
- LOBYTE(LOWORD(fcc)), HIBYTE(LOWORD(fcc)),
- LOBYTE(HIWORD(fcc)), HIBYTE(HIWORD(fcc)));
+ char fcc_str[5];
+ fourcc_to_string(fcc_str, fcc);
+ fcc_str[4] = '\0';
+ /* Last byte may be ' ' in some cases like "DIB " */
+ if (isalnum(fcc_str[0]) && isalnum(fcc_str[1]) && isalnum(fcc_str[2])
+ && (isalnum(fcc_str[3]) || isspace(fcc_str[3])))
+ return wine_dbg_sprintf("%s", fcc_str);
+ return wine_dbg_sprintf("0x%08x", fcc);
+}
+
+static const char *wine_dbgstr_icerr( int ret )
+{
+ const char *str;
+ if (ret <= ICERR_CUSTOM)
+ return wine_dbg_sprintf("ICERR_CUSTOM (%d)", ret);
+#define XX(x) case (x): str = #x; break
+ switch (ret)
+ {
+ XX(ICERR_OK);
+ XX(ICERR_DONTDRAW);
+ XX(ICERR_NEWPALETTE);
+ XX(ICERR_GOTOKEYFRAME);
+ XX(ICERR_STOPDRAWING);
+ XX(ICERR_UNSUPPORTED);
+ XX(ICERR_BADFORMAT);
+ XX(ICERR_MEMORY);
+ XX(ICERR_INTERNAL);
+ XX(ICERR_BADFLAGS);
+ XX(ICERR_BADPARAM);
+ XX(ICERR_BADSIZE);
+ XX(ICERR_BADHANDLE);
+ XX(ICERR_CANTUPDATE);
+ XX(ICERR_ABORT);
+ XX(ICERR_ERROR);
+ XX(ICERR_BADBITDEPTH);
+ XX(ICERR_BADIMAGESIZE);
+ default: str = wine_dbg_sprintf("UNKNOWN (%d)", ret);
+ }
+#undef XX
+ return str;
+}
+
+static inline int get_stride(int width, int depth)
+{
+ return ((depth * width + 31) >> 3) & ~3;
}
static WINE_HIC* MSVIDEO_FirstHic /* = NULL */;
static reg_driver* reg_driver_list = NULL;
-/* This one is a macro such that it works for both ASCII and Unicode */
-#define fourcc_to_string(str, fcc) do { \
- (str)[0] = LOBYTE(LOWORD(fcc)); \
- (str)[1] = HIBYTE(LOWORD(fcc)); \
- (str)[2] = LOBYTE(HIWORD(fcc)); \
- (str)[3] = HIBYTE(HIWORD(fcc)); \
- } while(0)
-
HMODULE MSVFW32_hModule;
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
ret = SendDriverMessage(whic->hdrv, msg, lParam1, lParam2);
}
- TRACE(" -> 0x%08lx\n", ret);
+ TRACE(" -> %s\n", wine_dbgstr_icerr(ret));
return ret;
}
return strncasecmp(fcc_str1, fcc_str2, 4);
}
-typedef BOOL (*enum_handler_t)(const char*, unsigned int, void*);
+typedef BOOL (*enum_handler_t)(const char *name, const char *driver, unsigned int index, void *param);
static BOOL enum_drivers(DWORD fccType, enum_handler_t handler, void* param)
{
- CHAR buf[2048], fccTypeStr[5], *s;
+ char fccTypeStr[4];
+ char name_buf[10];
+ char buf[2048];
+
DWORD i, cnt = 0, lRet;
BOOL result = FALSE;
HKEY hKey;
fourcc_to_string(fccTypeStr, fccType);
- fccTypeStr[4] = '.';
/* first, go through the registry entries */
lRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, HKLM_DRIVERS32, 0, KEY_QUERY_VALUE, &hKey);
if (lRet == ERROR_SUCCESS)
{
- DWORD name, data, type;
i = 0;
for (;;)
- {
- name = 10;
- data = sizeof buf - name;
- lRet = RegEnumValueA(hKey, i++, buf, &name, 0, &type, (LPBYTE)(buf+name), &data);
- if (lRet == ERROR_NO_MORE_ITEMS) break;
- if (lRet != ERROR_SUCCESS) continue;
- if (name != 9 || strncasecmp(buf, fccTypeStr, 5)) continue;
- buf[name] = '=';
- if ((result = handler(buf, cnt++, param))) break;
- }
- RegCloseKey( hKey );
+ {
+ DWORD name_len = 10, driver_len = 128;
+ lRet = RegEnumValueA(hKey, i++, name_buf, &name_len, 0, 0, (BYTE *)buf, &driver_len);
+ if (lRet == ERROR_NO_MORE_ITEMS) break;
+ if (name_len != 9 || name_buf[4] != '.') continue;
+ if (fccType && strncasecmp(name_buf, fccTypeStr, 4)) continue;
+ if ((result = handler(name_buf, buf, cnt++, param))) break;
+ }
+ RegCloseKey( hKey );
}
if (result) return result;
/* if that didn't work, go through the values in system.ini */
if (GetPrivateProfileSectionA("drivers32", buf, sizeof(buf), "system.ini"))
{
- for (s = buf; *s; s += strlen(s) + 1)
- {
- TRACE("got %s\n", s);
- if (strncasecmp(s, fccTypeStr, 5) || s[9] != '=') continue;
- if ((result = handler(s, cnt++, param))) break;
- }
+ char *s;
+ for (s = buf; *s; s += strlen(s) + 1)
+ {
+ if (s[4] != '.' || s[9] != '=') continue;
+ if (fccType && strncasecmp(s, fccTypeStr, 4)) continue;
+ if ((result = handler(s, s + 10, cnt++, param))) break;
+ }
}
return result;
return 0x040003B6; /* 4.950 */
}
-static BOOL ICInfo_enum_handler(const char *drv, unsigned int nr, void *param)
+static BOOL ICInfo_enum_handler(const char *name, const char *driver, unsigned int nr, void *param)
{
ICINFO *lpicinfo = param;
- DWORD fccHandler = mmioStringToFOURCCA(drv + 5, 0);
+ DWORD fccType = mmioStringToFOURCCA(name, 0);
+ DWORD fccHandler = mmioStringToFOURCCA(name + 5, 0);
- /* exact match of fccHandler or nth driver found */
- if ((lpicinfo->fccHandler != nr) && (lpicinfo->fccHandler != fccHandler))
- return FALSE;
+ if (lpicinfo->fccHandler != nr && compare_fourcc(lpicinfo->fccHandler, fccHandler))
+ return FALSE;
+ lpicinfo->fccType = fccType;
lpicinfo->fccHandler = fccHandler;
lpicinfo->dwFlags = 0;
lpicinfo->dwVersion = 0;
lpicinfo->dwVersionICM = ICVERSION;
lpicinfo->szName[0] = 0;
lpicinfo->szDescription[0] = 0;
- MultiByteToWideChar(CP_ACP, 0, drv + 10, -1, lpicinfo->szDriver,
+ MultiByteToWideChar(CP_ACP, 0, driver, -1, lpicinfo->szDriver,
sizeof(lpicinfo->szDriver)/sizeof(WCHAR));
return TRUE;
*/
BOOL VFWAPI ICInfo( DWORD fccType, DWORD fccHandler, ICINFO *lpicinfo)
{
- TRACE("(%s,%s/%08x,%p)\n",
- wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), fccHandler, lpicinfo);
+ TRACE("(%s,%s,%p)\n",
+ wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), lpicinfo);
lpicinfo->fccType = fccType;
lpicinfo->fccHandler = fccHandler;
TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wMode);
+ if (!fccHandler) /* No specific handler, return the first valid for wMode */
+ {
+ HIC local;
+ ICINFO info;
+ DWORD loop = 0;
+ info.dwSize = sizeof(info);
+ while(ICInfo(fccType, loop++, &info))
+ {
+ /* Ensure fccHandler is not 0x0 because we will recurse on ICOpen */
+ if(!info.fccHandler)
+ continue;
+ local = ICOpen(fccType, info.fccHandler, wMode);
+ if (local != 0)
+ {
+ TRACE("Returning %s as default handler for %s\n",
+ wine_dbgstr_fcc(info.fccHandler), wine_dbgstr_fcc(fccType));
+ return local;
+ }
+ }
+ }
+
/* Check if there is a registered driver that matches */
driver = reg_driver_list;
while(driver)
if (!compare_fourcc(fccType, driver->fccType) &&
- !compare_fourcc(fccHandler, driver->fccHandler))
+ !compare_fourcc(fccHandler, driver->fccHandler)) {
+ fccType = driver->fccType;
+ fccHandler = driver->fccHandler;
break;
- else
+ } else
driver = driver->next;
if (driver && driver->proc)
- /* The driver has been registered at runtime with its driverproc */
+ /* The driver has been registered at runtime with its driverproc */
return ICOpenFunction(fccType, fccHandler, wMode, driver->proc);
/* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the
* same layout as ICOPEN
*/
- icopen.dwSize = sizeof(ICOPEN);
- icopen.fccType = fccType;
- icopen.fccHandler = fccHandler;
- icopen.dwVersion = 0x00001000; /* FIXME */
- icopen.dwFlags = wMode;
- icopen.dwError = 0;
- icopen.pV1Reserved = NULL;
- icopen.pV2Reserved = NULL;
- icopen.dnDevNode = 0; /* FIXME */
-
+ icopen.dwSize = sizeof(ICOPEN);
+ icopen.fccType = fccType;
+ icopen.fccHandler = fccHandler;
+ icopen.dwVersion = 0x00001000; /* FIXME */
+ icopen.dwFlags = wMode;
+ icopen.dwError = 0;
+ icopen.pV1Reserved = NULL;
+ icopen.pV2Reserved = NULL;
+ icopen.dnDevNode = 0; /* FIXME */
+
if (!driver) {
- /* The driver is registered in the registry */
- fourcc_to_string(codecname, fccType);
+ /* normalize to lower case as in 'vidc' */
+ ((char*)&fccType)[0] = tolower(((char*)&fccType)[0]);
+ ((char*)&fccType)[1] = tolower(((char*)&fccType)[1]);
+ ((char*)&fccType)[2] = tolower(((char*)&fccType)[2]);
+ ((char*)&fccType)[3] = tolower(((char*)&fccType)[3]);
+ icopen.fccType = fccType;
+ /* Seek the driver in the registry */
+ fourcc_to_string(codecname, fccType);
codecname[4] = '.';
- fourcc_to_string(codecname + 5, fccHandler);
+ fourcc_to_string(codecname + 5, fccHandler);
codecname[9] = '\0';
hdrv = OpenDriver(codecname, drv32W, (LPARAM)&icopen);
- if (!hdrv)
+ if (!hdrv)
return 0;
} else {
/* The driver has been registered at runtime with its name */
TRACE("(%s,%s,%d,%p)\n",
wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wMode, lpfnHandler);
- icopen.dwSize = sizeof(ICOPEN);
- icopen.fccType = fccType;
- icopen.fccHandler = fccHandler;
- icopen.dwVersion = ICVERSION;
- icopen.dwFlags = wMode;
- icopen.dwError = 0;
- icopen.pV1Reserved = NULL;
- icopen.pV2Reserved = NULL;
- icopen.dnDevNode = 0; /* FIXME */
+ icopen.dwSize = sizeof(ICOPEN);
+ icopen.fccType = fccType;
+ icopen.fccHandler = fccHandler;
+ icopen.dwVersion = ICVERSION;
+ icopen.dwFlags = wMode;
+ icopen.dwError = 0;
+ icopen.pV1Reserved = NULL;
+ icopen.pV2Reserved = NULL;
+ icopen.dnDevNode = 0; /* FIXME */
whic = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC));
if (!whic) return 0;
TRACE("(%p,%p,%d)\n", hic, picinfo, cb);
- whic = MSVIDEO_GetHicPtr(hic);
if (!whic) return ICERR_BADHANDLE;
if (!picinfo) return MMSYSERR_INVALPARAM;
lstrcpyW(picinfo->szDriver, ii.szDriver);
}
- TRACE(" -> 0x%08lx\n", ret);
return ret;
}
return 0;
}
-static BOOL ICLocate_enum_handler(const char *drv, unsigned int nr, void *param)
+static BOOL ICLocate_enum_handler(const char *name, const char *driver, unsigned int nr, void *param)
{
driver_info_t *info = param;
- info->fccHandler = mmioStringToFOURCCA(drv + 5, 0);
+ info->fccHandler = mmioStringToFOURCCA(name + 5, 0);
info->hic = try_driver(info);
return info->hic != 0;
}
if (fccType == streamtypeVIDEO)
return ICLocate(ICTYPE_VIDEO, fccHandler, lpbiIn, lpbiOut, wMode);
- WARN("(%s,%s,%p,%p,0x%04x) not found!\n",
- wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), lpbiIn, lpbiOut, wMode);
+ ERR("Required media codec '%s %s' not found!\n",
+ wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler));
return 0;
}
HIC hic,LPBITMAPINFOHEADER lpbiIn,LPBITMAPINFOHEADER lpbiOut,
INT depth,INT dx,INT dy)
{
- HIC tmphic = hic;
+ static const struct
+ {
+ int depth;
+ int compression;
+ }
+ try_depths[] =
+ {
+ { 8, BI_RGB},
+ {16, BI_RGB},
+ {16, BI_BITFIELDS},
+ {24, BI_RGB},
+ {32, BI_RGB},
+ };
- TRACE("(%p,%p,%p,%d,%d,%d)!\n",hic,lpbiIn,lpbiOut,depth,dx,dy);
+ int screen_depth, i;
+ BOOL found = FALSE;
+ HIC tmphic;
+ HDC hdc;
- if (!tmphic) {
- tmphic=ICLocate(ICTYPE_VIDEO,0,lpbiIn,NULL,ICMODE_DECOMPRESS);
- if (!tmphic)
- return tmphic;
- }
- if ((dy == lpbiIn->biHeight) && (dx == lpbiIn->biWidth))
- dy = dx = 0; /* no resize needed */
+ TRACE("(%p,%p,%p,%d,%d,%d)!\n", hic, lpbiIn, lpbiOut, depth, dx, dy);
+
+ tmphic = hic ? hic : ICLocate(ICTYPE_VIDEO, 0, lpbiIn, NULL, ICMODE_DECOMPRESS);
+ if (!tmphic) return tmphic;
+
+ hdc = GetDC(0);
+ screen_depth = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
+ ReleaseDC(0, hdc);
+
+ if (dx <= 0) dx = lpbiIn->biWidth;
+ if (dy <= 0) dy = lpbiIn->biHeight;
+ if (!depth) depth = screen_depth;
/* Can we decompress it ? */
- if (ICDecompressQuery(tmphic,lpbiIn,NULL) != 0)
+ if (ICDecompressQuery(tmphic, lpbiIn, NULL) != ICERR_OK)
goto errout; /* no, sorry */
ICSendMessage(tmphic, ICM_DECOMPRESS_GET_FORMAT, (DWORD_PTR)lpbiIn, (DWORD_PTR)lpbiOut);
- if (lpbiOut->biCompression != 0) {
+ lpbiOut->biSize = sizeof(BITMAPINFOHEADER);
+ lpbiOut->biWidth = dx;
+ lpbiOut->biHeight = dy;
+ lpbiOut->biPlanes = 1;
+
+ for (i = 0; i < sizeof(try_depths) / sizeof(try_depths[0]); i++)
+ {
+ if (!found && try_depths[i].depth != depth)
+ continue;
+
+ found = TRUE;
+ lpbiOut->biBitCount = try_depths[i].depth;
+ lpbiOut->biCompression = try_depths[i].compression;
+ lpbiOut->biSizeImage = dx * get_stride(dy, lpbiOut->biBitCount);
+
+ if (ICDecompressQuery(tmphic, lpbiIn, lpbiOut) == ICERR_OK)
+ {
+ if (try_depths[i].depth == 8)
+ ICDecompressGetPalette(tmphic, lpbiIn, lpbiOut);
+ goto success;
+ }
+ }
+
+ if (!found)
+ {
+ lpbiOut->biBitCount = depth;
+ lpbiOut->biCompression = BI_RGB;
+ lpbiOut->biSizeImage = dx * get_stride(dy, lpbiOut->biBitCount);
+ if (ICDecompressQuery(tmphic, lpbiIn, lpbiOut) == ICERR_OK)
+ goto success;
+
+ lpbiOut->biBitCount = screen_depth;
+ lpbiOut->biCompression = BI_RGB;
+ lpbiOut->biSizeImage = dx * get_stride(dy, lpbiOut->biBitCount);
+ if (ICDecompressQuery(tmphic, lpbiIn, lpbiOut) == ICERR_OK)
+ goto success;
+ }
+
+ if (ICSendMessage(tmphic, ICM_DECOMPRESS_GET_FORMAT, (DWORD_PTR)lpbiIn, (DWORD_PTR)lpbiOut))
+ goto errout;
+
+ if (lpbiOut->biCompression != 0) {
FIXME("Ooch, how come decompressor outputs compressed data (%d)??\n",
lpbiOut->biCompression);
}
lpbiOut->biSize);
lpbiOut->biSize = sizeof(*lpbiOut);
}
- if (!depth) {
- HDC hdc;
-
- hdc = GetDC(0);
- depth = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES);
- ReleaseDC(0,hdc);
- if (depth==15) depth = 16;
- if (depth<8) depth = 8;
- }
- if (lpbiIn->biBitCount == 8)
- depth = 8;
+success:
TRACE("=> %p\n", tmphic);
return tmphic;
+
errout:
if (hic!=tmphic)
ICClose(tmphic);
icd.ckid = 0;
ret = ICSendMessage(hic,ICM_DECOMPRESS,(DWORD_PTR)&icd,sizeof(ICDECOMPRESS));
- TRACE("-> %d\n",ret);
-
return ret;
}
if (pc->lKey && pc->lKeyCount == (pc->lKey - 1))
/* No key frames if pc->lKey == 0 */
pc->lKeyCount = 0;
- icComp->dwFlags = 0;
+ icComp->dwFlags = 0;
}
icComp->lpInput = lpBits;
icComp->lFrameNum = pc->lFrame++;
icComp->lpOutput = pc->lpBitsOut;
icComp->lpPrev = pc->lpBitsPrev;
- ret = ICSendMessage(pc->hic, ICM_COMPRESS, (DWORD_PTR)icComp, sizeof(icComp));
+ ret = ICSendMessage(pc->hic, ICM_COMPRESS, (DWORD_PTR)icComp, sizeof(*icComp));
- if (icComp->dwFlags & AVIIF_KEYFRAME)
+ if (ret == ICERR_OK)
{
- pc->lKeyCount = 1;
- *pfKey = TRUE;
- TRACE("Key frame\n");
+ LPVOID oldprev, oldout;
+
+ if (icComp->dwFlags & AVIIF_KEYFRAME)
+ {
+ pc->lKeyCount = 1;
+ *pfKey = TRUE;
+ TRACE("Key frame\n");
+ }
+ else
+ *pfKey = FALSE;
+
+ *plSize = icComp->lpbiOutput->biSizeImage;
+
+ /* We shift Prev and Out, so we don't have to allocate and release memory */
+ oldprev = pc->lpBitsPrev;
+ oldout = pc->lpBitsOut;
+ pc->lpBitsPrev = oldout;
+ pc->lpBitsOut = oldprev;
+
+ TRACE("returning: %p, compressed frame size %u\n", icComp->lpOutput, *plSize);
+ return icComp->lpOutput;
}
- else
- *pfKey = FALSE;
+ return NULL;
+}
- *plSize = icComp->lpbiOutput->biSizeImage;
- TRACE(" -- 0x%08x\n", ret);
- if (ret == ICERR_OK)
+static void clear_compvars(PCOMPVARS pc)
+{
+ HeapFree(GetProcessHeap(), 0, pc->lpbiIn);
+ HeapFree(GetProcessHeap(), 0, pc->lpBitsPrev);
+ HeapFree(GetProcessHeap(), 0, pc->lpBitsOut);
+ HeapFree(GetProcessHeap(), 0, pc->lpState);
+ pc->lpbiIn = pc->lpBitsPrev = pc->lpBitsOut = pc->lpState = NULL;
+ if (pc->dwFlags & 0x80000000)
{
- LPVOID oldprev, oldout;
-/* We shift Prev and Out, so we don't have to allocate and release memory */
- oldprev = pc->lpBitsPrev;
- oldout = pc->lpBitsOut;
- pc->lpBitsPrev = oldout;
- pc->lpBitsOut = oldprev;
-
- TRACE("returning: %p\n", icComp->lpOutput);
- return icComp->lpOutput;
+ HeapFree(GetProcessHeap(), 0, pc->lpbiOut);
+ pc->lpbiOut = NULL;
+ pc->dwFlags &= ~0x80000000;
}
- return NULL;
}
/***********************************************************************
*/
void VFWAPI ICSeqCompressFrameEnd(PCOMPVARS pc)
{
- DWORD ret;
TRACE("(%p)\n", pc);
- ret = ICSendMessage(pc->hic, ICM_COMPRESS_END, 0, 0);
- TRACE(" -- %x\n", ret);
- HeapFree(GetProcessHeap(), 0, pc->lpbiIn);
- HeapFree(GetProcessHeap(), 0, pc->lpBitsPrev);
- HeapFree(GetProcessHeap(), 0, pc->lpBitsOut);
- HeapFree(GetProcessHeap(), 0, pc->lpState);
- pc->lpbiIn = pc->lpBitsPrev = pc->lpBitsOut = pc->lpState = NULL;
+ ICSendMessage(pc->hic, ICM_COMPRESS_END, 0, 0);
+ clear_compvars(pc);
}
/***********************************************************************
* it doesn't appear to be used though
*/
DWORD ret;
+ ICCOMPRESS* icComp;
pc->lpbiIn = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFO));
if (!pc->lpbiIn)
return FALSE;
*pc->lpbiIn = *lpbiIn;
- pc->lpBitsPrev = HeapAlloc(GetProcessHeap(), 0, pc->lpbiIn->bmiHeader.biSizeImage);
- if (!pc->lpBitsPrev)
- {
- HeapFree(GetProcessHeap(), 0, pc->lpbiIn);
- return FALSE;
- }
- pc->lpState = HeapAlloc(GetProcessHeap(), 0, sizeof(ICCOMPRESS));
+ pc->lpState = HeapAlloc(GetProcessHeap(), 0, sizeof(ICCOMPRESS)
+ + sizeof(*icComp->lpckid) + sizeof(*icComp->lpdwFlags));
if (!pc->lpState)
+ goto error;
+
+ pc->cbState = sizeof(ICCOMPRESS);
+
+ if (!pc->lpbiOut)
{
- HeapFree(GetProcessHeap(), 0, pc->lpbiIn);
- HeapFree(GetProcessHeap(), 0, pc->lpBitsPrev);
- return FALSE;
+ /* Ask compressor for needed header size */
+ int size = ICSendMessage(pc->hic, ICM_COMPRESS_GET_FORMAT,
+ (DWORD_PTR)pc->lpbiIn, 0);
+ if (size <= 0)
+ goto error;
+
+ pc->lpbiOut = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
+ if (!pc->lpbiOut)
+ goto error;
+ /* Flag to show that we allocated lpbiOut for proper cleanup */
+ pc->dwFlags |= 0x80000000;
+
+ ret = ICSendMessage(pc->hic, ICM_COMPRESS_GET_FORMAT,
+ (DWORD_PTR)pc->lpbiIn, (DWORD_PTR)pc->lpbiOut);
+ if (ret != ICERR_OK)
+ {
+ ERR("Could not get output format from compressor\n");
+ goto error;
+ }
+ if (!pc->lpbiOut->bmiHeader.biSizeImage)
+ {
+ /* If we can't know the output frame size for sure at least allocate
+ * the same size of the input frame and also at least 8Kb to be sure
+ * that poor compressors will have enough memory to work if the input
+ * frame is too small.
+ */
+ pc->lpbiOut->bmiHeader.biSizeImage = max(8192, pc->lpbiIn->bmiHeader.biSizeImage);
+ ERR("Bad codec! Invalid output frame size, guessing from input\n");
+ }
}
- pc->cbState = sizeof(ICCOMPRESS);
+ TRACE("Input: %ux%u, fcc %s, bpp %u, size %u\n",
+ pc->lpbiIn->bmiHeader.biWidth, pc->lpbiIn->bmiHeader.biHeight,
+ wine_dbgstr_fcc(pc->lpbiIn->bmiHeader.biCompression),
+ pc->lpbiIn->bmiHeader.biBitCount,
+ pc->lpbiIn->bmiHeader.biSizeImage);
+ TRACE("Output: %ux%u, fcc %s, bpp %u, size %u\n",
+ pc->lpbiOut->bmiHeader.biWidth, pc->lpbiOut->bmiHeader.biHeight,
+ wine_dbgstr_fcc(pc->lpbiOut->bmiHeader.biCompression),
+ pc->lpbiOut->bmiHeader.biBitCount,
+ pc->lpbiOut->bmiHeader.biSizeImage);
+
+ /* Buffer for compressed frame data */
pc->lpBitsOut = HeapAlloc(GetProcessHeap(), 0, pc->lpbiOut->bmiHeader.biSizeImage);
if (!pc->lpBitsOut)
- {
- HeapFree(GetProcessHeap(), 0, pc->lpbiIn);
- HeapFree(GetProcessHeap(), 0, pc->lpBitsPrev);
- HeapFree(GetProcessHeap(), 0, pc->lpState);
- return FALSE;
- }
+ goto error;
+
+ /* Buffer for previous compressed frame data */
+ pc->lpBitsPrev = HeapAlloc(GetProcessHeap(), 0, pc->lpbiOut->bmiHeader.biSizeImage);
+ if (!pc->lpBitsPrev)
+ goto error;
+
TRACE("Compvars:\n"
- "\tpc:\n"
"\tsize: %i\n"
- "\tflags: %i\n"
+ "\tflags: 0x%x\n"
"\thic: %p\n"
- "\ttype: %x\n"
- "\thandler: %x\n"
+ "\ttype: %s\n"
+ "\thandler: %s\n"
"\tin/out: %p/%p\n"
- "key/data/quality: %i/%i/%i\n",
- pc->cbSize, pc->dwFlags, pc->hic, pc->fccType, pc->fccHandler,
- pc->lpbiIn, pc->lpbiOut, pc->lKey, pc->lDataRate, pc->lQ);
+ "\tkey/data/quality: %i/%i/%i\n",
+ pc->cbSize, pc->dwFlags, pc->hic, wine_dbgstr_fcc(pc->fccType),
+ wine_dbgstr_fcc(pc->fccHandler), pc->lpbiIn, pc->lpbiOut, pc->lKey,
+ pc->lDataRate, pc->lQ);
ret = ICSendMessage(pc->hic, ICM_COMPRESS_BEGIN, (DWORD_PTR)pc->lpbiIn, (DWORD_PTR)pc->lpbiOut);
- TRACE(" -- %x\n", ret);
if (ret == ICERR_OK)
{
- ICCOMPRESS* icComp = pc->lpState;
- /* Initialise some variables */
- pc->lFrame = 0; pc->lKeyCount = 0;
-
- icComp->lpbiOutput = &pc->lpbiOut->bmiHeader;
- icComp->lpbiInput = &pc->lpbiIn->bmiHeader;
- icComp->lpckid = NULL;
- icComp->dwFrameSize = 0;
- icComp->dwQuality = pc->lQ;
- icComp->lpbiPrev = &pc->lpbiIn->bmiHeader;
- return TRUE;
+ icComp = pc->lpState;
+ /* Initialise some variables */
+ pc->lFrame = 0; pc->lKeyCount = 0;
+
+ icComp->lpbiOutput = &pc->lpbiOut->bmiHeader;
+ icComp->lpbiInput = &pc->lpbiIn->bmiHeader;
+ icComp->lpckid = (DWORD *)(icComp + 1);
+ *icComp->lpckid = 0;
+ icComp->lpdwFlags = (DWORD *)((char *)(icComp + 1) + sizeof(*icComp->lpckid));
+ *icComp->lpdwFlags = 0;
+ icComp->dwFrameSize = 0;
+ icComp->dwQuality = pc->lQ;
+ icComp->lpbiPrev = &pc->lpbiIn->bmiHeader;
+ return TRUE;
}
- HeapFree(GetProcessHeap(), 0, pc->lpbiIn);
- HeapFree(GetProcessHeap(), 0, pc->lpBitsPrev);
- HeapFree(GetProcessHeap(), 0, pc->lpState);
- HeapFree(GetProcessHeap(), 0, pc->lpBitsOut);
- pc->lpBitsPrev = pc->lpbiIn = pc->lpState = pc->lpBitsOut = NULL;
+error:
+ clear_compvars(pc);
return FALSE;
}
fnGetFileName = (LPVOID)GetProcAddress(hComdlg32, szFunctionName);
if (fnGetFileName == NULL)
+ {
+ FreeLibrary(hComdlg32);
return FALSE;
+ }
/* FIXME: need to add OFN_ENABLEHOOK and our own handler */
ret = fnGetFileName(lpofn);