我使用DirectX绘制视频。经过英特尔媒体SDK解码后。然后我通过以下英特尔代码绘制它:
mfxStatus CD3D11Device::RenderFrame(mfxFrameSurface1 * pSrf, mfxFrameAllocator * pAlloc)
{
HRESULT hres = S_OK;
mfxStatus sts;
sts = CreateVideoProcessor(pSrf);
MSDK_CHECK_STATUS(sts, "CreateVideoProcessor failed");
hres = m_pSwapChain->GetBuffer(0, __uuidof( ID3D11Texture2D ), (void**)&m_pDXGIBackBuffer.p);
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC OutputViewDesc;
if (2 == m_nViews)
{
m_pVideoContext->VideoProcessorSetStreamStereoFormat(m_pVideoProcessor, 0, TRUE,D3D11_VIDEO_PROCESSOR_STEREO_FORMAT_SEPARATE,
TRUE, TRUE, D3D11_VIDEO_PROCESSOR_STEREO_FLIP_NONE, NULL);
m_pVideoContext->VideoProcessorSetOutputStereoMode(m_pVideoProcessor,TRUE);
OutputViewDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2DARRAY;
OutputViewDesc.Texture2DArray.ArraySize = 2;
OutputViewDesc.Texture2DArray.MipSlice = 0;
OutputViewDesc.Texture2DArray.FirstArraySlice = 0;
}
else
{
OutputViewDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
OutputViewDesc.Texture2D.MipSlice = 0;
}
if (1 == m_nViews || 0 == pSrf->Info.FrameId.ViewId)
{
hres = m_pDX11VideoDevice->CreateVideoProcessorOutputView(
m_pDXGIBackBuffer,
m_VideoProcessorEnum,
&OutputViewDesc,
&m_pOutputView.p );
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
}
D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC InputViewDesc;
InputViewDesc.FourCC = 0;
InputViewDesc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
InputViewDesc.Texture2D.MipSlice = 0;
InputViewDesc.Texture2D.ArraySlice = 0;
mfxHDLPair pair = {NULL};
sts = pAlloc->GetHDL(pAlloc->pthis, pSrf->Data.MemId, (mfxHDL*)&pair);
MSDK_CHECK_STATUS(sts, "pAlloc->GetHDL failed");
ID3D11Texture2D *pRTTexture2D = reinterpret_cast<ID3D11Texture2D*>(pair.first);
D3D11_TEXTURE2D_DESC RTTexture2DDesc;
if(!m_pTempTexture && m_nViews == 2)
{
pRTTexture2D->GetDesc(&RTTexture2DDesc);
hres = m_pD3D11Device->CreateTexture2D(&RTTexture2DDesc,NULL,&m_pTempTexture.p);
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
}
// Creating input views for left and righ eyes
if (1 == m_nViews)
{
hres = m_pDX11VideoDevice->CreateVideoProcessorInputView(
pRTTexture2D,
m_VideoProcessorEnum,
&InputViewDesc,
&m_pInputViewLeft.p );
}
else if (2 == m_nViews && 0 == pSrf->Info.FrameId.ViewId)
{
m_pD3D11Ctx->CopyResource(m_pTempTexture,pRTTexture2D);
hres = m_pDX11VideoDevice->CreateVideoProcessorInputView(
m_pTempTexture,
m_VideoProcessorEnum,
&InputViewDesc,
&m_pInputViewLeft.p );
}
else
{
hres = m_pDX11VideoDevice->CreateVideoProcessorInputView(
pRTTexture2D,
m_VideoProcessorEnum,
&InputViewDesc,
&m_pInputViewRight.p );
}
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
// NV12 surface to RGB backbuffer
RECT rect = {0};
rect.right = pSrf->Info.CropW;
rect.bottom = pSrf->Info.CropH;
D3D11_VIDEO_PROCESSOR_STREAM StreamData;
if (1 == m_nViews || pSrf->Info.FrameId.ViewId == 1)
{
StreamData.Enable = TRUE;
StreamData.OutputIndex = 0;
StreamData.InputFrameOrField = 0;
StreamData.PastFrames = 0;
StreamData.FutureFrames = 0;
StreamData.ppPastSurfaces = NULL;
StreamData.ppFutureSurfaces = NULL;
StreamData.pInputSurface = m_pInputViewLeft;
StreamData.ppPastSurfacesRight = NULL;
StreamData.ppFutureSurfacesRight = NULL;
StreamData.pInputSurfaceRight = m_nViews == 2 ? m_pInputViewRight : NULL;
m_pVideoContext->VideoProcessorSetStreamSourceRect(m_pVideoProcessor, 0, true, &rect);
m_pVideoContext->VideoProcessorSetStreamFrameFormat( m_pVideoProcessor, 0, D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE);
hres = m_pVideoContext->VideoProcessorBlt( m_pVideoProcessor, m_pOutputView, 0, 1, &StreamData );
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
}
if (1 == m_nViews || 1 == pSrf->Info.FrameId.ViewId)
{
DXGI_PRESENT_PARAMETERS parameters = {0};
hres = m_pSwapChain->Present1(0, 0, ¶meters);
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
}
return MFX_ERR_NONE;
}
从代码行:
ID3D11Texture2D *pRTTexture2D = reinterpret_cast<ID3D11Texture2D*>(pair.first);
我的pRTTexture2D
是ID3D11Texture2D
,格式为DXGI_FORMAT_NV12。
我想从这个纹理中获取RGB数据,我尝试使用以下方式:
1)映射纹理使用d3dContext->Map(Texture, 0, D3D11_MAP_READ, 0, &mapInfo) => must copy to the staging resource in my case
2)在系统内存上创建RGB Array
并计算从mapInfo
上的NV12转换为RGB Array
。
这种方法运行正常,但我想用更好的方式做到这一点。因为我想在BackBuffer中渲染(RenderFrame() Function)
DirectX将纹理转换为RGB时,如果我可以从BackBuffer获取数据,那就太棒了。
有人可以告诉我上面的代码。或者有更好的方法来实现它吗?
非常感谢!