5
votes

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

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

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

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:

  1. You can enumerate all the decompressors using DirectShow, but this tells you nothing about the compressors (encoders).
  2. You can enumerate all the Video For Windows components, but you get no indication if these are encoders or decoders.
  3. 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".

Has anyone found a generalizes solution for this problem using any of the Windows APIs? Does the Windows Vista Media Foundation API solve any of these issues?

3

3 Answers

7
votes

This is best handled by DirectShow.

DirectShow is currently a part of the platform 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;
}

The following call enumerates all video compressors to the console :

enumerateDShowFilterList( CLSID_VideoCompressorCategory );

The MSDN page Filter Categories lists all other 'official' categories.

I hope that is a good starting point for you.

2
votes

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?

Not that I know of.

Most filters in this list are codecs, so contain both a encoder and decoder.

The filters in the

CLSID_ActiveMovieCategories

are wrappers around the VfW filters installed.

(Some software companies create their own categories, so there may be 'non official' categories on some machines)

If you want to see all installed categories, use GraphEdit which is supplied with the DirectShow SDK.

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.

1
votes

Another point I forgot.

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. There are bindings in WMV/WMA to DirectShow, so that you can use WM* files/streams in DirectShow applications.