Escolhendo um filtro de compactação
[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda fortemente que o novo código use MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation em vez de DirectShow, quando possível. A Microsoft sugere que o código existente que usa as APIs herdadas seja reescrito para usar as novas APIs, se possível.]
Vários tipos de componentes de software podem executar compactação de áudio ou vídeo, como:
- Filtros nativos do DirectShow
- Codecs do VCM (Gerenciador de Compactação de Vídeo)
- Codecs do ACM (Gerenciador de Compactação de Áudio)
- DMOs (Objetos de Mídia) do DirectX
No DirectShow, os codecs VCM são encapsulados pelo Filtro de Compressor AVI e os codecs do ACM são encapsulados pelo Filtro wrapper do ACM. Os DMOs são encapsulados pelo Filtro wrapper de DMO. O enumerador de dispositivo do sistema fornece uma maneira consistente de enumerar e criar qualquer um desses tipos de compressor, sem se preocupar com o modelo subjacente.
Para obter detalhes sobre o enumerador de dispositivo do sistema, consulte Usando o enumerador de dispositivo do sistema. Resumidamente, todos os filtros do DirectShow são classificados por categoria e cada categoria é identificada por um GUID. Para compressores de vídeo, a categoria GUID é CLSID_VideoCompressorCategory. Para compressores de áudio, é CLSID_AudioCompressorCategory. Para enumerar uma categoria específica, o enumerador de dispositivo do sistema cria um objeto enumerador que dá suporte à interface IEnumMoniker . O aplicativo usa essa interface para recuperar monikers de dispositivo, em que cada moniker de dispositivo representa uma instância de um filtro DirectShow. Você pode usar o moniker para criar o filtro ou para obter o nome amigável do dispositivo sem criar o filtro.
Para enumerar os compressores de áudio ou vídeo disponíveis no sistema do usuário, faça o seguinte:
- Chame CoCreateInstance para criar o enumerador de dispositivo do sistema, que tem uma ID de classe de CLSID_SystemDeviceEnum.
- Chame ICreateDevEnum::CreateClassEnumerator com o GUID da categoria de filtro. O método retorna um ponteiro de interface IEnumMoniker .
- Use o método IEnumMoniker::Next para enumerar os monikers do dispositivo. Esse método retorna uma interface IMoniker , que representa o moniker.
Para obter o nome amigável de um moniker, faça o seguinte:
- Chame o método IMoniker::BindToStorage . Esse método retorna um ponteiro de interface IPropertyBag .
- Use o método IPropertyBag::Read para ler a propriedade FriendlyName .
Normalmente, um aplicativo exibe uma lista de compressores para que o usuário possa escolher um. Por exemplo, o código a seguir preenche uma caixa de listagem com os nomes dos compressores de vídeo disponíveis.
void OnInitDialog(HWND hDlg)
{
HRESULT hr;
ICreateDevEnum *pSysDevEnum = NULL;
IEnumMoniker *pEnum = NULL;
IMoniker *pMoniker = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
(void**)&pSysDevEnum);
if (FAILED(hr))
{
// Handle the error.
}
hr = pSysDevEnum->CreateClassEnumerator(
CLSID_VideoCompressorCategory, &pEnum, 0);
if (hr == S_OK) // S_FALSE means nothing in this category.
{
while (S_OK == pEnum->Next(1, &pMoniker, NULL))
{
IPropertyBag *pPropBag = NULL;
pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
(void **)&pPropBag);
VARIANT var;
VariantInit(&var);
hr = pPropBag->Read(L"FriendlyName", &var, 0);
if (SUCCEEDED(hr))
{
LRESULT iSel = AddString(GetDlgItem(hDlg,
IDC_CODEC_LIST), var.bstrVal);
}
VariantClear(&var);
pPropBag->Release();
pMoniker->Release();
}
}
SendDlgItemMessage(hDlg, IDC_CODEC_LIST,
LB_SETCURSEL, 0, 0);
pSysDevEnum->Release();
pEnum->Release();
}
Para criar uma instância de filtro do moniker, chame o método IMoniker::BindToObject . O método retorna um ponteiro IBaseFilter .
IBaseFilter *pFilter = NULL;
hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,
(void**)&pFilter);
if (SUCCEEDED(hr))
{
// Use the filter.
// Remember to release the IBaseFilter interface.
}
Para codecs VCM, cada moniker representa um codec específico, mesmo que todos os codecs sejam encapsulados pelo mesmo filtro de Compactação AVI. Chamar BindToObject cria uma instância desse filtro, inicializada para esse codec. Por esse motivo, você não pode chamar CoCreateInstance diretamente no filtro compactação AVI. Você deve percorrer o enumerador de dispositivo do sistema.
Tópicos relacionados