5

我正在寻找一种枚举 Windows XP/Vista 机器上所有视频编解码器的好方法。

我需要向用户展示一组视频编解码器,包括压缩器和解压缩器。输出看起来像

可用的解码器
DiVX 版本 6.0
XVID
动态JPEG
CompanyX 的 MPEG-2 解码器
视窗媒体视频

**可用的编码器**
DiVX 版本 6.0
视窗媒体视频

我遇到的问题是没有可靠的方法来捕获系统可用的所有解码器。例如:

  1. 您可以使用 DirectShow 枚举所有解压缩器,但这不会告诉您有关压缩器(编码器)的任何信息。
  2. 您可以枚举所有 Video For Windows 组件,但您不会得到任何指示,它们是编码器还是解码器。
  3. 有 DirectShow 过滤器可以很好地为您完成这项工作(例如 Motion JPEG 过滤器),但没有迹象表明特定的 DirectShow 过滤器是“视频解码器”。

是否有人使用任何 Windows API 找到了针对此问题的通用解决方案?Windows Vista Media Foundation API是否解决了这些问题?

4

3 回答 3

7

这最好由 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 页面过滤器类别列出了所有其他“官方”类别。

我希望这对你来说是一个很好的起点。

于 2008-08-27T16:34:45.290 回答
2

上面的答案不考虑减压器。没有 CLSID_VideoDecompressorCategory。是否有一种方法可以询问过滤器是否是视频解压缩器?

从来没听说过。

此列表中的大多数过滤器都是编解码器,因此包含编码器和解码器。

中的过滤器

CLSID_ActiveMovieCategories

是安装的 VfW 过滤器的包装器。

(有些软件公司会自己创建分类,所以有些机器上可能会有“非官方”分类)

如果您想查看所有已安装的类别,请使用 DirectShow SDK 提供的 GraphEdit。

GraphEdit 本身是一个很好的工具,可以查看 DirectShow 在后台做了什么。因此,也许这可能是有关系统上过滤器(及其交互)的更多信息的来源。

于 2008-08-27T17:18:28.397 回答
1

还有一点我忘记了。

Windows Media Foundation 是一个使用 WMV/WMA 的工具包。它不提供 DirectShow 支持的所有东西。它实际上只是一个适用于 Windows Media 的 SDK。WMV/WMA 中有与 DirectShow 的绑定,因此您可以在 DirectShow 应用程序中使用 WM* 文件/流。

于 2008-08-27T17:21:55.970 回答