<p>I'm looking for a good way to enumerate all the Video codecs on a Windows XP/Vista machine.</p>

<p>I need present the user with a set of video codecs, including the compressors and decompressors.  The output would look something like</p>

<pre>
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
</pre>

<p>The problem that I am running into is that there is no reliable way to to capture all of the decoders available to the system.  For instance:</p>

<ol>
<li>You can enumerate all the decompressors using DirectShow, but this tells you nothing about the compressors (encoders).</li>
<li>You can enumerate all the Video For Windows components, but you get no indication if these are encoders or decoders.</li>
<li>There are DirectShow filters that may do the job for you perfectly well (Motion JPEG filter for example), but there is no indication that a particular DirectShow filter is a "video decoder".</li>
</ol>

<p>Has anyone found a generalizes solution for this problem using any of the Windows APIs?  Does the Windows Vista <a href="http://en.wikipedia.org/wiki/Media_Foundation" rel="nofollow noreferrer">Media Foundation API</a> solve any of these issues?</p>

[{'answer_id': 30596, 'author': 'Christopher', 'author_id': 3186, 'author_profile': 'https://Stackoverflow.com/users/3186', 'pm_score': 4, 'selected': True, 'text': '<p>This is best handled by DirectShow.</p>\n\n<p>DirectShow is currently a part of the platform SDK.</p>\n\n<pre><code>HRESULT extractFriendlyName( IMoniker* pMk, std::wstring&amp; str )\n{\n  assert( pMk != 0 );\n  IPropertyBag* pBag = 0;\n  HRESULT hr = pMk-&gt;BindToStorage(0, 0, IID_IPropertyBag, (void **)&amp;pBag );\n  if( FAILED( hr ) || pBag == 0 )\n  {\n    return hr;\n  }\n  VARIANT var;\n  var.vt = VT_BSTR;\n  hr = pBag-&gt;Read(L"FriendlyName", &amp;var, NULL);\n  if( SUCCEEDED( hr ) &amp;&amp; var.bstrVal != 0 )\n  {\n    str = reinterpret_cast&lt;wchar_t*&gt;( var.bstrVal );\n    SysFreeString(var.bstrVal);\n  }\n  pBag-&gt;Release();\n  return hr;\n}\n\n\nHRESULT enumerateDShowFilterList( const CLSID&amp; category )\n{\n  HRESULT rval = S_OK;\n  HRESULT hr;\n  ICreateDevEnum* pCreateDevEnum = 0; // volatile, will be destroyed at the end\n  hr = ::CoCreateInstance( CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast&lt;void**&gt;( &amp;pCreateDevEnum ) );\n\n  assert( SUCCEEDED( hr ) &amp;&amp; pCreateDevEnum != 0 );\n  if( FAILED( hr ) || pCreateDevEnum == 0 )\n  {\n    return hr;\n  }\n\n  IEnumMoniker* pEm = 0;\n  hr = pCreateDevEnum-&gt;CreateClassEnumerator( category, &amp;pEm, 0 );\n\n  // If hr == S_FALSE, no error is occured. In this case pEm is NULL, because\n  // a filter does not exist e.g no video capture devives are connected to\n  // the computer or no codecs are installed.\n  assert( SUCCEEDED( hr ) &amp;&amp; ((hr == S_OK &amp;&amp; pEm != 0 ) || hr == S_FALSE) );\n  if( FAILED( hr ) )\n  {\n    pCreateDevEnum-&gt;Release();\n    return hr;\n  }\n\n  if( hr == S_OK &amp;&amp; pEm != 0 ) // In this case pEm is != NULL\n  {\n    pEm-&gt;Reset();\n    ULONG cFetched;\n    IMoniker* pM = 0;\n    while( pEm-&gt;Next(1, &amp;pM, &amp;cFetched) == S_OK &amp;&amp; pM != 0 )\n    {\n       std::wstring str;\n\n       if( SUCCEEDED( extractFriendlyName( pM, str ) )\n       {\n          // str contains the friendly name of the filter\n          // pM-&gt;BindToObject creates the filter\n          std::wcout &lt;&lt; str &lt;&lt; std::endl;\n       }\n\n       pM-&gt;Release();\n    }\n    pEm-&gt;Release();\n  }\n  pCreateDevEnum-&gt;Release();\n  return rval;\n}\n</code></pre>\n\n<p>The following call enumerates all video compressors to the console :</p>\n\n<pre><code>enumerateDShowFilterList( CLSID_VideoCompressorCategory );\n</code></pre>\n\n<p>The MSDN page <a href="http://msdn.microsoft.com/en-us/library/ms783347(VS.85).aspx" rel="noreferrer">Filter Categories</a> lists all other \'official\' categories.</p>\n\n<p>I hope that is a good starting point for you.</p>\n'}, {'answer_id': 30669, 'author': 'Christopher', 'author_id': 3186, 'author_profile': 'https://Stackoverflow.com/users/3186', 'pm_score': 2, 'selected': False, 'text': "<blockquote>\n  <p>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?</p>\n</blockquote>\n\n<p><strong>Not that I know of.</strong></p>\n\n<p>Most filters in this list are codecs, so contain both a encoder and decoder.</p>\n\n<p>The filters in the </p>\n\n<pre><code>CLSID_ActiveMovieCategories\n</code></pre>\n\n<p>are wrappers around the VfW filters installed.</p>\n\n<p>(Some software companies create their own categories, so there may be 'non official' categories on some machines)</p>\n\n<p>If you want to see all installed categories, use GraphEdit which is supplied with the DirectShow SDK.</p>\n\n<p>GraphEdit itself is a great tool to see what DirectShow does under the hood. So maybe that may be a source of more information about the filters (and their interactions) on your system.</p>\n"}, {'answer_id': 30676, 'author': 'Christopher', 'author_id': 3186, 'author_profile': 'https://Stackoverflow.com/users/3186', 'pm_score': 1, 'selected': False, 'text': '<p>Another point I forgot.</p>\n\n<p>The Windows Media Foundation is a toolkit for using WMV/WMA. It does not provide all things that DirectShow supports. It is really only a SDK for Windows Media.\nThere are bindings in WMV/WMA to DirectShow, so that you can use WM* files/streams in DirectShow applications.</p>\n'}]
['https://Stackoverflow.com/questions/30539', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/2813/']