dxva2+ffmpeg硬件解码(Windows)重要笔记3,
dxva2+ffmpeg硬件解码(Windows)重要笔记3,
参考了csdn上Win32Project1_ffmpeg_dxva2这个例子,很不错,直接就可以运行。
但是,有几个问题:
1、窗口无法正常缩放,缩放后,图像大小并没有一起缩放
2、H265的编码格式,显示下面有一块绿色。
3、无法从显卡获取YUV420P数据或者NV12数据
3、找了很久网上也没有相关代码实现从显卡获取数据到内存(有些方法相当慢,基本无法使用!)
第3个问题,万能的网络变得不再万能,基本都是无解,要么实现不了,要么速度慢:
这个相当于是从显存直接复制到内存,如果速度慢了,就失去意义了,因为硬件解码的目的就是减少CPU占用和提升解码实时性。
其实,ffmpeg就自带了一个函数的,这个函数速度还是比较快的,对了,就是这个函数
av_image_copy_uc_from
只是大家都不会用而已,直接贴代码:
static int Extract(AVCodecContext *va, AVFrame *src, AVFrame *dst,CCacheBuffer *cache )
{
BYTE *pNV12=new BYTE[va->width*va->height*4];
int width;
int height;
int pitch;
int format;
int surfaceDesc_Height;
void *pSourceFrame;
D3DLOCKED_RECT lock;
DWORD dwTime1=::GetTickCount();
LPDIRECT3DSURFACE9 d3d = (LPDIRECT3DSURFACE9)(uintptr_t)src->data[3];
D3DSURFACE_DESC surfaceDesc;
IDirect3DSurface9_GetDesc(d3d, &surfaceDesc);
if (!dst->data[0])
{
delete []pNV12;
return -1;
}
width=surfaceDesc.Width;
height=surfaceDesc.Height;
format=surfaceDesc.Format;
if ( format == MAKEFOURCC('N', 'V', '1', '2') )
{
height = 3 * height / 2; // FULL Y, SUBSAMPLED UV PLANES
}
dwTime1=::GetTickCount();
if (FAILED(IDirect3DSurface9_LockRect(d3d, &lock, NULL, D3DLOCK_READONLY)))
{
delete []pNV12;
return -1;
}
pSourceFrame = lock.pBits;
pitch = lock.Pitch;
surfaceDesc_Height=surfaceDesc.Height;
uint8_t *plane[2] = {
( uint8_t *) lock.pBits,
(uint8_t*)lock.pBits + lock.Pitch * surfaceDesc.Height
};
const uint8_t *source[4]={( uint8_t *)lock.pBits,( uint8_t *)lock.pBits + lock.Pitch * surfaceDesc.Height,0,0};
int linesize_source[4]={lock.Pitch,lock.Pitch,0,0};
uint8_t *dest[4]={( uint8_t *)pNV12,( uint8_t *)pNV12+lock.Pitch * surfaceDesc.Height,0,0};
int linesize_dest[4]={lock.Pitch,lock.Pitch,0,0};
av_image_copy_uc_from(dest,linesize_dest,source,linesize_source,AV_PIX_FMT_NV12,va->width,va->height)
IDirect3DSurface9_UnlockRect(d3d);
libyuv::NV12ToI420(pNV12,pitch,pNV12+pitch*surfaceDesc_Height,pitch,dst->data[0],va->width,dst->data[1],va->width/2,dst->data[2],va->width/2,va->width,va->height);
//TRACE("时间:%d\n",::GetTickCount()-dwTime1);
delete []pNV12;
return 0;
}
实验了下,已经相当快了!打开一个4K视频,一帧花的时间平均不到30ms。1080P或者更低分辨率肯定是更没问题的。
好了,谢谢大家!本人QQ35744025,对音视频有些研究,需要合作交流的,欢迎骚扰!
评论暂时关闭