共用方式為


建立Kernel-Mode篩選

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

某些核心模式篩選無法透過 CoCreateInstance建立,因此沒有 CLSID。 這些篩選包括 Tee/Sink 對接收轉換器CC 解碼器 篩選和 WST 編解碼器 篩選。 若要建立其中一個篩選準則,請使用 系統裝置列舉值 物件,然後依篩選的名稱搜尋。

  1. 建立系統裝置列舉值。
  2. 使用該篩選之篩選類別的 CLSID 呼叫 ICreateDevEnum::CreateClassEnumerator 方法。 這個方法會建立篩選類別的列舉值。 (列舉值 只是傳回其他物件清單的物件,使用定義的 COM 介面。) 列舉值會傳回 IMoniker 指標,代表該類別中的篩選。
  3. 針對每個 Moniker,呼叫 IMoniker::BindToStorage 以取得 IPropertyBag 介面。
  4. 呼叫 IPropertyBag::Read 以取得篩選的名稱。
  5. 如果名稱相符,請呼叫 IMoniker::BindToObject 來建立篩選。

下列程式碼顯示執行下列步驟的函式:

HRESULT CreateKernelFilter(
    const GUID &guidCategory,  // Filter category.
    LPCOLESTR szName,          // The name of the filter.
    IBaseFilter **ppFilter     // Receives a pointer to the filter.
)
{
    HRESULT hr;
    ICreateDevEnum *pDevEnum = NULL;
    IEnumMoniker *pEnum = NULL;
    if (!szName || !ppFilter) 
    {
        return E_POINTER;
    }

    // Create the system device enumerator.
    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
        IID_ICreateDevEnum, (void**)&pDevEnum);
    if (FAILED(hr))
    {
        return hr;
    }

    // Create a class enumerator for the specified category.
    hr = pDevEnum->CreateClassEnumerator(guidCategory, &pEnum, 0);
    pDevEnum->Release();
    if (hr != S_OK) // S_FALSE means the category is empty.
    {
        return E_FAIL;
    }

    // Enumerate devices within this category.
    bool bFound = false;
    IMoniker *pMoniker;
    while (!bFound && (S_OK == pEnum->Next(1, &pMoniker, 0)))
    {
        IPropertyBag *pBag = NULL;
        hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
        if (FAILED(hr))
        {
            pMoniker->Release();
            continue; // Maybe the next one will work.
        }
        // Check the friendly name.
        VARIANT var;
        VariantInit(&var);
        hr = pBag->Read(L"FriendlyName", &var, NULL);
        if (SUCCEEDED(hr) && (lstrcmpiW(var.bstrVal, szName) == 0))
        {
            // This is the right filter.
            hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter,
                (void**)ppFilter);
            bFound = true;
        }
        VariantClear(&var);
        pBag->Release();
        pMoniker->Release();
    }
    pEnum->Release();
    return (bFound ? hr : E_FAIL);
}

下列程式碼範例會使用此函式來建立 CC 解碼器篩選,並將它新增至篩選圖形:

IBaseFilter *pCC = NULL;
hr = CreateKernelFilter(AM_KSCATEGORY_VBICODEC, 
    OLESTR("CC Decoder"), &pCC);
if (SUCCEEDED(hr))
{
    hr = pGraph->AddFilter(pCC, L"CC Decoder");
    pCC->Release();
}

進階擷取主題

使用系統裝置列舉值