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:
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?
To determine what codec was used with a specific file, play the file in the Player, if possible. While the file is playing, right-click the file in the library, and then select Properties. On the File tab, look at the Audio codec and Video codec sections. Use a non-Microsoft codec identification tool.
Type System Information in the Windows 10 search bar and click on the app to launch it. Now, expand the Components section on the left pane. Then expand the Multimedia section. In the Multimedia section, you will find Audio Codecs and Video Codecs.
For built-in support, you'll need the codecs. These aren't included with the latest versions of Windows 10 but must be installed from the Microsoft Store. These codecs are also required for encoding video in HEVC (H. 265) format in applications that use Windows 10's system codecs.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With