啟用 DirectX 視訊加速

本節說明如何在自訂播放程式中播放串流內容時啟用 Microsoft® DirectX® 影片加速。

背景

DirectX 影片加速 (DirectX VA) 是 2D 解碼作業硬體加速的 API 規格。 它可讓軟體解碼器將特定 CPU 密集作業卸載至圖形卡進行處理。 對於終端使用者,這可讓高位元速率視訊,例如在配備 DirectX VA 相容圖形卡的舊版電腦上播放全螢幕 DVD。

從Windows媒體格式 9 系列 SDK 開始,DMO包裝函式篩選器支援 DirectX VA。 這表示,針對本機播放,應用程式可以使用 WM ASF 讀取器篩選來播放Windows媒體型內容,如果圖形卡支援,則會自動叫用 DirectX VA 硬體加速。 不過,WM ASF 讀取器篩選不支援串流內容的播放。 因此,如果您想要在自訂播放機中播放串流內容時支援 DirectX VA,您必須使用替代機制,這是從 Windows Media 9 系列開始Windows 媒體播放機所使用的替代機制。

因為Windows 媒體播放機是在開發 QASF 篩選之前設計,所以Windows 媒體播放機有自己的來源篩選,以根據媒體格式 SDK Windows播放Windows媒體型內容。 WMP Windows媒體來源篩選會將解壓縮的資料直接傳遞至音訊和視訊轉譯器。 相反地,WM ASF 讀取器會將壓縮的內容傳遞給Windows媒體解碼器 DirectX 媒體物件 (DMO) ,這些物件裝載于DMO包裝函式內。 下圖說明 WM ASF 讀取器和 WMP Windows媒體來源篩選之間的差異。

custom source filter outputs uncompressed samples

qasf source filter outputs compressed samples

若要啟用串流內容的 DirectX VA,您必須建立自訂來源篩選準則,例如頂端圖表中的自訂來源篩選準則。 基本上,此篩選會使用 Windows 媒體格式 SDK 來具現化 WM 讀取器物件、解壓縮範例,並在輸出針腳上將其下游傳送。 此討論假設您已建立來源篩選,現在已準備好實作 DirectX VA 支援。

若要啟用 DirectX VA,來源篩選的基本工作是提供影片轉譯器和 WMV 解碼器,DMO它們需要交涉 DirectX VA 連線的介面。 來源篩選不會參與這些交涉。 串流啟動之後,來源篩選可以執行的唯一 DirectX VA 相關工作是在 WMV 解碼器將時間戳記傳遞給影片轉譯器之前,修改影片範例上的時間戳記。 這樣做的主要原因是提供超出標準 DirectShow® 介面啟用的自訂時間軸控制項。

定義了三個介面,以啟用Windows媒體格式 SDK、播放機的來源篩選、Windows媒體視訊解碼器DMO,以及重迭Mixer或視訊混合轉譯器之間的必要通訊。 下表說明這些介面。

介面 描述
IWMCodecAMVideoAccelerator 由Windows媒體解碼器DMO公開,並由媒體播放機的來源篩選器呼叫,以設定啟用 DirectX VA 以解碼Windows媒體視訊內容所需的各種連線。
IWMPlayerTimestampHook 在玩家的來源篩選上實作。 它可讓篩選準則先修改影片範例上的時間戳記,再將其傳遞給下游。
IWMReaderAccelerator 在 WM Reader 物件上實作。 播放機來源篩選會呼叫它,以從解碼器DMO取得介面。

 

啟用 DirectX VA 的播放作業順序

本節說明啟用 DirectX VA 的播放機及其來源篩選的執行時間作業一般順序。 本節所參考的元件如下:

  • 協力廠商媒體播放機,稱為播放機。
  • 由播放機具現化的自訂來源篩選,會使用 Windows Media Format SDK 來解壓縮Windows媒體型內容。
  • 播放程式來源篩選的視訊輸出釘選,稱為輸出釘選。
  • DirectShow 視訊播放篩選圖表,稱為圖表。
  • 影片混合轉譯器,稱為 VMR。
  • Windows媒體格式 SDK 非同步讀取器物件,稱為讀取器。
  • Windows媒體視訊解碼器 DirectX 媒體物件,稱為解碼器DMO。

作業順序如下:

  1. 玩家會具現化其來源篩選和讀取器物件。 讀取器會建立影片解碼器DMO,並在其上設定壓縮) 輸入類型的 (。 這必須在播放程式嘗試設定其視訊播放圖表之前發生,因為 SDK 和解碼器DMO必須涉及與圖形的交涉程式,而DMO必須在步驟 9 期間知道輸入格式。
  2. 播放機會呼叫 IGraphBuilder::Render,並提供視訊來源篩選的輸出釘選。 此時,DirectShow 篩選圖表管理員會嘗試將 VMR 連線到播放機的視訊來源篩選。
  3. 篩選圖形管理員會在播放程式視訊來源篩選的輸出釘選上呼叫IPin::連線

步驟 4 到 10 發生在IPin::連線內。

  1. 來源篩選器會從讀取器的IWMReaderAccelerator::GetCodecInterface方法取得IWMCodecAMVideoAccelerator介面。 如果編解碼器不支援 DirectX VA, 對 GetCodecInterface 的呼叫可能會失敗。 在此情況下,交涉會如往常一樣繼續,而不需要 DirectX VA 支援。

  2. 來源篩選會透過IWMCodecAMVideoAccelerator::SetAcceleratorInterface,從傳入連線的針腳將IAMVideoAccelerator指標傳遞至解碼器DMO。

  3. 然後,來源篩選會將IPin::連線作業的其餘部分委派給CBaseOutputPin::連線方法。 SDK 的格式列舉會像今天一樣繼續進行。 如果編解碼器支援 DirectX VA 進行連線的內容,則編解碼器DMO先呈現這些 DirectX VA 子類型,再支援 YUV 和 RGB 類型。 如果 DirectX VA 支援可供使用,則會在 DirectX VA 子類型的內容中嘗試步驟 7 到 11。 下列程式碼片段示範如何識別 DirectX VA 媒體子類型。

    bool IsDXVASubtype( AM_MEDIA_TYPE * pmt )
    {
        // All DXVA types have the same last 3 DWORDs.
        // guidDXVA is the base GUID for all DXVA subtypes.
    
        GUID guidDXVA = { 0x00000000, 0xa0c7, 0x11d3, { 0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5 } };
    
        unsigned long const * plguid;
        unsigned long const * plguidDXVA;
        plguid = (unsigned long const *)&pmt->subtype;
        plguidDXVA = (unsigned long *)&guidDXVA;
    
        if( ( plguid[1] == plguidDXVA[1] ) &&
            ( plguid[2] == plguidDXVA[2] ) &&
            ( plguid[3] == plguidDXVA[3] ) )
        {
            return true;
        }
    
        return false;
    }
    
    
  4. CBaseOutputPin::連線實作會在步驟 3 期間呼叫IPin::CompleteConnect。 如果考慮 DirectX VA 子類型,則會嘗試 DirectX VA 交涉。 輸出針腳會呼叫 IWMCodecAMVideoAccelerator::NegotiateConnection,並傳遞目前的輸出媒體類型。

  5. 解碼器DMO透過IAMVideoAccelerator介面執行與 VMR 的必要交涉,並傳回兩者已同意的視訊子類型 GUID。 輸出針腳會將此程式期間收到的所有IAMVideoAcceleratorNotify呼叫委派給解碼器DMO的IAMVideoAcceleratorNotify介面,也可以透過IWMReaderAccelerator::GetCodecInterface方法取得。

  6. 如果 NegotiateConnection 成功,輸出針腳會呼叫 IWMCodecAMVideoAccelerator::SetPlayerNotifyIWMPlayerTimestampHook 介面。 此勾點可讓來源篩選準則更新樣本上的時間戳記,再將時間戳記交給轉譯器。

  7. 來源篩選會使用交涉媒體類型呼叫 IWMReaderAccelerator::Notify 。 這可讓讀取器更新其內部變數,並認可至 DirectX VA。 這是編解碼器或讀取器可以失敗的最後一個位置。 如果上述任何步驟失敗,來源篩選應該會返回步驟 3,然後嘗試讀取器列舉的下一個類型。

  8. 播放會啟動。 如果連接輸出類型為 DirectX VA,讀取器會忽略解碼器的輸出緩衝區DMO。

  9. 發生 IPin::D isconnect時,來源篩選會使用Null呼叫IWMCodecAMVideoAccelerator::SetAcceleratorInterface。 這會中斷編解碼器與轉譯器之間的 DirectX VA 連線。

讀取 ASF 檔案