【视频处理工程】8、关于DXVA视频解码硬件加速(1):Decoder如何调用IAMVideoAccelerator接口
2014-05-13 11:47
274 查看
前言:这段时间一直在研究一个项目就是改如何在L*** Video中加入DXVA1.0的相关功能。在L*** Filter中已经叫好地实现了DXVA 2.0的相关功能,但是我们知道DXVA 2.0仅能支持Windows Vista以上版本的操作系统。然而我国国内的很多用户依然在使用者Windows XP不肯更新,所以公司的产品为了支持XP下的硬件解码加速,不得不硬着头皮在L*** Video中集成DXVA
1.0,尽管按照L*** Filter的作者Nevcairiel认为,这么做是没有任何意义的……在此之前,需要在MSDN上查阅一些相关的资料,本文是MSDN中这篇文档的译文。
视频解码器如何调用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方法释放所有锁定的缓存区。
1.0,尽管按照L*** Filter的作者Nevcairiel认为,这么做是没有任何意义的……在此之前,需要在MSDN上查阅一些相关的资料,本文是MSDN中这篇文档的译文。
视频解码器如何调用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结构的定义如:
typedef struct _AMMediaType { GUID majortype; GUID subtype; BOOL bFixedSizeSamples; BOOL bTemporalCompression; ULONG lSampleSize; GUID formattype; IUnknown *pUnk; ULONG cbFormat; BYTE *pbFormat; } 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方法释放所有锁定的缓存区。
相关文章推荐
- 如何处理libva加速元件的显示:(vaPutImage)(2)-将视频过滤器更改为视频接收器
- GStreamer播放教程08——视频解码的硬件加速
- 【ARM-Linux开发】【CUDA开发】【视频开发】关于Linux下利用GPU对视频进行硬件加速转码的方案
- Opencv3.0-python的那些事儿:(九)、Opencv关于如何读取大量视频帧进行处理的方法
- 几个平台环境里视频编解码和图像scale的硬件加速的方法
- 【视频开发】ffmpeg实现dxva2硬件加速
- 关于Linux下利用GPU对视频进行硬件加速转码的方案
- 【GStreamer开发】GStreamer播放教程08——视频解码的硬件加速
- 关于SetForegroundWindow调用失败的处理
- 关于platform_driver 是如何匹配 platform_device的和如何调用到platform_driver中的probe函数的研究
- WCF技术剖析之十:调用WCF服务的客户端应该如何进行异常处理(转)
- nodejs如何调用动态链接库(dll)呢?写一个addon来处理,写此文抛砖引玉。
- 如何将GTK+-2.0的信号、回调处理映射成类成员函数的调用--示例
- 关于使用sts-bundle开发SpringMVC工程时如何应用复制而不是下载的repository
- WCF技术剖析之十:调用WCF服务的客户端应该如何进行异常处理
- 如何将GTK+-2.0的信号、回调处理映射成类成员函数的调用--VC中测试(单类继承)
- 关于android视频解码
- 请教:Android正播放视频时的解码输出流如何获取?
- 关于如何将Maven工程上传到Github和从Github下载到本地
- 树莓派sip视频电话-1:exosip2ctype+python使用硬件编解码