共用方式為


設定視訊壓縮屬性

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

視訊壓縮篩選器可以支援其輸出針腳上的 IAMVideoCompression 介面。 使用此介面可設定壓縮屬性,例如主要畫面格速率、每個主要畫面格的預測 (P) 畫面數,以及相對壓縮品質。

首先,呼叫 IBaseFilter::EnumPins 方法來尋找篩選的輸出釘選,並查詢介面的針腳。 某些篩選完全不支援 介面。 其他人可能會公開 介面,但不支援每個壓縮屬性。 若要判斷支援哪些屬性,請呼叫 IAMVideoCompression::GetInfo。 此方法會傳回數項資訊:

  • 一組功能旗標
  • 描述性字串和版本號碼字串
  • 支援) 時,主要畫面播放速率、P 畫面播放速率和品質 (的預設值

方法具有下列語法:

hr = pCompress->GetInfo(pszVersion, &cbVersion, pszDesc, &cbDesc, 
         &lKeyFrame, &lPFrame, &dblQuality, &lCap);

pszVersionpszDesc參數是接收版本字串和描述字串的寬字元緩衝區。 cbVersioncbDesc參數會接收所需的緩衝區大小,以位元組為單位, (不是字元) 。 lKeyFramelPFramedblQuality參數會接收主要畫面播放速率、P 畫面播放速率和品質的預設值。 品質會以從 0.0 到 1.0 的浮點數表示。 lCap參數會接收由CompressionCaps列舉類型所定義的功能旗標位OR

任何這些參數可以是 Null,在此情況下,方法會忽略該參數。 例如,若要配置版本和描述字串的緩衝區,請先在第一個和第三個參數中使用 Null 呼叫 方法。 使用 cbVersioncbDesc 的傳回值來配置緩衝區,然後再次呼叫 方法:

int cbVersion, cbDesc; // Size in bytes, not characters!
hr = pCompress->GetInfo(0, &cbVersion, 0, &cbDesc, 0, 0, 0, 0);
if (SUCCEEDED(hr))
{
    WCHAR *pszVersion = new WCHAR[cbVersion/2]; // Wide character = 2 bytes
    WCHAR *pszDesc = new WCHAR[cbDesc/2];
    hr = pCompress->GetInfo(pszVersion, 0, pszDesc, 0, 0, 0, 0, 0);
}

lCap的值表示篩選支援的其他IAMVideoCompression方法之哪一種。 例如,如果 lCap 包含CompressionCaps_CanKeyFrame旗標,您可以呼叫 IAMVideoCompression::get_KeyFrameRate 以取得主要畫面播放速率和 IAMVideoCompression::p ut_KeyFrameRate 來設定主要畫面播放速率。 負值表示篩選會使用預設值,如從 IAMVideoCompression::GetInfo取得。 例如:

if (lCap & CompressionCaps_CanKeyFrame)
{
    hr = pCompress->get_KeyFrameRate(&lKeyFrame);
    if (FAILED(hr) || lKeyFrame < 0)
    {
        lKeyFrame = lDefaultKeyFrame; // From GetInfo.
    }
}

下列程式碼範例會嘗試在輸出釘選上尋找 IAMVideoCompression 介面。 如果成功,它會擷取壓縮屬性的預設值和實際值:

HRESULT hr = E_FAIL;
IEnumPins *pEnum = NULL;
IPin *pPin = NULL;
IAMVideoCompression *pCompress = NULL;

// Find the pin that supports IAMVideoCompression (if any).
pFilter->EnumPins(&pEnum);
while (S_OK == pEnum->Next(1, &pPin, NULL))
{
    hr = pPin->QueryInterface(IID_IAMVideoCompression, (void**)&pCompress);
    pPin->Release();
    if (SUCCEEDED(hr)) // Found the interface.
    {
        break;
    }
}
if (SUCCEEDED(hr)) 
{
    long lCap;                     // Capability flags
    long lKeyFrame, lPFrame;       // Real values
    double m_Quality;
    long lKeyFrameDef, lPFrameDef; // Default values
    double QualityDef;
    
    // Get default values and capabilities.
    hr = pCompress->GetInfo(0, 0, 0, 0, &KeyFrameDef, &lPFrameDef,
             &QualityDef, &lCap);
    if (SUCCEEDED(hr))
    {
        // Get actual values where possible.
        if (lCap & CompressionCaps_CanKeyFrame)
        {
            hr = pCompress->get_KeyFrameRate(&lKeyFrame);
            if (FAILED(hr) || lKeyFrame < 0)
                lKeyFrame = lKeyFrameDef;
        }
        if (lCap & CompressionCaps_CanBFrame)
        {
            hr = pCompress->get_PFramesPerKeyFrame(&lPFrame);
            if (FAILED(hr) || lPFrame < 0)
                lPFrame = lPFrameDef;
        }
        if (lCap & CompressionCaps_CanQuality)
        {
            hr = pCompress->get_Quality(&Quality);
            if (FAILED(hr) || Quality < 0)
                Quality = QualityDef;
        }
    }
}

注意

如果您使用ICaptureGraphBuilder2介面來建置圖形,您可以呼叫ICaptureGraphBuilder2::FindInterface來取得IAMVideoCompression介面,而不是使用IBaseFilter::EnumPinsFindInterface方法是協助程式方法,可搜尋圖形中指定介面的篩選和釘選。