我正在寻找一种好方法来枚举 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

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

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

有没有人使用任何 Windows API 找到此问题的通用解决方案?是否是Windows Vista 媒体基础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 页面 筛选类别 列出所有其他“官方”类别。

我希望这对您来说是一个良好的起点。

其他提示

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

从来没听说过。

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

中的过滤器

CLSID_ActiveMovieCategories

安装了 VfW 过滤器周围的包装器。

(一些软件公司创建自己的类别,因此某些机器上可能存在“非官方”类别)

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

GraphEdit 本身是一个很好的工具,可以让您了解 DirectShow 的底层功能。因此,这可能是有关您系统上的过滤器(及其交互)的更多信息的来源。

还有一点我忘记了。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top