关于DirectShow:枚举Windows上所有可用视频编解码器的最佳方法?

关于DirectShow:枚举Windows上所有可用视频编解码器的最佳方法?

Best way to enumerate all available video codecs on Windows?

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

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

1
2
3
4
5
6
7
8
9
10
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枚举所有解压缩器,但这对压缩器(编码器)一无所知。
  • 您可以枚举Windows的所有Video组件,但是没有指示它们是编码器还是解码器。
  • 有DirectShow过滤器可以很好地为您完成这项工作(例如,Motion JPEG过滤器),但是没有迹象表明特定的DirectShow过滤器是"视频解码器"。
  • 有人使用任何Windows API找到了针对此问题的通用解决方案吗? Windows Vista Media Foundation API是否可以解决所有这些问题?


    这最??好由DirectShow处理。

    DirectShow当前是平台SDK的一部分。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    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;
    }

    以下调用将所有视频压缩器枚举到控制台:

    1
    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?

    我不知道。

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

    中的过滤器

    1
    CLSID_ActiveMovieCategories

    是已安装的VfW过滤器的package器。

    (某些软件公司会创建自己的类别,因此某些计算机上可能存在"非官方"类别)

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

    GraphEdit本身是一个很好的工具,可以了解DirectShow的功能。因此,也许这可能是有关系统上的筛选器(及其相互作用)的更多信息的来源。


    我忘记了另一点。

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


    推荐阅读