解碼器如何使用 IAMVideoAccelerator
[與此頁面相關的功能 DirectShow是舊版功能。 它已被 MediaPlayer、 IMFMediaEngine和 Media Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayer、 IMFMediaEngine 和 音訊/視訊擷取 ,而不是 DirectShow。 Microsoft 建議使用舊版 API 的現有程式碼盡可能重寫為使用新的 API。
IAMVideoAccelerator介面可啟用一般影片加速作業,包括 DirectX 影片加速 (VA) 。 針對非 DirectX VA 加速,解碼器和視訊驅動程式必須同時遵守通用通訊協定。
本節說明使用這個介面時,任何解碼器都應該遵循的作業一般順序。 如需 DirectX VA 型解碼器特有的進一步資訊,請參閱 將 DirectX 影片加速對應至 IAMVideoAccelerator。
注意
此介面適用于 Windows 2000 和更新版本。
IAMVideoAccelerator介面會在重迭混音器或視訊混合轉譯器 (VMR) 的輸入針腳上公開。 IAMVideoAcceleratorNotify介面會在解碼器的輸出針腳上公開。 連接篩選針腳的事件順序如下所示:
篩選圖形管理員會在解碼器篩選的輸出針腳上呼叫 IPin::Connect 。 AM_MEDIA_TYPE是選擇性參數。
- AM_MEDIA_TYPE 是描述媒體類型的資料結構。 它包含主要類型 GUID (,在我們的案例中應該MEDIATYPE_Video) 、子類型 GUID (,在我們的案例中應該是視訊加速器 GUID) ,以及各種其他專案。 其中一項是格式類型 GUID,其中包含媒體的相關資訊,包括在我們的案例中,未壓縮視訊圖片的寬度和高度,最有可能在 MPEG1VIDEOINFO、 VIDEOINFOHEADER、 MPEG2VIDEOINFO或 VIDEOINFOHEADER2 結構中。
- 如果存在, AM_MEDIA_TYPE 結構會指示解碼器使用指定的媒體類型運作,這可以是「完全指定」或「部分指定」。 如果「完全指定」,解碼器通常會嘗試使用該媒體類型運作。 如果「部分指定」,它會嘗試尋找「完全指定」相容模式的作業,其可用來以與「部分指定」媒體類型一致的方式來連線。
- 嘗試尋找用於連線之「完整指定」媒體類型的一般方式,就是直接透過輸出針腳所支援的每個「完全指定」媒體類型清單來執行,而輸出針腳支援與「部分指定」媒體類型相容,並嘗試與每一種媒體類型連線,直到成功為止。 如果 IPin::Connect 呼叫中未包含任何AM_MEDIA_TYPE,但輸出針腳需要檢查其所有媒體類型,則此程式通常會類似。
如果解碼器想要檢查下游輸入針腳是否支援特定 AM_MEDIA_TYPE ( 包括視訊加速器 GUID) ,則可以呼叫該釘選的 IPin::QueryAccept (,並將影片加速器 GUID 當做 AM_MEDIA_TYPE) 的子類型,或直接嘗試連線到該釘選,如下列專案 5 所述。
如果解碼器不知道下游輸入針腳支援的視訊加速器 GUID,而且不想只藉由呼叫下游輸入針腳的 IPin::QueryAccept來建議一些特定的候選視訊加速器 GUID,解碼器可以呼叫 IAMVideoAccelerator::GetVideoAcceleratorGUID 來取得釘選支援的視訊加速器 GUID 清單。
對於某些特定的視訊加速器 GUID,解碼器可以呼叫下游輸入針腳的 IAMVideoAccelerator::GetUncompFormatsSupported ,以取得可用來轉譯特定視訊加速器 GUID 的 DDPIXELFORMAT 像素格式清單。 傳回的清單應該視為以遞減喜好設定順序 (,也就是先列出最慣用的格式) 。
解碼器會呼叫下游輸入針腳的 IPin::ReceiveConnection,並傳遞具有適當視訊加速器 GUID 作為媒體類型子類型的 AM_MEDIA_TYPE 。 這會設定作業的連線,包括建立未壓縮的輸出介面 (,這些介面是使用 AM_MEDIA_TYPE中找到的寬度和高度來配置,以及下列呼叫所要配置的介面數目,以及視訊加速器可供使用且想要用於該用途的任何其他資訊,例如視訊加速器 GUID 本身) 。 如果下游輸入針腳拒絕視訊加速器 GUID 或其他連線層面,這可能會導致 IPin::ReceiveConnection 失敗。 如果 IPin::ReceiveConnection 失敗,這會在傳回 的 HRESULT中指出,解碼器可以嘗試再次呼叫,例如, 在 AM_MEDIA_TYPE 結構中使用新的視訊加速器 GUID。
[注意]
這是另一種方式 (,以及解碼器最明確的方式) ,可判斷下游輸入針腳所支援的內容,只要呼叫 IPin::ReceiveConnection 並嘗試連線,然後檢查連線嘗試是否成功。
在 IPin::ReceiveConnection期間,轉譯器會呼叫解碼器的 IAMVideoAcceleratorNotify::GetUncompSurfacesInfo,傳遞影片加速器 GUID 和 AMVAUncompBufferInfo 結構,以找出要配置的未壓縮表面數目。 解碼器會填入 並傳回 結構,其中包含要配置特定類型的最小和最大表面數目,以及描述要配置之表面像素格式的 DDPIXELFORMAT 結構。
[注意]
在呼叫 IAMVideoAcceleratorNotify::GetUncompSurfacesInfo 以外的影片加速器 GUID 中,實際上不會將任何專案傳入解碼器。
轉譯器會呼叫解碼器的 IAMVideoAcceleratorNotify::SetUncompSurfacesInfo,傳遞至解碼器已配置的實際未壓縮表面數目。
轉譯器會呼叫解碼器的 IAMVideoAcceleratorNotify::GetCreateVideoAcceleratorData ,以取得初始化視訊加速器所需的任何資料。
解碼器會呼叫 IAMVideoAccelerator::GetCompBufferInfo,傳遞影片加速器 GUID、 AMVAUncompDataInfo 結構,以及壓縮緩衝區類型的數目,以傳回一組 AMVACompBufferInfo 資料結構,一個對應至視訊加速器 GUID 所使用的每種壓縮資料緩衝區類型。
- AMVAUncompDataInfo結構包含解碼未壓縮資料 (的寬度和高度,以圖元) 和未壓縮圖片的 DDPIXELFORMAT。
-
AMVACompBufferInfo資料結構傳回每個結構都包含:
特定類型所需的壓縮緩衝區數目。
要建立 (欄位的寬度和高度,這些欄位可能沒有任何實際意義) 。
注意
壓縮緩衝區的 DirectDraw 表面配置作業目前未提供這些表面的寬度或高度大於或等於 2^15,不過如果違反此限制,介面配置呼叫可能不會過度失敗。 因此,驅動程式可以建構其壓縮緩衝區記憶體的要求,以避免這類極端大小。 例如,驅動程式應該要求 width=「1」 和 height=「65536」 的緩衝區,應該要求 width=「1024」 和 height=「64」 的緩衝區。
介面要使用的位元組總數。
定義 DirectDrawSurface 物件的 DDSCAPS2類型結構,描述建立介面以儲存壓縮資料的功能。
DDPIXELFORMAT,描述用來建立表面的像素格式,以儲存壓縮資料 (欄位) 。
注意
轉譯器對某些解碼器 IAMVideoAcceleratorNotify 介面方法的呼叫可能會 (,而且通常會在轉譯器的 IPin::ReceiveConnection呼叫內發生) 。 具體來說,這適用于下列各項:
注意
為了支援動態格式變更,解碼器也可以呼叫上述的 IPin::ReceiveConnection 和其他方法,同時篩選準則已連線並執行。 這項功能是為了支援動態格式變更, (雖然不在 H.263、附錄 P 中,但意義 - 因為所有資料集都會從頭開始,因此任何參考圖片資訊都會遺失) 。
以下是初始化後作業期間 IAMVideoAccelerator 使用的描述:
針對每個未壓縮表面,解碼器會呼叫 IAMVideoAccelerator::BeginFrame 開始處理以建立輸出圖片。 這樣做時,解碼器會傳送 AMVABeginFrameInfo 結構。
AMVABeginFrameInfo結構包含目的地緩衝區的索引、要傳送下游之某些資料的指標,以及加速器可以放置一些資料以供解碼器讀取的位置指標。
注意 1:加速器實際上不會接收目的地緩衝區索引,因為轉譯器會在下游之前轉譯。
注意 2: IAMVideoAccelerator::BeginFrame 在對 IAMVideoAccelerator::EndFrame的呼叫之間可以多次呼叫。
附注 3:介面作業中沒有假設, IAMVideoAccelerator::BeginFrame 和 IAMVideoAccelerator::EndFrame 必須呼叫,才能處理 bitstream 中的每個個別圖片。
根據介面的考慮, IAMVideoAccelerator::BeginFrame 會在索引與未壓縮表面之間的轉譯器內建立關聯。 它也提供在設備磁碟機中呼叫特定函式的方法, (支援在解碼器和設備磁碟機) 之間來回傳遞任意資料的方法。
不過, (,在 DirectX VA 作業中,有一項需求如下所述, IAMVideoAccelerator::BeginFrame 和 IAMVideoAccelerator::EndFrame 必須呼叫 ,才能處理 bitstream.)
若要將未壓縮的資料傳送至加速器,解碼器會呼叫:
- IAMVideoAccelerator::QueryRenderStatus ,以判斷緩衝區是否適合讀取或寫入。
- IAMVideoAccelerator::GetBuffer ,如果先前尚未呼叫此緩衝區以取得該存取) ,請 (取得指定緩衝區的存取權。 GetBuffer也可以用來取得上次未壓縮輸出圖片內容的複本,其中已呼叫IAMVideoAccelerator::BeginFrame,提供 IAMVideoAccelerator::EndFrame尚未針對該目的地緩衝區索引呼叫。 如果 DDI 傳回所要求緩衝區DDERR_WASSTILLDRAWING的轉譯狀態,則會在 GetBuffer 內運作睡眠迴圈,直到清除此條件為止。 若要呼叫 GetBuffer,解碼器需要 AMVACompBufferInfo 資料結構中取得的一些資訊,這是藉由呼叫 IAMVideoAccelerator::GetCompBufferInfo取得。
- IAMVideoAccelerator::Execute 表示應該處理一組壓縮緩衝區中的資料,如 AMVABUFFERINFO 資料結構的陣列所示。 函式程式碼 dwFunction 會在此呼叫中傳遞至驅動程式。 lpPrivateInputData 指標也會傳遞至某些資料以傳送下游,而 lpPrivateOutputData 指標會傳遞給下游進程可以放置一些資料以供解碼器讀取的位置。
- IAMVideoAccelerator::ReleaseBuffer ,表示解碼器目前已完成使用指定的緩衝區,而不再需要鎖定的緩衝區存取權。 (如果解碼器想要繼續使用緩衝區, 它目前無法直接呼叫 IAMVideoAccelerator::ReleaseBuffer ,因此避免呼叫 IAMVideoAccelerator::GetBuffer ,直到真的想要不要再使用緩衝區為止。) 解碼器不應該在呼叫 Execute 之後寫入緩衝區,直到 QueryRenderStatus 指出緩衝區是安全的寫入為止。
若要完成目的地緩衝區的輸出處理,解碼器會呼叫 IAMVideoAccelerator::EndFrame。 它可以使用此呼叫傳遞一些任意資料,基本上就是因為此呼叫而發生的所有動作。 它不會在此呼叫中傳送目的地緩衝區索引,因此無法精確地向加速器指出目的地緩衝區已完成,除非此指示包含在傳遞的任意資料中。
若要顯示框架,解碼器會呼叫IAMVideoAccelerator::D isplayFrame,其中包含要顯示的畫面索引,以及包含開始和停止時間戳記的IMediaSample結構,以及AM_SAMPLE2_PROPERTIES 結構中的dwTypeSpecificFlags等相關旗標,以及VIDEOINFOHEADER2結構中的dwInterlaceFlags。 解碼器必須確認影響框架內容的所有解壓縮作業在呼叫 DisplayFrame之前都已完成。
最後,解碼器應該在完成所有處理時,藉由呼叫 IAMVideoAccelerator::EndFrame 來指出所有剩餘的開始輸出畫面格完成,並呼叫 IAMVideoAccelerator::ReleaseBuffer 來釋放其所有鎖定的緩衝區。
相關主題