gpt4 book ai didi

c++ - 将 IMFSample* 转换为 ID3D11ShaderResourceView*

转载 作者:行者123 更新时间:2023-11-30 02:24:17 26 4
gpt4 key购买 nike

我是 DirectX 新手,我正在尝试编写一个简单的应用程序来读取视频并将其显示在 Quad 上。

我使用 Windows Media Foundation (IMFSourceReader) 阅读视频,它会在样本解码 (IMFSample) 时向我发送回调。

我想将此 IMFSample* 转换为 ID3D11ShaderResourceView*,以便将其用作纹理来绘制我的四边形,但是转换失败。

这是我所做的(我删除了不相关的错误检查):

HRESULT SourceReaderCB::OnReadSample(HRESULT hrStatus, DWORD dwStreamIndex, DWORD dwStreamFlags, LONGLONG llTimestamp, IMFSample *pSample)
{
...
DWORD NumBuffers = 0;
hr = pSample->GetBufferCount(&NumBuffers);

if (FAILED(hr) || NumBuffers < 1)
{
...
}

IMFMediaBuffer* SourceMediaPtr = nullptr;
hr = pSample->GetBufferByIndex(0, &SourceMediaPtr);

if (FAILED(hr))
{
...
}

ComPtr<IMFMediaBuffer> _pInputBuffer = SourceMediaPtr;
ComPtr<IMF2DBuffer2> _pInputBuffer2D2;

bool isVideoFrame = (_pInputBuffer.As(&_pInputBuffer2D2) == S_OK);
if (isVideoFrame)
{
IMFDXGIBuffer* pDXGIBuffer = NULL;
ID3D11Texture2D* pSurface = NULL;

hr = _pInputBuffer->QueryInterface(__uuidof(IMFDXGIBuffer), (LPVOID*)&pDXGIBuffer);
if (FAILED(hr))
{
SafeRelease(&SourceMediaPtr);
goto done;
}

hr = pDXGIBuffer->GetResource(__uuidof(ID3D11Texture2D), (LPVOID*)&pSurface);
if (FAILED(hr))
{
...
}

ID3D11ShaderResourceView* resourceView;

if (pSurface)
{
D3D11_TEXTURE2D_DESC textureDesc;
pSurface->GetDesc(&textureDesc);

D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
shaderResourceViewDesc.Format = DXGI_FORMAT_R8_UNORM;
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
shaderResourceViewDesc.Texture2D.MipLevels = 1;

ID3D11ShaderResourceView* resourceView;
hr = d3d11device->CreateShaderResourceView(pSurface, &shaderResourceViewDesc, &resourceView);
if (FAILED(hr))
{
... // CODE FAILS HERE
}
...
}
}
}

我的第一个问题是,我将 ShaderResourceViewDesc.Format 设置为 DXGI_FORMAT_R8_UNORM,这可能只会给我红色图像(我稍后必须对此进行调查)。

我面临的第二个阻塞问题是,ID3D11Texture2D 到 ID3D11ShaderResourceView 的转换失败,并显示以下错误消息:

ID3D11Device::CreateShaderResourceView: A ShaderResourceView cannot be created of a Resource that did not specify the D3D11_BIND_SHADER_RESOURCE BindFlag. [ STATE_CREATION ERROR #129: CREATESHADERRESOURCEVIEW_INVALIDRESOURCE]

我知道在创建纹理时缺少一个标志,这会阻止我做我想做的事情,但由于数据缓冲区是由 WMF 创建的,我不确定我应该做什么来修复这个问题。

感谢您的帮助

最佳答案

我看到你的代码,我可以说你的方式是错误的 - 无意冒犯。首先,视频解码器创建简单的纹理 - 在您的情况下 DirectX11 纹理 - 它是常规纹理 - 它不是着色器资源,因此它不能在着色器代码中使用。在我看来,有两种方法可以解决您的任务:

  1. 研究 - Walkthrough: Using MF to render video in a Direct3D app - 此链接提供了“演练:使用 Microsoft Media Foundation for Windows Phone 8”的方式 - 从您的代码中我看到您尝试为 WindowsStore 编写解决方案 - UWP 和 Windows Phone 代码是可行的 - 此代码需要 MediaEnginePlayer - MediaEnginePlayer 类用作包装 MF API 的帮助程序类;

  2. 在 GitHub Windows-classic-samples 上查找并找到 DX11VideoRenderer - 这是使用 DirectX11 的 Media Foundation 渲染器的完整代码 - 它包含使用 DirectX11 视频处理器的非常好的示例将常规视频纹理从解码器传输到交换链的渲染视频纹理中:2.1.从交换链获取渲染纹理:

        // Get Backbuffer
    hr = m_pSwapChain1->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pDXGIBackBuffer);
    if (FAILED(hr))
    {
    break;
    }

    2.2。从视频处理器的渲染纹理输出 View 创建:

    //
    // Create Output View of Output Surfaces.
    //
    D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC OutputViewDesc;
    ZeroMemory( &OutputViewDesc, sizeof( OutputViewDesc ) );
    if (m_b3DVideo && m_bStereoEnabled)
    {
    OutputViewDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2DARRAY;
    }
    else
    {
    OutputViewDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
    }
    OutputViewDesc.Texture2D.MipSlice = 0;
    OutputViewDesc.Texture2DArray.MipSlice = 0;
    OutputViewDesc.Texture2DArray.FirstArraySlice = 0;
    if (m_b3DVideo && 0 != m_vp3DOutput)
    {
    OutputViewDesc.Texture2DArray.ArraySize = 2; // STEREO
    }

    QueryPerformanceCounter(&lpcStart);

    hr = m_pDX11VideoDevice->CreateVideoProcessorOutputView(pDXGIBackBuffer, m_pVideoProcessorEnum, &OutputViewDesc, &pOutputView);

2.3。从视频处理器的常规解码器视频纹理输入 View 创建:

    D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC InputLeftViewDesc;
ZeroMemory( &InputLeftViewDesc, sizeof( InputLeftViewDesc ) );
InputLeftViewDesc.FourCC = 0;
InputLeftViewDesc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
InputLeftViewDesc.Texture2D.MipSlice = 0;
InputLeftViewDesc.Texture2D.ArraySlice = dwLeftViewIndex;

hr = m_pDX11VideoDevice->CreateVideoProcessorInputView(pLeftTexture2D, m_pVideoProcessorEnum, &InputLeftViewDesc, &pLeftInputView);
if (FAILED(hr))
{
break;
}

2.4。在来自交换链的渲染纹理上执行常规解码器视频纹理的位 block 传输:

    D3D11_VIDEO_PROCESSOR_STREAM StreamData;
ZeroMemory( &StreamData, sizeof( StreamData ) );
StreamData.Enable = TRUE;
StreamData.OutputIndex = 0;
StreamData.InputFrameOrField = 0;
StreamData.PastFrames = 0;
StreamData.FutureFrames = 0;
StreamData.ppPastSurfaces = NULL;
StreamData.ppFutureSurfaces = NULL;
StreamData.pInputSurface = pLeftInputView;
StreamData.ppPastSurfacesRight = NULL;
StreamData.ppFutureSurfacesRight = NULL;

if (m_b3DVideo && MFVideo3DSampleFormat_MultiView == m_vp3DOutput && pRightTexture2D)
{
StreamData.pInputSurfaceRight = pRightInputView;
}

hr = pVideoContext->VideoProcessorBlt(m_pVideoProcessor, pOutputView, 0, 1, &StreamData );
if (FAILED(hr))
{
break;
}

是的,它们是复杂代码的部分,需要研究整个 DX11VideoRenderer 项目才能理解它 - 这将花费大量时间。

问候,

叶夫根尼·佩雷古达

关于c++ - 将 IMFSample* 转换为 ID3D11ShaderResourceView*,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45509705/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com