Esempio n. 1
0
// to set/get/query special features/parameters
static int control(sh_video_t *sh,int cmd,void* arg,...){
    vd_vfw_ctx *priv = sh->context;
    switch(cmd){
    case VDCTRL_QUERY_MAX_PP_LEVEL:
	return 9;
    case VDCTRL_SET_PP_LEVEL:
	vfw_set_postproc(sh,10*(*((int*)arg)));
	return CONTROL_OK;
    // FIXME: make this optional...
    case VDCTRL_QUERY_FORMAT:
      {
	HRESULT ret;
	if(!(sh->codec->outflags[sh->outfmtidx]&CODECS_FLAG_QUERY))
	    return CONTROL_UNKNOWN;	// do not query!
	set_csp(priv->o_bih,*((int*)arg));
#ifdef BUILD_VFWEX
	ret = ICDecompressQueryEx(priv->handle, sh->bih, priv->o_bih);
#else
	ret = ICDecompressQuery(priv->handle, sh->bih, priv->o_bih);
#endif
	if (ret)
	{
	    mp_msg(MSGT_WIN32, MSGL_DBG2, "ICDecompressQuery failed:: Error %d\n", (int)ret);
	    return CONTROL_FALSE;
	}
	return CONTROL_TRUE;
      }
    }
    return CONTROL_UNKNOWN;
}
Esempio n. 2
0
/***********************************************************************
 *		ICGetDisplayFormat			[MSVFW32.@]
 */
HIC VFWAPI ICGetDisplayFormat(
	HIC hic,LPBITMAPINFOHEADER lpbiIn,LPBITMAPINFOHEADER lpbiOut,
	INT depth,INT dx,INT dy)
{
	HIC	tmphic = hic;

	TRACE("(%p,%p,%p,%d,%d,%d)!\n",hic,lpbiIn,lpbiOut,depth,dx,dy);

	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 */

	/* Can we decompress it ? */
	if (ICDecompressQuery(tmphic,lpbiIn,NULL) != 0)
		goto errout; /* no, sorry */

	ICSendMessage(tmphic, ICM_DECOMPRESS_GET_FORMAT, (DWORD_PTR)lpbiIn, (DWORD_PTR)lpbiOut);

	if (lpbiOut->biCompression != 0) {
           FIXME("Ooch, how come decompressor outputs compressed data (%d)??\n",
			 lpbiOut->biCompression);
	}
	if (lpbiOut->biSize < sizeof(*lpbiOut)) {
           FIXME("Ooch, size of output BIH is too small (%d)\n",
			 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;

	TRACE("=> %p\n", tmphic);
	return tmphic;
errout:
	if (hic!=tmphic)
		ICClose(tmphic);

	TRACE("=> 0\n");
	return 0;
}
Esempio n. 3
0
static HRESULT WINAPI AVIDec_SetMediaType(TransformFilter *tf, PIN_DIRECTION dir, const AM_MEDIA_TYPE * pmt)
{
    AVIDecImpl* This = (AVIDecImpl*)tf;
    HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED;

    TRACE("(%p)->(%p)\n", This, pmt);

    if (dir != PINDIR_INPUT)
        return S_OK;

    /* Check root (GUID w/o FOURCC) */
    if ((IsEqualIID(&pmt->majortype, &MEDIATYPE_Video)) &&
        (!memcmp(((const char *)&pmt->subtype)+4, ((const char *)&MEDIATYPE_Video)+4, sizeof(GUID)-4)))
    {
        VIDEOINFOHEADER *format1 = (VIDEOINFOHEADER *)pmt->pbFormat;
        VIDEOINFOHEADER2 *format2 = (VIDEOINFOHEADER2 *)pmt->pbFormat;
        BITMAPINFOHEADER *bmi;

        if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
            bmi = &format1->bmiHeader;
        else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2))
            bmi = &format2->bmiHeader;
        else
            goto failed;
        TRACE("Fourcc: %s\n", debugstr_an((const char *)&pmt->subtype.Data1, 4));

        This->hvid = ICLocate(pmt->majortype.Data1, pmt->subtype.Data1, bmi, NULL, ICMODE_DECOMPRESS);
        if (This->hvid)
        {
            AM_MEDIA_TYPE* outpmt = &This->tf.pmt;
            const CLSID* outsubtype;
            DWORD bih_size;
            DWORD output_depth = bmi->biBitCount;
            DWORD result;
            FreeMediaType(outpmt);

            switch(bmi->biBitCount)
            {
                case 32: outsubtype = &MEDIASUBTYPE_RGB32; break;
                case 24: outsubtype = &MEDIASUBTYPE_RGB24; break;
                case 16: outsubtype = &MEDIASUBTYPE_RGB565; break;
                case 8:  outsubtype = &MEDIASUBTYPE_RGB8; break;
                default:
                    WARN("Non standard input depth %d, forced output depth to 32\n", bmi->biBitCount);
                    outsubtype = &MEDIASUBTYPE_RGB32;
                    output_depth = 32;
                    break;
            }

            /* Copy bitmap header from media type to 1 for input and 1 for output */
            bih_size = bmi->biSize + bmi->biClrUsed * 4;
            This->pBihIn = CoTaskMemAlloc(bih_size);
            if (!This->pBihIn)
            {
                hr = E_OUTOFMEMORY;
                goto failed;
            }
            This->pBihOut = CoTaskMemAlloc(bih_size);
            if (!This->pBihOut)
            {
                hr = E_OUTOFMEMORY;
                goto failed;
            }
            memcpy(This->pBihIn, bmi, bih_size);
            memcpy(This->pBihOut, bmi, bih_size);

            /* Update output format as non compressed bitmap */
            This->pBihOut->biCompression = 0;
            This->pBihOut->biBitCount = output_depth;
            This->pBihOut->biSizeImage = This->pBihOut->biWidth * This->pBihOut->biHeight * This->pBihOut->biBitCount / 8;
            TRACE("Size: %u\n", This->pBihIn->biSize);
            result = ICDecompressQuery(This->hvid, This->pBihIn, This->pBihOut);
            if (result != ICERR_OK)
            {
                ERR("Unable to found a suitable output format (%d)\n", result);
                goto failed;
            }

            /* Update output media type */
            CopyMediaType(outpmt, pmt);
            outpmt->subtype = *outsubtype;

            if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
                memcpy(&(((VIDEOINFOHEADER *)outpmt->pbFormat)->bmiHeader), This->pBihOut, This->pBihOut->biSize);
            else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2))
                memcpy(&(((VIDEOINFOHEADER2 *)outpmt->pbFormat)->bmiHeader), This->pBihOut, This->pBihOut->biSize);
            else
                assert(0);

            TRACE("Connection accepted\n");
            return S_OK;
        }
        TRACE("Unable to find a suitable VFW decompressor\n");
    }

failed:

    TRACE("Connection refused\n");
    return hr;
}
Esempio n. 4
0
// init driver
static int init(sh_video_t *sh){
    HRESULT ret;
//    unsigned int outfmt=sh->codec->outfmt[sh->outfmtidx];
    int i, o_bih_len;
    vd_vfw_ctx *priv;
    const char *dll = codec_idx2str(sh->codec->dll_idx);

    /* Hack for VSSH codec: new dll can't decode old files
     * In my samples old files have no extradata, so use that info
     * to decide what dll should be used (here and in vd_dshow).
     */
    if (!strcmp(dll, "vssh264.dll") && (sh->bih->biSize > 40))
      return 0;

    priv = malloc(sizeof(vd_vfw_ctx));
    if (!priv)
	return 0;
    memset(priv, 0, sizeof(vd_vfw_ctx));
    sh->context = priv;

    mp_msg(MSGT_WIN32,MSGL_V,"======= Win32 (VFW) VIDEO Codec init =======\n");


//    win32_codec_name = dll;
//    sh->hic = ICOpen( 0x63646976, sh->bih->biCompression, ICMODE_FASTDECOMPRESS);
//    priv->handle = ICOpen( 0x63646976, sh->bih->biCompression, ICMODE_DECOMPRESS);
    priv->handle = ICOpen( (long)(dll), sh->bih->biCompression, ICMODE_DECOMPRESS);
    if(!priv->handle){
	mp_msg(MSGT_WIN32,MSGL_ERR,"ICOpen failed! unknown codec / wrong parameters?\n");
	return 0;
    }

//    sh->bih->biBitCount=32;

    o_bih_len = ICDecompressGetFormatSize(priv->handle, sh->bih);

    if(o_bih_len < sizeof(BITMAPINFOHEADER)){
       mp_msg(MSGT_WIN32,MSGL_ERR,"ICDecompressGetFormatSize returned a bogus value: %d\n", o_bih_len);
       return 0;
    }

    priv->o_bih = malloc(o_bih_len);
    memset(priv->o_bih, 0, o_bih_len);

    mp_msg(MSGT_WIN32,MSGL_V,"ICDecompressGetFormatSize ret: %d\n", o_bih_len);

    ret = ICDecompressGetFormat(priv->handle, sh->bih, priv->o_bih);
    if(ret < 0){
	mp_msg(MSGT_WIN32,MSGL_ERR,"ICDecompressGetFormat failed: Error %d\n", (int)ret);
	for (i=0; i < o_bih_len; i++) mp_msg(MSGT_WIN32, MSGL_DBG2, "%02x ", priv->o_bih[i]);
	return 0;
    }
    mp_msg(MSGT_WIN32,MSGL_V,"ICDecompressGetFormat OK\n");

#if 0
    // workaround for pegasus MJPEG:
    if(!sh_video->o_bih.biWidth) sh_video->o_bih.biWidth=sh_video->bih->biWidth;
    if(!sh_video->o_bih.biHeight) sh_video->o_bih.biHeight=sh_video->bih->biHeight;
    if(!sh_video->o_bih.biPlanes) sh_video->o_bih.biPlanes=sh_video->bih->biPlanes;
#endif

    // ok let libvo and vd core to handshake and decide the optimal csp:
    if(!mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_YUY2)) return 0;

    if (!(sh->codec->outflags[sh->outfmtidx]&CODECS_FLAG_FLIP)) {
	priv->o_bih->biHeight=-sh->bih->biHeight; // flip image!
    }

    // ok, let's set the choosen colorspace:
    set_csp(priv->o_bih,sh->codec->outfmt[sh->outfmtidx]);

    // fake it to RGB for broken DLLs (divx3)
    if(sh->codec->outflags[sh->outfmtidx] & CODECS_FLAG_YUVHACK)
	priv->o_bih->biCompression = 0;

    // sanity check:
#ifdef BUILD_VFWEX
    ret = ICDecompressQueryEx(priv->handle, sh->bih, priv->o_bih);
#else
    ret = ICDecompressQuery(priv->handle, sh->bih, priv->o_bih);
#endif
    if (ret)
    {
	mp_msg(MSGT_WIN32,MSGL_WARN,"ICDecompressQuery failed: Error %d\n", (int)ret);
//	return 0;
    } else
	mp_msg(MSGT_WIN32,MSGL_V,"ICDecompressQuery OK\n");

#ifdef BUILD_VFWEX
    ret = ICDecompressBeginEx(priv->handle, sh->bih, priv->o_bih);
#else
    ret = ICDecompressBegin(priv->handle, sh->bih, priv->o_bih);
#endif
    if (ret)
    {
	mp_msg(MSGT_WIN32,MSGL_WARN,"ICDecompressBegin failed: Error %d\n", (int)ret);
//	return 0;
    }

    // for broken codecs set it again:
    if(sh->codec->outflags[sh->outfmtidx] & CODECS_FLAG_YUVHACK)
	set_csp(priv->o_bih,sh->codec->outfmt[sh->outfmtidx]);

    mp_msg(MSGT_WIN32, MSGL_V, "Input format:\n");
    if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh->bih,MSGL_V);
    mp_msg(MSGT_WIN32, MSGL_V, "Output format:\n");
    if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(priv->o_bih,MSGL_V);

    // set postprocessing level in xvid/divx4 .dll
    ICSendMessage(priv->handle, ICM_USER+80, (long)(&divx_quality), 0);

    // don't do this palette mess always, it makes div3 dll crashing...
    if(sh->codec->outfmt[sh->outfmtidx]==IMGFMT_BGR8){
	if(ICDecompressGetPalette(priv->handle, sh->bih, priv->o_bih)){
	    priv->palette = (unsigned char*)(priv->o_bih+1);
	    mp_msg(MSGT_WIN32,MSGL_V,"ICDecompressGetPalette OK\n");
	} else {
	    if(sh->bih->biSize>=40+4*4)
		priv->palette = (unsigned char*)(sh->bih+1);
	}
    }

    mp_msg(MSGT_DECVIDEO,MSGL_V,"INFO: Win32 video codec init OK!\n");
    return 1;
}
Esempio n. 5
0
static void test_Locate(void)
{
    static BITMAPINFOHEADER bi = {sizeof(BITMAPINFOHEADER),32,8, 1,8, BI_RLE8, 0,100000,100000, 0,0};
    static BITMAPINFOHEADER bo = {sizeof(BITMAPINFOHEADER),32,8, 1,8, BI_RGB, 0,100000,100000, 0,0};
    HIC h;
    DWORD err;

    /* Oddly, MSDN documents that ICLocate takes BITMAPINFOHEADER
     * pointers, while ICDecompressQuery takes the larger
     * BITMAPINFO.  Probably it's all the same as long as the
     * variable length color quads are present when they are
     * needed. */

    h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
    ok(h != 0, "RLE8->RGB failed\n");
    if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");

    bo.biHeight = - bo.biHeight;
    h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
    ok(h == 0, "RLE8->RGB height<0 succeeded\n");
    if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
    bo.biHeight = - bo.biHeight;

    bi.biCompression = mmioFOURCC('c','v','i','d'); /* Cinepak */
    h = ICOpen(ICTYPE_VIDEO, mmioFOURCC('c','v','i','d'), ICMODE_DECOMPRESS);
    if (h == 0) win_skip("Cinepak/ICCVID codec not found\n");
    else {
        bo.biBitCount = bi.biBitCount = 32;
        err = ICDecompressQuery(h, &bi, &bo);
        ok(err == ICERR_OK, "Query cvid->RGB32: %d\n", err);

        err = ICDecompressQuery(h, &bi, NULL);
        ok(err == ICERR_OK, "Query cvid 32: %d\n", err);

        bo.biHeight = -bo.biHeight;
        err = ICDecompressQuery(h, &bi, &bo);
        ok(err == ICERR_OK, "Query cvid->RGB32 height<0: %d\n", err);
        bo.biHeight = -bo.biHeight;

        ok(ICClose(h) == ICERR_OK,"ICClose failed\n");

        bo.biBitCount = bi.biBitCount = 8;
        h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
        todo_wine ok(h != 0, "cvid->RGB8 failed\n");
        if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
        bo.biHeight = - bo.biHeight;
        h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
        todo_wine ok(h != 0, "cvid->RGB8 height<0 failed\n");
        if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
        bo.biHeight = - bo.biHeight;

        bo.biBitCount = bi.biBitCount = 16;
        h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
        ok(h != 0, "cvid->RGB16 failed\n");
        if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
        bo.biHeight = - bo.biHeight;
        h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
        ok(h != 0, "cvid->RGB16 height<0 failed\n");
        if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
        bo.biHeight = - bo.biHeight;

        bo.biBitCount = bi.biBitCount = 32;
        h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
        ok(h != 0, "cvid->RGB32 failed\n");
        if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
        bo.biHeight = - bo.biHeight;
        h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
        ok(h != 0, "cvid->RGB32 height<0 failed\n");
        if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
        bo.biHeight = - bo.biHeight;

        bi.biCompression = mmioFOURCC('C','V','I','D');
        /* Unlike ICOpen, upper case fails with ICLocate. */
        h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
        ok(h == 0, "CVID->RGB32 upper case succeeded\n");
        if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
    }

    bi.biCompression = mmioFOURCC('M','S','V','C'); /* MS Video 1 */

    bo.biBitCount = bi.biBitCount = 16;
    h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
    ok(h != 0, "MSVC->RGB16 failed\n");
    if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");

    bo.biHeight = - bo.biHeight;
    h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
    todo_wine ok(h != 0, "MSVC->RGB16 height<0 failed\n");
    if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
    bo.biHeight = - bo.biHeight;

    bo.biHeight--;
    h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
    ok(h == 0, "MSVC->RGB16 height too small succeeded\n");
    if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
    bo.biHeight++;

    /* ICLocate wants upper case MSVC */
    bi.biCompression = mmioFOURCC('m','s','v','c');
    h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
    ok(h == 0, "msvc->RGB16 succeeded\n");
    if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");

    bi.biCompression = mmioFOURCC('M','S','V','C');
    h = ICOpen(ICTYPE_VIDEO, mmioFOURCC('M','S','V','C'), ICMODE_DECOMPRESS);
    ok(h != 0, "No MSVC codec installed!?\n");
    if (h != 0) {
        err = ICDecompressQuery(h, &bi, &bo);
        ok(err == ICERR_OK, "Query MSVC->RGB16: %d\n", err);

        err = ICDecompressQuery(h, &bi, NULL);
        ok(err == ICERR_OK, "Query MSVC 16: %d\n", err);

        bo.biHeight = -bo.biHeight;
        err = ICDecompressQuery(h, &bi, &bo);
        todo_wine ok(err == ICERR_OK, "Query MSVC->RGB16 height<0: %d\n", err);
        bo.biHeight = -bo.biHeight;

        bi.biCompression = mmioFOURCC('m','s','v','c');
        err = ICDecompressQuery(h, &bi, &bo);
        ok(err == ICERR_BADFORMAT, "Query msvc->RGB16: %d\n", err);

        ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
    }

    bi.biCompression = BI_RGB;
    bo.biBitCount = bi.biBitCount = 8;
    h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
    ok(h != 0, "RGB8->RGB identity failed\n");
    if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");

    bi.biCompression = BI_RLE8;
    h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
    ok(h != 0, "RLE8->RGB again failed\n");
    if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
}
Esempio n. 6
0
/***********************************************************************
 *		ICGetDisplayFormat			[MSVFW32.@]
 */
HIC VFWAPI ICGetDisplayFormat(HIC hic, BITMAPINFOHEADER *in, BITMAPINFOHEADER *out,
                              int depth, int width, int height)
{
    HIC tmphic = hic;

    TRACE("(%p, %p, %p, %d, %d, %d)\n", hic, in, out, depth, width, height);

    if (!tmphic)
    {
        tmphic = ICLocate(ICTYPE_VIDEO, 0, in, NULL, ICMODE_DECOMPRESS);
        if (!tmphic)
            return NULL;
    }

    if (ICDecompressQuery(tmphic, in, NULL))
        goto err;

    if (width <= 0 || height <= 0)
    {
        width = in->biWidth;
        height = in->biHeight;
    }

    if (!depth)
        depth = 32;

    *out = *in;
    out->biSize = sizeof(*out);
    out->biWidth = width;
    out->biHeight = height;
    out->biCompression = BI_RGB;
    out->biSizeImage = get_size_image(width, height, depth);

    /* first try the given depth */
    out->biBitCount = depth;
    out->biSizeImage = get_size_image(width, height, out->biBitCount);
    if (!ICDecompressQuery(tmphic, in, out))
    {
        if (depth == 8)
            ICDecompressGetPalette(tmphic, in, out);
        return tmphic;
    }

    /* then try 16, both with BI_RGB and BI_BITFIELDS */
    if (depth <= 16)
    {
        out->biBitCount = 16;
        out->biSizeImage = get_size_image(width, height, out->biBitCount);
        if (!ICDecompressQuery(tmphic, in, out))
            return tmphic;

        out->biCompression = BI_BITFIELDS;
        if (!ICDecompressQuery(tmphic, in, out))
            return tmphic;
        out->biCompression = BI_RGB;
    }

    /* then try 24 */
    if (depth <= 24)
    {
        out->biBitCount = 24;
        out->biSizeImage = get_size_image(width, height, out->biBitCount);
        if (!ICDecompressQuery(tmphic, in, out))
            return tmphic;
    }

    /* then try 32 */
    if (depth <= 32)
    {
        out->biBitCount = 32;
        out->biSizeImage = get_size_image(width, height, out->biBitCount);
        if (!ICDecompressQuery(tmphic, in, out))
            return tmphic;
    }

    /* as a last resort, try 32 bpp with the original width and height */
    out->biWidth = in->biWidth;
    out->biHeight = in->biHeight;
    out->biBitCount = 32;
    out->biSizeImage = get_size_image(out->biWidth, out->biHeight, out->biBitCount);
    if (!ICDecompressQuery(tmphic, in, out))
        return tmphic;

    /* finally, ask the compressor for its default output format */
    if (!ICSendMessage(tmphic, ICM_DECOMPRESS_GET_FORMAT, (DWORD_PTR)in, (DWORD_PTR)out))
        return tmphic;

err:
    if (hic != tmphic)
        ICClose(tmphic);

    return NULL;
}