天天看點

【視訊處理工程】8、關于DXVA視訊解碼硬體加速(1):Decoder如何調用IAMVideoAccelerator接口

前言:這段時間一直在研究一個項目就是改如何在LAV Video中加入DXVA1.0的相關功能。在LAV Filter中已經叫好地實作了DXVA 2.0的相關功能,但是我們知道DXVA 2.0僅能支援Windows Vista以上版本的作業系統。然而我國國内的很多使用者依然在使用者Windows XP不肯更新,是以公司的産品為了支援XP下的硬體解碼加速,不得不硬着頭皮在LAV Video中內建DXVA

視訊解碼器如何調用IAMVideoAccelerator接口?

IAMVideoAccelerator接口實作了通用的視訊處理加速功能,其中包括DXVA。該接口支援Windows 2000之後,Windows Vista之前的Windows作業系統。該接口暴露在視訊渲染器(主要是Overlay

Mixer和VMR)的輸入接口上,而與其配合的另一個接口IAMVideoAcceleratorNotify則暴露在視訊解碼器的輸出接口上,二者配合實作DXVA 1.0硬解碼加速功能。

對各個filter的pin進行連接配接的步驟如下:、

1、Filter Graph Manager調用Decoder輸出pin接口的IPin::Connect方法,可選擇一個類型的結構體執行個體作為參數。

AM_MEDIA_TYPE結構的定義如:

顧名思義,該結構表示的是某一種媒體類型。該結構體中包含一個majortype(視訊解碼時應為MEDIATYPE_Video)、一個subtype(DXVA Decoder的guid)等。另外其包含的formattype儲存了視訊的格式資訊, MPEG1VIDEOINFO, VIDEOINFOHEADER, MPEG2VIDEOINFO及VIDEOINFOHEADER2等。當存在一AM_MEDIA_TYPE類型的對象作為參數時,該對象通知解碼器按照某種指定的媒體類型進行操作。

2、如果解碼器想要确認下遊的filter的輸入pin是否支援某種格式的media type,調用該pin的 IPin::QueryAccept方法(以視訊加速器的GUID作為AM_MEDIA_TYPE對象的subtype),或者直接試圖與該pin進行連接配接。

3、若解碼器不知道下遊輸入pin所支援的視訊加速器GUID,也不去調用 IPin::QueryAccept去嘗試各個可能支援的GUID,可以調用 IAMVideoAccelerator::GetVideoAcceleratorGUIDs方法擷取該pin支援的視訊加速器的guid。

4、對于某些特定的視訊加速器,解碼器調用下遊輸入pin的IAMVideoAccelerator::GetUncompFormatsSupported方法擷取DDPIXELFORMAT像素格式的清單,用于渲染對應格式的視訊。

5、解碼器調用下遊輸入pin的 IPin::ReceiveConnection方法,參數為一個AM_MEDIA_TYPE執行個體(某個視訊加速器的guid作為該執行個體的subtype)。這一步驟實作filter之間的連接配接操作,包括建立解碼圖像的surfaces。若下遊輸入pin拒絕該mediatype,則該方法會傳回一個錯誤的HRESULT,随後解碼器可以換用包含其他視訊加速器GUID的AM_MEDIA_TYPE執行個體繼續嘗試。

在 IPin::ReceiveConnection方法中,渲染器調用解碼器的IAMVideoAcceleratorNotify::GetUncompSurfacesInfo方法,傳入視訊加速器的GUID和一個AMVAUncompBufferInfo執行個體,目的是知道需要配置設定多少個解碼圖像surface。解碼器将AMVAUncompBufferInfo執行個體指派并傳回,該執行個體中包含某種特定類型所需要的surface數目的最大值和最小值,以及描述該surface像素格式的DDPIXELFORMAT結構執行個體。

6、渲染器調用解碼器的IAMVideoAcceleratorNotify::SetUncompSurfacesInfo方法,通知解碼器實際配置設定的解碼圖像surface的數目。

7、渲染器調用解碼器的 IAMVideoAcceleratorNotify::GetCreateVideoAcceleratorData方法,擷取用于初始化視訊加速器的其他資料。

8、解碼器調用 IAMVideoAccelerator::GetCompBufferInfo方法,傳入標明的視訊加速器的GUID和一個AMVAUncompDataInfo執行個體以及編碼資料緩存種類數,傳回AMVACompBufferInfo執行個體的集合,每一個元素都對應一個視訊加速器GUID的編碼資料緩存。

AMVAUncompDataInfo結構儲存了編碼視訊的寬高分辨率(以像素為機關)以及DDPIXELFORMAT

表示的像素格式;

AMVACompBufferInfo提供了某種特定類型所需的編碼資料緩存數、建立的surface的寬高、這個surface所需的總比特數、一個DDSCAPS2結構執行個體和DDPIXELFORMAT執行個體;

* 視訊渲染器調用解碼器 IAMVideoAcceleratorNotify接口的方法,通常在解碼器調用渲染器的 IPin::ReceiveConnection方法中實作。主要有:

IAMVideoAcceleratorNotify::GetUncompSurfacesInfo、IAMVideoAcceleratorNotify::SetUncompSurfacesInfo和IAMVideoAcceleratorNotify::GetCreateVideoAcceleratorData。為了支援動态格式切換,在filter進行切換和運作的過程時,在上述方法中可能會多次調用 IPin::ReceiveConnection等方法。

在完成初始化後, IAMVideoAccelerator在解碼器完成的工作有;

1、對于每一個解壓縮surface,解碼器調用IAMVideoAccelerator::BeginFrame方法,傳遞一個AMVABeginFrameInfo結構執行個體作為參數,開始建立輸出圖像。該結構體包含一個目标緩存區的索引、向下遊傳遞資料的指針以及加速器傳遞到解碼器供其讀取的資料指針。IAMVideoAccelerator::BeginFrame方法在IAMVideoAccelerator::EndFrame方法調用的間隙可以多次調用。IAMVideoAccelerator::BeginFrame方法實際完成的工作,是在渲染器中建立索引和解壓縮surface之間的聯系,并提供一種在裝置驅動(device

driver)中調用某特定函數的方法。

2、解碼器調用IAMVideoAccelerator::QueryRenderStatus方法确定緩存是否可以安全讀寫,IAMVideoAccelerator::GetBuffer方法鎖定并擷取某個緩存區的入口。同時若尚未針對此緩存區索引調用IAMVideoAccelerator::EndFrame方法,IAMVideoAccelerator::GetBuffer方法還可以擷取最新的解碼圖像輸出資料的一份拷貝。若DDI傳回的狀态為DDERR_WASSTILLDRAWING,則GetBuffer方法将休眠直至該狀态結束。為了調用GetBuffer方法,解碼器需要調用IAMVideoAccelerator::GetCompBufferInfo方法擷取一個AMVACompBufferInfo結構體執行個體,并從中擷取所需資訊。

解碼器調用IAMVideoAccelerator::Execute方法,表示在一組AMVABUFFERINFO結構執行個體中标記的壓縮緩存中的視訊流資料開始被處理。所需的參數有lpPrivateInputData指針、lpPrivateOutputData

指針和函數代碼dwFunction等。

解碼器調用IAMVideoAccelerator::ReleaseBuffer方法,表示解碼器已經完成了對某個緩存區的占用。需要注意的是,在調用過Execute方法後,如果沒有調用QueryRenderStatus方法确認緩存可安全讀寫,則不可向緩存區中寫入資料。

3、對于目标緩存區完成資料輸出後,解碼器調用 IAMVideoAccelerator::EndFrame方法。該方法不将某個緩存索引作為參數,是以不能精确指定已完成對那個緩存區的操作,除非通過該方法傳遞的參數中有指明。

4、解碼器調用IAMVideoAccelerator::DisplayFrame方法以顯示一幀圖像,所需的參數有待顯示幀的索引、包含起止時間戳的IMediaSample結構執行個體以及相關的辨別為(如AM_SAMPLE2_PROPERTIES結構中的dwTypeSpecificFlags和VIDEOINFOHEADER2中的dwInterlaceFlags等)。在調用該方法之前,必須确認所有操作幀緩存區的方法必須調用完成。

5、最後,在完成上述所有操作後,調用 IAMVideoAccelerator::EndFrame方法完成對輸出幀的操作,并調用IAMVideoAccelerator::ReleaseBuffer方法釋放所有鎖定的緩存區。

繼續閱讀