硬编码支持情况(一)
图片信息原文链接:http://trac.ffmpeg.org/wiki/HWAccelIntro
截个图:
注:
(一):Intel 平台
1:Intel 平台的Quick Sync Video(qsv)是对于音视频编解码的框架具体对外接口则为上面图中的LIBMFX,可以理解为Quick Sync Video(qsv)是对外宣称的技术ffmpeg对外设备TYPE选择也是这个,但如果不用ffmpeg直接用intel自身api则操作的是LIBMFX库提供的对外API接口。
2:SDK下载地址:https://github.com/Intel-Media-SDK/MediaSDK,需要安装。
3:samples下载地址:https://github.com/Intel-Media-SDK/samples/tree/4293f965b42310c043bc49d23c6f9f5d3d587dd8,里面有编码和解码的samples。
4:【Intel(R)_Media_SDK】官方文档翻译摘要:https://blog.csdn.net/zhuweigangzwg/article/details/83861644。
5:如果开发程序需要添加的lib库如下:
//用intel的mfx的media库command工程中引用如下才能编译成功生成lib库。
//本项目再引用此lib库。
/*
..\include;
$(INTELMEDIASDKROOT); //intelmediasdk
..\include\vm;
*/
/*
本工程添加的头文件目录
..\INTEL_MFX\include;
$(INTELMEDIASDKROOT)\include; //intelmediasdk
添加的lib库目录:..\Debug; ..\Release; 即上面command生成的lib库。
添加lib库目录:$(INTELMEDIASDKROOT)\lib\$(Platform) //intelmediasdk
*/
//添加command库
#pragma comment(lib,"libmfx_vs2015.lib")
#pragma comment(lib,"dxva2.lib")
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"dwmapi.lib")
#pragma comment(lib,"comsuppw.lib")
#pragma comment(lib,"dxgi.lib")
//目录C:\Program Files (x86)\IntelSWTools\Intel(R) Media SDK 2018 R2\Software Development Kit\lib
#pragma comment(lib,"libmfx.lib")
//目录C:\Program Files (x86)\IntelSWTools\Intel(R) Media SDK 2018 R2\Software Development Kit\lib
#pragma comment(lib,"libmfx_vs2015.lib")
#pragma comment(lib,"command.lib")
6:CBuffering::m_pSurfaces内存管理的类,由于此类中的一些函数或变量是protected的,
只有用c++继承方式,但这里是c语言,需要修改源码protected为public,文件是mfx_buffering.h,函数和变量都修改为public。
7:mfx解码时候的5个surface,输入两个在(1)中说明,输出两个在(2)中说明,(3)中是个临时变量为解决解码参数问题。
如果输出的surface不用直接将(3)的解码后的surface用于输出也可以。
(1)CurrentFreeSurface是空闲的surface,传入解码器,用于解码,如果在解码途中则需要转给m_UsedSurfacesPool队列。
即这段数据正在解码被锁住则传入正在使用的surface队列中
m_FreeSurfacesPool队列中取出的m_pCurrentFreeInSurface和m_UsedSurfacesPool都是用于存放对H264处理的surface.都是输入surface。current字段是防止和系统的变量名称冲突。
(2)CurrentFreeOutputSurface是空闲的输出surface,传入解码器,用于接收解码之后的yuv数据,接收之后传给m_OutputSurfacesPool队列。GetFreeOutputSurface中取出的m_pCurrentFreeOutputSurface和m_OutputSurfacesPool都是用于存放解码后的yuv数据surface,都是输出队列。
(3)引入m_pOutSurface这个变量只是为了适应DecodeFrameAsync这个函数传入**指针的操作,如果可以用m_pCurrentFreeOutputSurface也可以。
8:这里一定要注意有个大坑:
mfxBitstream * pBitstream 这个变量中就是存放一帧要解码数据的结构体其中,MaxLength:申请的内存大小,DataLength:解码前是传入的数据大小,解码后是剩余的数据大小。DataOffset:解码前为0,解码后实际解码了多少数据。
解码后的状态码MFX_ERR_MORE_DATA == sts时pBitstream->DataLength一定等于0这时候再读取一帧数据没问题。
如果MFX_ERR_NONE == sts时分为两种情况,1:pBitstream->DataLength == 0,这时再去读取一帧数据。
如果MFX_ERR_NONE == sts时分为两种情况,2:pBitstream->DataLength != 0,这时一定不能读取新的数据,要继续用剩下的数据去解码.否则会有帧减少产生图像花屏绿屏情况。
也就是说解码传进去一帧数据有可能返回的时候剩余一些字段,需要将这些字段再传给解码器做解码,而不是再读取一帧用于解码这个值就是pBitstream->DataLength。
9:mfxEncodeCtrl encCtrl; //编码的帧类型和一些扩展信息存储结构体。只是扩展用填写为NULL也可以如果没有扩展。
//编码时这个值必须清零否则EncodeFrameAsync会失败返回-15.
MSDK_ZERO_MEMORY(encCtrl);
编码后需要做异步同步操作。//同步操作,输出数据到m_mfxBS中
sts = m_mfxSession.SyncOperation(UserSyncp, MSDK_WAIT_INTERVAL);
10:mfx 填写qp时,unsigned short UserRateControlMethod = MFX_RATECONTROL_CQP; //CBR,ABR,CQP
m_mfxEncParams.mfx.RateControlMethod = UserRateControlMethod; //CBR,ABR,CQP
if (UserRateControlMethod == MFX_RATECONTROL_CQP)
{
m_mfxEncParams.mfx.QPI = 24;
m_mfxEncParams.mfx.QPP = 34;
m_mfxEncParams.mfx.QPB = 34;
}
其他值RateControlMethod 则一旦填写QP初始化会失败。
11: //解决实时编码问题(传入空数据)。
do
{
sts = m_pmfxENC->EncodeFrameAsync(&encCtrl, pSurf, &m_mfxBS, &UserSyncp);
pSurf = NULL;
Sleep(1);
} while (sts == MFX_ERR_MORE_DATA);
12://解决实时解码问题(传入空数据)。
do
{
sts = m_pmfxDEC->DecodeFrameAsync(NULL, &(m_pCurrentFreeSurface->frame), &m_pOutSurface, &usersyncp);
if (sts == MFX_ERR_MORE_DATA)
{
Sleep(1);
}
} while (MFX_ERR_MORE_DATA== sts);
13: //解决实时解码问题(传入空数据)。
//错误处理
if (sts == MFX_ERR_DEVICE_LOST ||
sts == MFX_ERR_INCOMPATIBLE_VIDEO_PARAM ||
sts == MFX_ERR_INVALID_VIDEO_PARAM ||
sts == MFX_ERR_UNDEFINED_BEHAVIOR ||
sts == MFX_ERR_DEVICE_FAILED)
{
DISPATCHER_LOG_INFO((("CMfxDecoder::DecodeFrameAsync = %d."), sts)