共用方式為


設定 Deinterlace 喜好設定

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

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

VMR-7 與 VMR-9 之間的交錯行為有一個重要差異。 在圖形硬體不支援進階反交錯的系統上,VMR-7 可以切換回硬體重迭,並指示它使用 BOB 樣式取消交錯。 在此情況下,雖然 VMR 正在報告 30fps,但影片實際上會以每秒 60 次翻轉呈現。

除了使用硬體重迭的 VMR-7 案例之外,反交錯是由 VMR 的混音器執行。 混音器會使用 DirectX 視訊加速 (DXVA) deinterlacing 設備磁碟機介面, (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。 (反交錯之後,畫面播放速率為 doubled.) 否則,請將值設定為 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.
    }
}