代码之家  ›  专栏  ›  技术社区  ›  Nick Haddad

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

  •  5
  • Nick Haddad  · 技术社区  · 16 年前

    我正在寻找一种枚举WindowsXP/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. 您可以为Windows组件枚举所有视频,但如果这些组件是编码器或解码器,则不会得到任何指示。
    3. 有一些DirectShow过滤器可以很好地为您完成工作(例如,Motion JPEG过滤器),但没有迹象表明特定的DirectShow过滤器是“视频解码器”。

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

    3 回复  |  直到 11 年前
        1
  •  7
  •   Christopher    16 年前

    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 );
    

    Filter Categories

        2
  •  2
  •   Christopher    16 年前

    CLSID_ActiveMovieCategories
    

        3
  •  1
  •   Christopher    16 年前