Example #1
0
static void test_ICInfo(void)
{
    ICINFO info, info2;
    DWORD i, found;
    unsigned char *fcc;

    for (i = found = 0; ICInfo(0, i, &info); i++)
    {
        trace("Codec name: %s, fccHandler: 0x%08x\n", wine_dbgstr_w(info.szName), info.fccHandler);
        ok(info.fccType, "expected nonzero fccType\n");

        ok(ICInfo(info.fccType, info.fccHandler, &info2),
           "ICInfo failed on fcc 0x%08x\n", info.fccHandler);

        fcc = (unsigned char *)&info.fccHandler;
        if (!isalpha(fcc[0])) continue;

        found++;
        /* Test getting info with a different case - bug 41602 */
        fcc[0] ^= 0x20;
        ok(ICInfo(info.fccType, info.fccHandler, &info2),
           "ICInfo failed on fcc 0x%08x\n", info.fccHandler);
    }
    ok(found != 0, "expected at least one codec\n");

    memset(&info, 0, sizeof(info));
    ok(!ICInfo(ICTYPE_VIDEO, mmioFOURCC('f','a','k','e'), &info), "expected failure\n");
    ok(info.fccType == ICTYPE_VIDEO, "got 0x%08x\n", info.fccType);
    ok(info.fccHandler == mmioFOURCC('f','a','k','e'), "got 0x%08x\n", info.fccHandler);
}
Example #2
0
void CPgPubExtra::FillCodecs()
{
	m_comboCodec.ResetContent();
	m_codecs.Destroy();

	BITMAPINFOHEADER bih; 
	ZeroMemory( &bih, sizeof( bih ) );
	bih.biSize = sizeof( bih );
	bih.biPlanes = 1; 
	bih.biCompression = BI_RGB;
	bih.biBitCount = 24;
	
	ICINFO ii;
	ZeroMemory( &ii, sizeof( ii ) );
	ii.dwSize = sizeof( ii );
	
	for ( DWORD i = 0; ICInfo( ICTYPE_VIDEO, i, &ii ); i++ )
	{
		// This one is valid
		DWORD fourCC = ii.fccHandler;

		HIC hIc = ICOpen( ii.fccType, ii.fccHandler, ICMODE_QUERY );
		if ( hIc != NULL )
		{
			// Ensure it supports our video type
			if (	ii.fccType == ICTYPE_VIDEO && 
//					ICCompressQuery( hIc, &bih, NULL ) == ICERR_OK &&
					ICGetInfo( hIc, &ii, sizeof( ii ) ) )
			{
				char str[ 256 ] = { 0 };
				wcstombs( str, ii.szDescription, sizeof( str ) );

				// Save codec info
				LPCODECINFO pci = (LPCODECINFO)m_codecs.NewObj( sizeof( CODECINFO ), NULL, i, str );
				if ( pci != NULL )
				{
					// Save data
					pci->bConfig = ICQueryConfigure( hIc ) != ICERR_OK; // Backwards???
					pci->fourCC = fourCC;

					// Get settings
					int item = m_comboCodec.AddString( str );
					if ( item != CB_ERR ) m_comboCodec.SetItemData( item, (DWORD)pci );

				} // end if
					
			} // end if

			ICClose( hIc ); 

		} // end if

		// Next codec
		ZeroMemory( &ii, sizeof( ii ) );
		ii.dwSize = sizeof( ii );
		i++;

	} // end while

}
Example #3
0
/***********************************************************************
 *		ICGetInfo			[MSVFW32.@]
 */
LRESULT VFWAPI ICGetInfo(HIC hic, ICINFO *picinfo, DWORD cb) 
{
    LRESULT	ret;
    WINE_HIC*   whic = MSVIDEO_GetHicPtr(hic);

    TRACE("(%p,%p,%d)\n", hic, picinfo, cb);

    if (!whic) return ICERR_BADHANDLE;
    if (!picinfo) return MMSYSERR_INVALPARAM;

    /* (WS) The field szDriver should be initialized because the driver 
     * is not obliged and often will not do it. Some applications, like
     * VirtualDub, rely on this field and will occasionally crash if it
     * goes uninitialized.
     */
    if (cb >= sizeof(ICINFO)) picinfo->szDriver[0] = '\0';

    ret = ICSendMessage(hic, ICM_GETINFO, (DWORD_PTR)picinfo, cb);

    /* (WS) When szDriver was not supplied by the driver itself, apparently 
     * Windows will set its value equal to the driver file name. This can
     * be obtained from the registry as we do here.
     */
    if (cb >= sizeof(ICINFO) && picinfo->szDriver[0] == 0)
    {
        ICINFO  ii;

        memset(&ii, 0, sizeof(ii));
        ii.dwSize = sizeof(ii);
        ICInfo(picinfo->fccType, picinfo->fccHandler, &ii);
        lstrcpyW(picinfo->szDriver, ii.szDriver);
    }

    return ret;
}
Example #4
0
static bool DetectDriver(const char *pszName) {
    char szDriverANSI[256];
    ICINFO info = { sizeof(ICINFO) };

    for(int i=0; ICInfo(ICTYPE_VIDEO, i, &info); ++i) {
        if (WideCharToMultiByte(CP_ACP, 0, info.szDriver, -1, szDriverANSI, sizeof szDriverANSI, NULL, NULL)
                && !_stricmp(szDriverANSI, pszName))

            return true;
    }

    return false;
}
Example #5
0
static BOOL enum_compressors(HWND list, COMPVARS *pcv, BOOL enum_all)
{
    UINT id, total = 0;
    ICINFO icinfo;

    id = 0;

    while (ICInfo(pcv->fccType, id, &icinfo))
    {
        struct codec_info *ic;
        DWORD idx;
        HIC hic;

        id++;

        hic = ICOpen(icinfo.fccType, icinfo.fccHandler, ICMODE_COMPRESS);

        if (hic)
        {
            /* for unknown reason fccHandler reported by the driver
             * doesn't always work, use the one returned by ICInfo instead.
             */
            DWORD fccHandler = icinfo.fccHandler;

            if (!enum_all && pcv->lpbiIn)
            {
                if (ICCompressQuery(hic, pcv->lpbiIn, NULL) != ICERR_OK)
                {
                    TRACE("fccHandler %s doesn't support input DIB format %d\n",
                          wine_dbgstr_fcc(icinfo.fccHandler), pcv->lpbiIn->bmiHeader.biCompression);
                    ICClose(hic);
                    continue;
                }
            }

            ICGetInfo(hic, &icinfo, sizeof(icinfo));
            icinfo.fccHandler = fccHandler;

            idx = SendMessageW(list, CB_ADDSTRING, 0, (LPARAM)icinfo.szDescription);

            ic = HeapAlloc(GetProcessHeap(), 0, sizeof(struct codec_info));
            ic->icinfo = icinfo;
            ic->hic = hic;
            SendMessageW(list, CB_SETITEMDATA, idx, (LPARAM)ic);
        }
        total++;
    }

    return total != 0;
}
Example #6
0
/***********************************************************************
 *		ICInfo				[MSVIDEO.200]
 */
BOOL16 VFWAPI ICInfo16(DWORD fccType, DWORD fccHandler, ICINFO16 *lpicinfo)
{
    BOOL16 ret;
    LPVOID lpv;
    DWORD lParam = (DWORD)lpicinfo;
    DWORD size = ((ICINFO*)(MapSL((SEGPTR)lpicinfo)))->dwSize;

    /* Use the mapping functions to map the ICINFO structure */
    lpv = MSVIDEO_MapMsg16To32(ICM_GETINFO, &lParam, &size);

    ret = ICInfo(fccType, fccHandler, (ICINFO*)lParam);

    MSVIDEO_UnmapMsg16To32(ICM_GETINFO, lpv, &lParam, &size);

    return ret;
}
Example #7
0
void EnumVCM(bool bEnc)
{
	ICINFO info;
	char buf[256];

	for (int i = 0; ICInfo(ICTYPE_VIDEO, i, &info); i++)
	{
		HIC hic = ICOpen(ICTYPE_VIDEO, info.fccHandler, bEnc ? ICMODE_COMPRESS : ICMODE_DECOMPRESS);
		if (hic == NULL)
			continue;
		ICGetInfo(hic, &info, sizeof(info));
		ICClose(hic);
		wsprintf(buf, "VCM\t%d\t%S\t%c%c%c%c\n", bEnc, info.szDescription, FCC4PRINTF(info.fccHandler));
		printf("%s", buf);
	}
}
QMap<std::wstring, bool> AviCodecRestrictions::getUsableCodecs(const TDimension &resolution)
{
	QMap<std::wstring, bool> codecs;

	HIC hic = 0;
	ICINFO icinfo;
	memset(&icinfo, 0, sizeof(ICINFO));

	char descr[2048], name[2048];
	DWORD fccType = 0;

	BITMAPINFO inFmt;
	memset(&inFmt, 0, sizeof(BITMAPINFO));

	inFmt.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	inFmt.bmiHeader.biWidth = inFmt.bmiHeader.biHeight = 100;
	inFmt.bmiHeader.biPlanes = 1;
	inFmt.bmiHeader.biCompression = BI_RGB;
	int bpp;
	for (bpp = 32; (bpp >= 24); bpp -= 8) {
		//find the codec.
		inFmt.bmiHeader.biBitCount = bpp;
		for (int i = 0; ICInfo(fccType, i, &icinfo); i++) {
			hic = ICOpen(icinfo.fccType, icinfo.fccHandler, ICMODE_COMPRESS);

			ICGetInfo(hic, &icinfo, sizeof(ICINFO)); // Find out the compressor name
			WideCharToMultiByte(CP_ACP, 0, icinfo.szDescription, -1, descr, sizeof(descr), 0, 0);
			WideCharToMultiByte(CP_ACP, 0, icinfo.szName, -1, name, sizeof(name), 0, 0);

			std::wstring compressorName;
			compressorName = toWideString(std::string(name) + " '" + toString(bpp) + "' " + std::string(descr));

			if (hic) {
				if (ICCompressQuery(hic, &inFmt, NULL) != ICERR_OK) {
					ICClose(hic);
					continue; // Skip this compressor if it can't handle the format.
				}
				codecs[compressorName] = canWork(hic, resolution, bpp);
				ICClose(hic);
			}
		}
	}
	return codecs;
}
Example #9
0
int LBXGL_CodecVFW_Init()
{
	LBXGL_VidCodec *codec;
	ICINFO *info;
	int i, j;
	short *sw;
	char buf[256];
	char *t;

	printf("VFW: Init\n");

	codec=LBXGL_VidCodec_New();
	codec->begin_decompress=&vfw_begin_decompress;

	PDGL_RegisterShutdown(&vfw_shutdown);

#if 1
	info=malloc(sizeof(ICINFO));
	memset(info, 0, sizeof(ICINFO));

	for(i=0; i<1024; i++)
	{
//		info->dwSize=sizeof(ICINFO);
		j=ICInfo(0, i, info);
		if(j!=1)break;
//		kprint("%d: %d %p\n", i, j, info);
//		kprint("dwSize: %d (%d)\n", info->dwSize, sizeof(ICINFO));
		printf("fccType: %04.4s\n", &info->fccType);
		printf("fccHandler: %04.4s\n", &info->fccHandler);
//		kprint("dwFlags: %d\n", info->dwFlags);
		if(info->szName[0])
			printf("szName: %S\n", info->szName);
		if(info->szDescription[0])
			printf("szDescription: %S\n", info->szDescription);
	}
#endif

	return(0);
}
Example #10
0
void CAviFile::GetCompressorList( CStringList &List, BITMAPINFO &SourceBitmapInfo )
{
	///////////////////////////////////////////////////////////
	LPBITMAPINFOHEADER lpbi = 0;
	HIC hIC;
	ICINFO icinfo;

	int fccType = ICTYPE_VIDEO;	//0 to get all installed codecs
	for (int i=0; ICInfo(fccType, i, &icinfo); i++) {
		hIC = ICOpen(icinfo.fccType, icinfo.fccHandler, ICMODE_QUERY);

		if (hIC) {
			//Find out the compressor name.
			ICGetInfo(hIC, &icinfo, sizeof(icinfo));

			//Skip this compressor if it can't handle the format.
			if (fccType == ICTYPE_VIDEO )
			{
				if( icinfo.dwFlags != 0 )
				{
					if( ICCompressQuery( hIC, &SourceBitmapInfo, NULL ) == ICERR_OK )
					{
						CString Temp = CString( icinfo.szDescription );
						if( icinfo.fccHandler == 1129730893 )
							Temp += " - Low Resolution";
						Temp += " (";
						Temp.Append( (const char*)&icinfo.fccHandler, 4 ); // Assuming little endian system.
						Temp += ")";
						List.AddTail( Temp );
					}
				}
			}

			//check here whether it is the driver you want
			ICClose(hIC);
		}
	}
}
Example #11
0
static void register_vfw_codecs(void)
{
    WCHAR avico_clsid_str[CHARS_IN_GUID];
    HKEY basekey, key;
    ICINFO icinfo;
    DWORD i, res;

    static const WCHAR CLSIDW[] = {'C','L','S','I','D',0};
    static const WCHAR FccHandlerW[] = {'F','c','c','H','a','n','d','l','e','r',0};
    static const WCHAR FriendlyNameW[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};

    StringFromGUID2(&CLSID_AVICo, avico_clsid_str, sizeof(avico_clsid_str)/sizeof(WCHAR));

    basekey = open_special_category_key(&CLSID_VideoCompressorCategory, TRUE);
    if(!basekey) {
        ERR("Could not create key\n");
        return;
    }

    for(i=0; ICInfo(FCC('v','i','d','c'), i, &icinfo); i++) {
        WCHAR fcc_str[5] = {LOBYTE(LOWORD(icinfo.fccHandler)), HIBYTE(LOWORD(icinfo.fccHandler)),
                            LOBYTE(HIWORD(icinfo.fccHandler)), HIBYTE(HIWORD(icinfo.fccHandler))};

        res = RegCreateKeyW(basekey, fcc_str, &key);
        if(res != ERROR_SUCCESS)
            continue;

        RegSetValueExW(key, CLSIDW, 0, REG_SZ, (const BYTE*)avico_clsid_str, sizeof(avico_clsid_str));
        RegSetValueExW(key, FccHandlerW, 0, REG_SZ, (const BYTE*)fcc_str, sizeof(fcc_str));
        RegSetValueExW(key, FriendlyNameW, 0, REG_SZ, (const BYTE*)icinfo.szName, (strlenW(icinfo.szName)+1)*sizeof(WCHAR));
        /* FIXME: Set ClassManagerFlags and FilterData values */

        RegCloseKey(key);
    }

    RegCloseKey(basekey);
}
Example #12
0
int AVInfo::GetCodecListSize(int width, int height)
{
    if (m_plCodecList)
    {
        for (int i=0; i<m_codecListSize; ++i)
            delete m_plCodecList[i];
        delete[] m_plCodecList;
        m_plCodecList = NULL;
        m_codecListSize = 0;
    }

    BITMAPINFO bmi;
    Make24BitRGB(&bmi.bmiHeader, width, height);

    ICINFO icInfo;
    ZeroMemory(&icInfo, sizeof ICINFO);
    icInfo.dwSize = sizeof ICINFO;
    int count = 0;

    std::vector<CODECINFO *> codecList;

    // The first codec is always uncompressed RGB
    // data. We can be sure this is the case here
    CODECINFO *pInfo = new CODECINFO;
    pInfo->fcc = MAKEFOURCC('D', 'I', 'B', ' ');
    pInfo->alternativeFcc = BI_RGB;
    pInfo->bHasAboutDialog = false;
    pInfo->bHasConfigureDialog = false;
    pInfo->bSupportsKeyframes = false;
    pInfo->bSupportsQuality = false;
    pInfo->nDefaultKeyframeRate = 1;
    pInfo->nDefaultQuality = 100;
    _tcscpy(pInfo->tszDescription, _T("DIB : <uncompressed>"));
    codecList.push_back(pInfo);

    while (ICInfo(ICTYPE_VIDEO, count, &icInfo))
    {
        HIC hic = ICOpen(icInfo.fccType, icInfo.fccHandler, ICMODE_QUERY);
        if (hic)
        {
            ICINFO moreInfo;
            ZeroMemory(&moreInfo, sizeof ICINFO);
            moreInfo.dwSize = sizeof ICINFO;

            if (ICGetInfo(hic, &moreInfo, sizeof ICINFO) > 0)
            {
                // Ignore MSVC/CRAM
                if (moreInfo.fccHandler != 'CVSM' &&
                        moreInfo.fccHandler != 'MARC')
                {
                    if (ICERR_OK == ICCompressQuery(hic, &bmi, NULL))
                    {
                        // Ok, this codec seems to be ok; put that
                        // into the list
                        CODECINFO *pInfo = new CODECINFO;
                        ZeroMemory(pInfo, sizeof CODECINFO);

                        char szFcc[5];
                        if (moreInfo.fccHandler != BI_RGB)
                        {
                            szFcc[0] = (moreInfo.fccHandler & 0x000000ff);
                            szFcc[1] = (moreInfo.fccHandler & 0x0000ff00) >> 8;
                            szFcc[2] = (moreInfo.fccHandler & 0x00ff0000) >> 16;
                            szFcc[3] = (moreInfo.fccHandler & 0xff000000) >> 24;
                            szFcc[4] = 0;
                        }
                        else
                            strcpy(szFcc, "DIB ");

                        bool bIsReallyOk = true;

                        // We know that IV50 has restrictions.
                        if (moreInfo.fccHandler == '05vi' ||
                                moreInfo.fccHandler == '05VI')
                        {
                            if (width % 4 != 0 ||
                                    height % 4 != 0)
                                bIsReallyOk = false;
                        }

                        // The following code should normally check if the codec
                        // is really able encode a certain BITMAPINFO type. But,
                        // This will fail for the HuffYUV codec. Thus, we have to
                        // assume that it might fail for other codecs, too.
                        /*
                        if (moreInfo.fccHandler == BI_RGB)
                        {
                           bIsReallyOk = true;
                        }
                        else
                        {
                           // The codec says that the input format is ok.
                           // Let's try to create an output format and try
                           // again. For some resolutions, e.g. Indeo Video 5
                           // now fails to compress the format.
                           AM_MEDIA_TYPE mtTmp;
                           ZeroMemory(&mtTmp, sizeof AM_MEDIA_TYPE);
                           bool cool = CreateStreamFormat(moreInfo.fccHandler, width, height, &mtTmp);

                           if (cool)
                           {
                              BITMAPINFO bmiOut;
                              ZeroMemory(&bmiOut, sizeof BITMAPINFO);
                              bmiOut.bmiHeader = ((VIDEOINFOHEADER *) mtTmp.pbFormat)->bmiHeader;
                              DWORD dwOk = ICCompressBegin(hic, &bmi, &bmiOut);
                              if (ICERR_OK == dwOk)
                              {
                                 // It's really ok to use this codec.
                                 bIsReallyOk = true;
                                 ICCompressEnd(hic);
                              }
                           }

                           FreeMediaType(mtTmp);
                        }
                        */

                        if (bIsReallyOk)
                        {
                            // Copy the name
#ifndef _UNICODE
                            _TCHAR tszDesc[128];
                            if (WideCharToMultiByte(CP_ACP, 0, moreInfo.szDescription, -1, tszDesc, 128, NULL, NULL) == 0)
                                strcpy(tszDesc, "<unknown>");
                            sprintf(pInfo->tszDescription, "(%s): %s", szFcc, tszDesc);
#else
                            _stprintf(pInfo->tszDescription, _T("(%S): %s"), szFcc, moreInfo.szDescription);
#endif

                            pInfo->fcc = moreInfo.fccHandler;
                            pInfo->alternativeFcc = icInfo.fccHandler;
                            pInfo->bSupportsKeyframes = (moreInfo.dwFlags & VIDCF_TEMPORAL) > 0;
                            pInfo->bSupportsQuality = (moreInfo.dwFlags & VIDCF_QUALITY) > 0;
                            if (pInfo->bSupportsKeyframes)
                                pInfo->nDefaultKeyframeRate = ICGetDefaultKeyFrameRate(hic);
                            else
                                pInfo->nDefaultKeyframeRate = 0;
                            if (pInfo->bSupportsQuality)
                                pInfo->nDefaultQuality = ICGetDefaultQuality(hic) / 100;
                            else
                                pInfo->nDefaultQuality = 0;

                            pInfo->bHasConfigureDialog = ICQueryConfigure(hic) == TRUE ? true : false;
                            pInfo->bHasAboutDialog = ICQueryAbout(hic) == TRUE ? true : false;

                            codecList.push_back(pInfo);
                        }
                    }
                }
            }
Example #13
0
int
PGRAviFile::enumerateCompressors( int  iRows, int iCols, int iBPP, 
                                  ICINFO* picinfo, int iNumICInfo )
{
   // If picinfo is NULL, then we are retreiving the number of
   // usable compressors at the current settings so we can allocate
   // enough memory.
   bool bpicinfoNull = picinfo == NULL;

   ICINFO* picinfoTemp = new ICINFO[ 50 ];

   HIC hic;
   
   BITMAPINFOHEADER bih; 
   
   // Initialize the bitmap structure. 
   bih.biSize          = sizeof( BITMAPINFOHEADER );
   bih.biPlanes        = 1;
   bih.biCompression   = BI_RGB;
   bih.biXPelsPerMeter = 100;
   bih.biYPelsPerMeter = 100;
   bih.biClrUsed       = 0;
   bih.biClrImportant  = 0;
   bih.biWidth         = iCols;
   bih.biHeight        = iRows;
   bih.biBitCount      = (unsigned short)iBPP;
   
   bih.biSizeImage = 
      bih.biWidth * bih.biHeight * ( bih.biBitCount / 8 );

   int  iNumCompressors = 0;
   bool bICInfoFull     = false;
   
   for( int i = 0; ICInfo( 0, i, &picinfoTemp[ i ] ) && !bICInfoFull; i++ ) 
   { 
      // Open the compressor so we can query it.
      hic = ICOpen( picinfoTemp[ i ].fccType, 
         picinfoTemp[ i ].fccHandler, ICMODE_QUERY ); 
      
      if( hic ) 
      { 
         // Skip this compressor if it can't handle the format. 
         if( ICCompressQuery( hic, &bih, 0 ) != ICERR_OK ) 
         { 
            ICClose( hic ); 
            continue; 
         } 
         
         // Find out the compressor info. 
         if( !bpicinfoNull )
         {
            ICGetInfo( hic, &picinfo[ iNumCompressors ], sizeof( ICINFO ) );
         }

         iNumCompressors++;

         if( !bpicinfoNull && (iNumCompressors == iNumICInfo) )
         {
            bICInfoFull = true;
         }
         
         // Close the compressor.
         ICClose( hic ); 
      } 
   } 

   delete [] picinfoTemp;

   return iNumCompressors;
}
Example #14
0
/***********************************************************************
 *		ICOpen				[MSVFW32.@]
 * Opens an installable compressor. Return special handle.
 */
HIC VFWAPI ICOpen(DWORD fccType, DWORD fccHandler, UINT wMode) 
{
    WCHAR		codecname[10];
    ICOPEN		icopen;
    HDRVR		hdrv;
    WINE_HIC*           whic;
    static const WCHAR  drv32W[] = {'d','r','i','v','e','r','s','3','2','\0'};
    reg_driver*         driver;

    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)) {
	    fccType = driver->fccType;
	    fccHandler = driver->fccHandler;
	    break;
        } else
            driver = driver->next;

    if (driver && driver->proc)
        /* 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 */

    if (!driver) {
        /* 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);
        codecname[9] = '\0';

        hdrv = OpenDriver(codecname, drv32W, (LPARAM)&icopen);
        if (!hdrv)
            return 0;
    } else {
        /* The driver has been registered at runtime with its name */
        hdrv = OpenDriver(driver->name, NULL, (LPARAM)&icopen);
        if (!hdrv) 
            return 0; 
    }

    whic = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC));
    if (!whic)
    {
        CloseDriver(hdrv, 0, 0);
        return FALSE;
    }
    whic->hdrv          = hdrv;
    whic->driverproc    = NULL;
    whic->type          = fccType;
    whic->handler       = fccHandler;
    while (MSVIDEO_GetHicPtr((HIC)(ULONG_PTR)IC_HandleRef) != NULL) IC_HandleRef++;
    whic->hic           = (HIC)(ULONG_PTR)IC_HandleRef++;
    whic->next          = MSVIDEO_FirstHic;
    MSVIDEO_FirstHic = whic;

    TRACE("=> %p\n", whic->hic);
    return whic->hic;
}