ctx->d3d9device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &m_pBackBuffer);
ctx->d3d9device->SetRenderTarget(0, m_pBackBuffer);
ctx->d3d9device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
ctx->d3d9device->BeginScene();
ctx->d3d9device->SetTexture(0, g_SurfaceTexture);
ctx->d3d9device->SetFVF(Dxva2TexVertex::FVF);
ctx->d3d9device->SetStreamSource(0, QuadVB, 0, sizeof(Dxva2TexVertex));
ctx->d3d9device->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
ctx->d3d9device->EndScene();
hr = ctx->d3d9device->Present(NULL, NULL, NULL, NULL);
if (FAILED(hr)) {
if (ctx->d3d9device->TestCooperativeLevel() == D3DERR_DEVICENOTRESET)
{
printf("Failed to Present !") ;
ret = -1 ;
}
}
else
{
ret = 0 ;
}
}
LeaveCriticalSection(&cs);
return ret;
}
可以看到代码中有两组
ctx->d3d9device->BeginScene();
····
ctx->d3d9device->EndScene();
第一组通过 ctx->d3d9device->SetRenderTarget(0, g_OffScreenSurface); 把渲染目标设置为纹理的surface,把DXVA2解码得到的数据渲染到前面准备好的纹理的surface中;第二组则把渲染目标设为后台缓存,直接把纹理渲染出来即可。做这一层折腾的原因在于StretchRect函数的一个限制,
大意就是如果源或者目的surface是个纹理surface,就需要查看驱动是否支持,而
详见https://msdn.microsoft.com/en-us/library/windows/desktop/bb174471(v=vs.85).aspx
所以我在前面强调创建纹理的第四个参数注意设置为D3DUSAGE_RENDERTARGET。起初我也是因为这个参数设错了,一直没法成功,后来突然想到RT texture可能是指设为D3DUSAGE_RENDERTARGET的texture,RT可能是RENDERTARGET的缩写,然后才成功的。Off-screen plain指离屏表面,我对D3D的一些概念不是特别清楚,不知道承载DXVA2解码数据的surface是不是离屏表面,但我试了许多方法,只有这样才最后成功。如果这一块的理解有问题,欢迎拍砖指教。
对于FFmpeg DXVA2硬解有疑问的,可以参考http://www.cnblogs.com/betterwgo/p/6125507.html。对于D3D有疑问的,请自行上网查询,我懂的也不多,可以相互交流一下。
完整工程源码:http://download.csdn.net/download/qq_33892166/9742467
运行工程的时候注意修改代码中视频文件的路径。
|