Compartir a través de


Elección de un filtro de compresión

[La característica asociada a esta página, DirectShow, es una característica heredada. Se ha reemplazado por MediaPlayer, IMFMediaEngine y Captura de audio/vídeo en Media Foundation. Esas características se han optimizado para Windows 10 y Windows 11. Microsoft recomienda encarecidamente que el nuevo código use MediaPlayer, IMFMediaEngine y Audio/Video Capture en Media Foundation en lugar de DirectShow, siempre que sea posible. Microsoft sugiere que el código existente que usa las API heredadas se reescriba para usar las nuevas API si es posible.

Varios tipos de componentes de software pueden realizar compresión de audio o vídeo, como:

  • Filtros directShow nativos
  • Códecs del Administrador de compresión de vídeo (VCM)
  • Códecs del Administrador de compresión de audio (ACM)
  • Objetos multimedia de DirectX (DPO)

En DirectShow, los códecs VCM se encapsulan mediante el filtro de compresor AVI y los códecs ACM se encapsulan mediante el filtro contenedor de ACM. Las DPO se encapsulan mediante el filtro contenedor DMO. El enumerador de dispositivos del sistema proporciona una manera coherente de enumerar y crear cualquiera de estos tipos de compresor, sin preocuparse por el modelo subyacente.

Para obtener más información sobre el enumerador de dispositivos del sistema, consulte Uso del enumerador de dispositivos del sistema. Brevemente, todos los filtros directShow se clasifican por categoría y cada categoría se identifica mediante un GUID. En el caso de los compresores de vídeo, el GUID de categoría es CLSID_VideoCompressorCategory. Para compresores de audio, es CLSID_AudioCompressorCategory. Para enumerar una categoría determinada, el enumerador de dispositivos del sistema crea un objeto enumerador que admite la interfaz IEnumMoniker . La aplicación usa esta interfaz para recuperar monikers de dispositivo, donde cada moniker de dispositivo representa una instancia de un filtro DirectShow. Puede usar el moniker para crear el filtro o para obtener el nombre descriptivo del dispositivo sin crear el filtro.

Para enumerar los compresores de audio o vídeo disponibles en el sistema del usuario, haga lo siguiente:

  1. Llame a CoCreateInstance para crear el enumerador de dispositivos del sistema, que tiene un identificador de clase de CLSID_SystemDeviceEnum.
  2. Llame a ICreateDevEnum::CreateClassEnumerator con el GUID de categoría de filtro. El método devuelve un puntero de interfaz IEnumMoniker .
  3. Use el método IEnumMoniker::Next para enumerar los monikers del dispositivo. Este método devuelve una interfaz IMoniker , que representa el moniker.

Para obtener el nombre descriptivo de un moniker, haga lo siguiente:

  1. Llame al método IMoniker::BindToStorage . Este método devuelve un puntero de interfaz IPropertyBag .
  2. Use el método IPropertyBag::Read para leer la propiedad FriendlyName .

Normalmente, una aplicación mostraría una lista de compresores para que el usuario pudiera elegir una. Por ejemplo, el código siguiente rellena un cuadro de lista con los nombres de los compresores de vídeo disponibles.

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 crear una instancia de filtro desde el moniker, llame al método IMoniker::BindToObject . El método devuelve un puntero 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 los códecs VCM, cada moniker representa un códec determinado, aunque todos los códecs estén encapsulados por el mismo filtro de compresión AVI. Al llamar a BindToObject , se crea una instancia de este filtro, inicializada para ese códec. Por este motivo, no puede llamar a CoCreateInstance directamente en el filtro de compresión AVI. Debe recorrer el enumerador de dispositivos del sistema.

Recompresión de un archivo AVI