枚举Windows上所有可用视频编解码器的最佳方法?
时间:2020-03-05 18:43:56 来源:igfitidea点击:
我正在寻找枚举Windows XP / Vista计算机上所有视频编解码器的好方法。
我需要向用户提供一组视频编解码器,包括压缩器和解压缩器。输出看起来像
Available Decoders DiVX Version 6.0 XVID Motion JPEG CompanyX's MPEG-2 Decoder Windows Media Video **Available Encoders** DiVX Version 6.0 Windows Media Video
我遇到的问题是,没有可靠的方法来捕获系统可用的所有解码器。例如:
- 我们可以使用DirectShow枚举所有解压缩器,但这对压缩器(编码器)一无所知。
- 我们可以枚举" Video For Windows"的所有组件,但没有指示它们是编码器还是解码器。
- 有DirectShow过滤器可以很好地为我们完成这项工作(例如,Motion JPEG过滤器),但是没有迹象表明特定的DirectShow过滤器是"视频解码器"。
是否有人使用任何Windows API找到了针对此问题的通用解决方案? Windows Vista Media Foundation API是否可以解决所有这些问题?
解决方案
回答
这最好由DirectShow处理。
DirectShow当前是平台SDK的一部分。
HRESULT extractFriendlyName( IMoniker* pMk, std::wstring& str ) { assert( pMk != 0 ); IPropertyBag* pBag = 0; HRESULT hr = pMk->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag ); if( FAILED( hr ) || pBag == 0 ) { return hr; } VARIANT var; var.vt = VT_BSTR; hr = pBag->Read(L"FriendlyName", &var, NULL); if( SUCCEEDED( hr ) && var.bstrVal != 0 ) { str = reinterpret_cast<wchar_t*>( var.bstrVal ); SysFreeString(var.bstrVal); } pBag->Release(); return hr; } HRESULT enumerateDShowFilterList( const CLSID& category ) { HRESULT rval = S_OK; HRESULT hr; ICreateDevEnum* pCreateDevEnum = 0; // volatile, will be destroyed at the end hr = ::CoCreateInstance( CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast<void**>( &pCreateDevEnum ) ); assert( SUCCEEDED( hr ) && pCreateDevEnum != 0 ); if( FAILED( hr ) || pCreateDevEnum == 0 ) { return hr; } IEnumMoniker* pEm = 0; hr = pCreateDevEnum->CreateClassEnumerator( category, &pEm, 0 ); // If hr == S_FALSE, no error is occured. In this case pEm is NULL, because // a filter does not exist e.g no video capture devives are connected to // the computer or no codecs are installed. assert( SUCCEEDED( hr ) && ((hr == S_OK && pEm != 0 ) || hr == S_FALSE) ); if( FAILED( hr ) ) { pCreateDevEnum->Release(); return hr; } if( hr == S_OK && pEm != 0 ) // In this case pEm is != NULL { pEm->Reset(); ULONG cFetched; IMoniker* pM = 0; while( pEm->Next(1, &pM, &cFetched) == S_OK && pM != 0 ) { std::wstring str; if( SUCCEEDED( extractFriendlyName( pM, str ) ) { // str contains the friendly name of the filter // pM->BindToObject creates the filter std::wcout << str << std::endl; } pM->Release(); } pEm->Release(); } pCreateDevEnum->Release(); return rval; }
以下调用将所有视频压缩器枚举到控制台:
enumerateDShowFilterList( CLSID_VideoCompressorCategory );
MSDN页面"过滤器类别"列出了所有其他"官方"类别。
我希望这对我们来说是一个很好的起点。
回答
The answer above doesn't account for decompressors. There is no CLSID_VideoDecompressorCategory. Is the are a way to ask a filter if it is a video decompressor?
从来没听说过。
此列表中的大多数过滤器都是编解码器,因此同时包含编码器和解码器。
中的过滤器
CLSID_ActiveMovieCategories
是围绕已安装的VfW过滤器的包装。
(某些软件公司会创建自己的类别,因此某些计算机上可能存在"非官方"类别)
如果要查看所有已安装的类别,请使用DirectShow SDK随附的GraphEdit。
GraphEdit本身是一个很好的工具,可以了解DirectShow的功能。因此,这可能是有关系统上筛选器(及其相互作用)的更多信息的来源。
回答
我忘记了另一点。
Windows Media Foundation是使用WMV / WMA的工具包。它不提供DirectShow支持的所有功能。它实际上只是Windows Media的一个SDK。
WMV / WMA中有到DirectShow的绑定,因此我们可以在DirectShow应用程序中使用WM *文件/流。