共用方式為


選擇壓縮篩選

[與此頁面相關的功能 DirectShow是舊版功能。 它已被 MediaPlayerIMFMediaEngineMedia Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayerIMFMediaEngine音訊/視訊擷取 ,而不是 DirectShow。 Microsoft 建議使用舊版 API 的現有程式碼盡可能重寫為使用新的 API。

數種類型的軟體元件可以執行視訊或音訊壓縮,例如:

  • 原生 DirectShow 篩選準則
  • 影片壓縮管理員 (VCM) 編解碼器
  • 音訊壓縮管理員 (ACM) 編解碼器
  • DirectX 媒體物件 (DMO)

在 DirectShow 中,VCM 編解碼器會由 AVI 壓接器篩選包裝,而 ACM 編解碼器會由 ACM 包裝函式篩選包裝。 DMO 包裝函式篩選條件會包裝 DMO。 系統裝置列舉值提供一致的方式來列舉和建立上述任何一種冰箱類型,而不必擔心基礎模型。

如需系統裝置列舉值的詳細資訊,請參閱 使用系統裝置列舉值。 簡單來說,所有 DirectShow 篩選都會依類別分類,而且每個類別都是以 GUID 來識別。 對於視訊壓縮程式,類別 GUID 會CLSID_VideoCompressorCategory。 針對音訊壓縮器,它會CLSID_AudioCompressorCategory。 若要列舉特定類別,系統裝置列舉值會建立支援IEnumMoniker介面的列舉值物件。 應用程式會使用此介面來擷取裝置 Monikers,其中每個裝置 Moniker 都代表 DirectShow 篩選準則的實例。 您可以使用 Moniker 來建立篩選,或取得裝置的易記名稱,而不需建立篩選。

若要列舉使用者系統上可用的視訊或音訊壓縮器,請執行下列動作:

  1. 呼叫 CoCreateInstance 以建立系統裝置列舉值,其類別識別碼為 CLSID_SystemDeviceEnum。
  2. 使用篩選類別 GUID 呼叫 ICreateDevEnum::CreateClassEnumerator 。 方法會傳回 IEnumMoniker 介面指標。
  3. 使用 IEnumMoniker::Next 方法來列舉裝置 Monikers。 這個方法會傳回 代表 Moniker 的 IMoniker 介面。

若要從 Moniker 取得易記名稱,請執行下列動作:

  1. 呼叫 IMoniker::BindToStorage 方法。 這個方法會傳回 IPropertyBag 介面指標。
  2. 使用 IPropertyBag::Read 方法來讀取 FriendlyName 屬性。

一般而言,應用程式會顯示一份冰箱清單,讓使用者可以選擇一個。 例如,下列程式碼會填入清單方塊,其中包含可用視訊壓縮器的名稱。

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

若要從 Moniker 建立篩選實例,請呼叫 IMoniker::BindToObject 方法。 方法會傳回 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.
}

針對 VCM 編解碼器,每個 Moniker 都代表一個特定的編解碼器,即使所有編解碼器都會以相同的 AVI 壓縮篩選器包裝。 呼叫 BindToObject 會建立此篩選的實例,針對該編解碼器初始化。 基於這個理由,您無法直接在 AVI 壓縮篩選器上呼叫 CoCreateInstance 。 您必須通過系統裝置列舉值。

重新壓縮 AVI 檔案