[與此頁面相關聯的功能,DirectShow是舊版功能。 它已被 MediaPlayer、IMFMediaEngine及媒體基金會中的音訊/視訊擷取 所取代。 這些功能已針對 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 介面會在譯碼器的輸出接腳上公開。 連接篩選針腳的事件順序如下:
Filter Graph 管理員會在解碼器濾鏡的輸出接腳上調用 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::GetVideoAcceleratorGUIDs 來獲取引腳支援的視訊加速器 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" 的緩衝區。
介面要使用的位元組總數。
DDSCAPS2 定義 DirectDrawSurface 物件的型別結構,描述用來建立介面以儲存壓縮數據的功能。
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。
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,直到它真的打算不再使用緩衝區為止。在呼叫執行 之後,譯碼器不應該寫入緩衝區,直到 QueryRenderStatus 表示緩衝區是安全的寫入為止。
若要完成目的地緩衝區的輸出處理,譯碼器會呼叫 IAMVideoAccelerator::EndFrame。 它可以透過這個呼叫將一些任意的數據傳遞到下游,這就是這個呼叫所產生的效果之一。 它不會在此呼叫中傳送目的地緩衝區索引,因此它無法精確地向加速器指出完成的目的地緩衝區,除非此指示包含在傳遞的任意數據中。
為了顯示畫面,解碼器會呼叫 IAMVideoAccelerator::DisplayFrame,並傳入要顯示的畫面的索引,以及 IMediaSample 結構,其中包含開始和停止的時間戳以及相關的旗標,例如 AM_SAMPLE2_PROPERTIES 結構中的 dwTypeSpecificFlags 和 VIDEOINFOHEADER2 結構中的 dwInterlaceFlags。 譯碼器必須先確認影響框架內容的所有解壓縮作業都已完成,再呼叫 DisplayFrame。
最後,當完成所有處理時,譯碼器應該藉由呼叫 IAMVideoAccelerator::EndFrame 來表示所有剩餘已開始的輸出畫面格已完成,並且為每個未釋放的緩衝區呼叫 IAMVideoAccelerator::ReleaseBuffer 來釋放其所有鎖定的緩衝區。
相關主題