設定 Deinterlace 喜好設定
[與此頁面 相關的功能 DirectShow是舊版功能。 它已被 MediaPlayer、 IMFMediaEngine和 Media Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayer、 IMFMediaEngine 和 音訊/視訊擷取 ,而不是 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 版本幾乎完全相同。
若要取得視訊串流的取消交錯功能,請執行下列動作:
- 使用影片串流的描述填入 VMR9VideoDesc 結構。 稍後會提供如何填入此結構的詳細資料。
- 將 結構傳遞至 IVMRDeinterlaceControl9::GetNumberOfDeinterlaceModes 方法。 呼叫 方法兩次。 第一次呼叫會傳回硬體針對指定格式所支援的反交錯模式數目。 配置這個大小的 GUID 陣列,然後再次呼叫 方法,並傳入陣列的位址。 第二個呼叫會以 GUID 填入陣列。 每個 GUID 都會識別一個反交錯模式。
- 若要取得特定模式的上限,請呼叫 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;
}
}
現在,應用程式可以使用下列方法來設定資料流程的反交錯模式:
- SetDeinterlaceMode方法會設定慣用模式。 使用GUID_Null關閉反交錯。
- 如果要求的模式無法使用, SetDeinterlacePrefs 方法會指定行為。
- GetDeinterlaceMode方法會傳回您設定的慣用模式。
- GetActualDeinterlaceMode方法會傳回使用中的實際模式,如果慣用模式無法使用,可能是後援模式。
方法參考頁面會提供詳細資訊。
使用 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.
}
}