Лучший способ перечислить все доступные видеокодеки в Windows? - PullRequest
5 голосов
/ 27 августа 2008

Я ищу хороший способ перечислить все видеокодеки на компьютере с 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. Вы можете перечислить все компоненты «Видео для Windows», но не можете указать, являются ли они кодерами или декодерами.
  3. Существуют фильтры DirectShow, которые могут отлично выполнять эту работу (например, фильтр Motion JPEG), но нет никаких признаков того, что определенный фильтр DirectShow является «видеодекодером».

Кто-нибудь нашел обобщающее решение для этой проблемы с использованием любого из API Windows? Решает ли Windows Vista Media Foundation API какие-либо из этих проблем?

Ответы [ 3 ]

7 голосов
/ 27 августа 2008

Это лучше всего обрабатывается 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 Категории фильтров перечислены все другие «официальные» категории.

Надеюсь, это хорошая отправная точка для вас.

2 голосов
/ 27 августа 2008

Ответ выше не учитывает декомпрессоры. Не существует CLSID_VideoDecompressorCategory. Есть ли способ спросить фильтр, если это видео декомпрессор?

Не то, что я знаю.

Большинство фильтров в этом списке являются кодеками, поэтому содержат кодер и декодер.

Фильтры в

CLSID_ActiveMovieCategories

- оболочки вокруг установленных фильтров VfW.

(Некоторые компании-разработчики создают свои собственные категории, поэтому на некоторых машинах могут быть категории «неофициальные»)

Если вы хотите просмотреть все установленные категории, используйте GraphEdit, который поставляется вместе с DirectShow SDK.

Сам GraphEdit - отличный инструмент, чтобы увидеть, что DirectShow делает изнутри. Так что, возможно, это может быть источником дополнительной информации о фильтрах (и их взаимодействиях) в вашей системе.

1 голос
/ 27 августа 2008

Еще один момент, который я забыл.

Windows Media Foundation - это инструментарий для использования WMV / WMA. Он не предоставляет все, что поддерживает DirectShow. Это действительно только SDK для Windows Media. В WMV / WMA есть привязки к DirectShow, так что вы можете использовать файлы WM * в потоковых приложениях DirectShow.

...