Scelta di un filtro di compressione

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice usi MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation invece di DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.

Diversi tipi di componenti software possono eseguire la compressione video o audio, ad esempio:

  • Filtri DirectShow nativi
  • Codec di Gestione compressione video (VCM)
  • Codec ACM (Audio Compression Manager)
  • Oggetti multimediali DirectX (DMO)

In DirectShow, i codec VCM vengono inclusi nel filtro compressore AVI e i codec ACM vengono inclusi nel filtro wrapper ACM. Le DMO vengono incapsulate dal filtro wrapper DMO. L'enumeratore di dispositivi di sistema offre un modo coerente per enumerare e creare uno di questi tipi di compressore, senza doversi preoccupare del modello sottostante.

Per informazioni dettagliate sull'enumeratore del dispositivo di sistema, vedere Uso dell'enumeratore del dispositivo di sistema. Brevemente, tutti i filtri DirectShow vengono classificati per categoria e ogni categoria è identificata da un GUID. Per i compressori video, il GUID della categoria è CLSID_VideoCompressorCategory. Per i compressori audio, è CLSID_AudioCompressorCategory. Per enumerare una determinata categoria, l'enumeratore del dispositivo di sistema crea un oggetto enumeratore che supporta l'interfaccia IEnumMoniker . L'applicazione usa questa interfaccia per recuperare i moniker del dispositivo, in cui ogni moniker del dispositivo rappresenta un'istanza di un filtro DirectShow. È possibile usare il moniker per creare il filtro o ottenere il nome descrittivo del dispositivo senza creare il filtro.

Per enumerare i compressori audio o video disponibili nel sistema dell'utente, eseguire le operazioni seguenti:

  1. Chiamare CoCreateInstance per creare l'enumeratore del dispositivo di sistema, che ha un ID classe di CLSID_SystemDeviceEnum.
  2. Chiamare ICreateDevEnum::CreateClassEnumerator con il GUID della categoria di filtro. Il metodo restituisce un puntatore all'interfaccia IEnumMoniker .
  3. Usare il metodo IEnumMoniker::Next per enumerare i moniker del dispositivo. Questo metodo restituisce un'interfaccia IMoniker , che rappresenta il moniker.

Per ottenere il nome descrittivo da un moniker, eseguire le operazioni seguenti:

  1. Chiamare il metodo IMoniker::BindToStorage . Questo metodo restituisce un puntatore all'interfaccia IPropertyBag .
  2. Utilizzare il metodo IPropertyBag::Read per leggere la proprietà FriendlyName .

In genere, un'applicazione visualizza un elenco di compressori, in modo che l'utente possa sceglierne uno. Ad esempio, il codice seguente popola una casella di riepilogo con i nomi dei compressori video disponibili.

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();
}

Per creare un'istanza di filtro dal moniker, chiamare il metodo IMoniker::BindToObject . Il metodo restituisce un puntatore 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.
}

Per i codec VCM, ogni moniker rappresenta un codec specifico, anche se tutti i codec sono inclusi nello stesso filtro di compressione AVI. La chiamata a BindToObject crea un'istanza di questo filtro, inizializzata per tale codec. Per questo motivo, non è possibile chiamare CoCreateInstance direttamente nel filtro di compressione AVI. È necessario passare attraverso l'enumeratore del dispositivo di sistema.

Ricompressione di un file AVI