共用方式為


設定 Deinterlace 喜好設定

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

影片混合轉譯器 (VMR) 支援硬體加速的反交錯,可改善交錯視訊的轉譯品質。 可用的確切功能取決於基礎硬體。 應用程式可以查詢硬體去交錯功能,並透過 IVMRDeinterlaceControl 介面 (VMR-7)或 IVMRDeinterlaceControl9 介面 (VMR-9)來設定去交錯偏好設定。 反交錯處理是依據每個數據流來執行。

VMR-7 與 VMR-9 之間的交錯行為有一個重要差異。 在圖形硬體不支援進階反交錯的系統上,VMR-7 可以退回到硬體覆疊,並指示其使用 BOB 樣式的反交錯。 在此情況下,雖然 VMR 報告每秒 30 帧,但影片實際上以每秒 60 帧的速度渲染。

除了在使用硬體覆蓋的 VMR-7 案例中,去隔行處理是由 VMR 混音器執行。 混音器會使用 DirectX 影片加速 (DXVA) 去交錯裝置驅動程式介面 (DDI) 來進行去交錯處理。 應用程式無法呼叫此 DDI,而且應用程式無法取代 VMR 的解交功能。 不過,應用程式可以選取所需的反交錯模式,如本節所述。

注意

本節描述 IVMRDeinterlaceControl9 方法,但 VMR-7 版本幾乎完全相同。

 

若要取得視訊數據流的解交功能,請執行下列動作:

  1. 將影片串流的描述填入 VMR9VideoDesc 結構中。 稍後會提供如何填入此結構的詳細數據。
  2. 將結構傳遞至 IVMRDeinterlaceControl9::GetNumberOfDeinterlaceModes 方法。 方法呼叫兩次。 第一個呼叫會傳回硬體針對指定格式所支援之去交錯模式的數目。 配置一個此大小的 GUID 陣列,然後再次呼叫該方法,並傳入陣列位址。 第二個呼叫會以 GUID 填入陣列。 每個 GUID 都會標識一個解交錯模式。
  3. 若要取得特定模式的功能,請呼叫 IVMRDeinterlaceControl9::GetDeinterlaceModeCaps 方法。 傳入相同的 VMR9VideoDesc 結構,以及陣列中的其中一個 GUID。 方法會將模式功能資料填入 VMR9DeinterlaceCaps 結構中。

下列程式代碼顯示下列步驟:

VMR9VideoDesc VideoDesc; 
DWORD dwNumModes = 0;
// Fill in the VideoDesc structure (not shown).
hr = pDeinterlace->GetNumberOfDeinterlaceModes(&VideoDesc, 
    &dwNumModes, NULL);
if (SUCCEEDED(hr) && (dwNumModes != 0))
{
    // Allocate an array for the GUIDs that identify the modes.
    GUID *pModes = new GUID[dwNumModes];
    if (pModes)
    {
        // Fill the array.
        hr = pDeinterlace->GetNumberOfDeinterlaceModes(&VideoDesc, 
            &dwNumModes, pModes);
        if (SUCCEEDED(hr))
        {
            // Loop through each item and get the capabilities.
            for (int i = 0; i < dwNumModes; i++)
            {
                VMR9DeinterlaceCaps Caps;
                hr = pDeinterlace->GetDeinterlaceModeCaps(pModes + i, 
                    &VideoDesc, &Caps);
                if (SUCCEEDED(hr))
                {
                    // Examine the Caps structure.
                }
            }
        }
        delete [] pModes;
    }
}

現在,應用程式可以使用下列方法來設定資料流的解交模式:

方法參考頁面會提供詳細資訊。

使用 VMR9VideoDesc 結構

在先前指定的程式中,第一個步驟是填入 VMR9VideoDesc 結構,並說明視訊串流。 從取得視訊數據流的媒體類型開始。 您可以在 VMR 過濾器的輸入引腳上呼叫 IPin::ConnectionMediaType 來執行此動作。 然後確認視訊串流是否交錯。 只有 VIDEOINFOHEADER2 格式可以交錯。 如果格式類型是FORMAT_VideoInfo,它必須是漸進式框架。 如果格式類型為FORMAT_VideoInfo2,請檢查 dwInterlaceFlags 字段是否有AMINTERLACE_IsInterlaced旗標。 此旗標的存在表示影片是交錯的。

假設 pBMI 變數 是格式區塊中 BITMAPINFOHEADER 結構的指標。 在 VMR9VideoDesc 結構中設定下列值:

  • dwSize:將此欄位設定為 sizeof(VMR9VideoDesc)

  • dwSampleWidth:將此字段設定為 pBMI->biWidth

  • dwSampleHeight:將此字段設定為 abs(pBMI->biHeight)

  • SampleFormat:此字段描述媒體類型的交錯特性。 檢查 VIDEOINFOHEADER2 結構中的 dwInterlaceFlags 欄位,並將 SampleFormat 設定為相等 VMR9_SampleFormat 旗標。 以下提供執行這項作的協助程式函式。

  • InputSampleFreq:此字段會提供輸入頻率,可從 VIDEOINFOHEADER2 結構中的 AvgTimePerFrame 字段計算。 在一般情況下,將 dwNumerator 設為 10000000,並將 dwDenominator 設定為 AvgTimePerFrame。 不過,您也可以檢查一些已知的幀速率:

    每個畫面的平均時間 幀速率 (fps) 分子 分母
    166833 59.94 (NTSC) 60000 1001
    333667 29.97 (NTSC) 30000 1001
    417188 23.97 (NTSC) 24000 1001
    200000 50.00 (PAL) 50 1
    400000 25.00 (PAL) 25 1
    416667 24.00 (電影) 24 1

     

  • OutputFrameFreq:此欄位提供輸出頻率,可從 InputSampleFreq 值和輸入數據流交錯特性計算:

    • OutputFrameFreq.dwDenominator 設為等於 InputSampleFreq.dwDenominator
    • 如果輸入視訊交錯,請將 outputFrameFreq.dwNumerator 設為 2 x InputSampleFreq.dwNumerator。 (去隔行後,幀率翻倍。否則,請將值設定為 InputSampleFreq.dwNumerator
  • dwFourCC:將此欄位設定為 pBMI->biCompression

下列協助程式函式會將AMINTERLACE_X 旗標轉換成 VMR9_SampleFormat 值:

#define IsInterlaced(x) ((x) & AMINTERLACE_IsInterlaced)
#define IsSingleField(x) ((x) & AMINTERLACE_1FieldPerSample)
#define IsField1First(x) ((x) & AMINTERLACE_Field1First)

VMR9_SampleFormat ConvertInterlaceFlags(DWORD dwInterlaceFlags)
{
    if (IsInterlaced(dwInterlaceFlags)) {
        if (IsSingleField(dwInterlaceFlags)) {
            if (IsField1First(dwInterlaceFlags)) {
                return VMR9_SampleFieldSingleEven;
            }
            else {
                return VMR9_SampleFieldSingleOdd;
            }
        }
        else {
            if (IsField1First(dwInterlaceFlags)) {
                return VMR9_SampleFieldInterleavedEvenFirst;
             }
            else {
                return VMR9_SampleFieldInterleavedOddFirst;
            }
        }
    }
    else {
        return VMR9_SampleProgressiveFrame;  // Not interlaced.
    }
}