有效地在 Direct3D 中渲染从 Media Foundation 获取的视频
Rendering video in Direct3D obtained from Media Foundation efficiently
我想有效地使用我正在从媒体基础解码的实时视频。
最初,我是 运行 在解码每一帧后同步渲染功能。传入的帧率约为 25-30 fps,但我想以 60fps 的速度渲染图形(游戏)内容。
如果我异步执行此操作,我将得到损坏的输出/黑屏/两者或由于激进锁定而导致帧率非常低。由于 GPU 操作是异步的,因此我无法找到合理的关键部分。这通常是如何完成的?我可以使用我的临时表面之一(source、dest 或 g_pDecodedTexture)作为同步点,并使用 CRITICAL_SECTION 环绕写入 it/them,但我不知道关键在哪里部分应该继续呈现(阅读)线程。如果我包围整个渲染函数,我的帧率会很低,如果我不这样做,我会得到不正确的输出。也许还有另一种更合适的同步方法。
在渲染设置时
hr = g_d3dDevice->CreateShaderResourceView(g_pDecodedTexture, &shaderResourceViewDesc, &g_pTextureRV);
在解码线程中
void Decode()
{
MFT_OUTPUT_DATA_BUFFER output = { 0 };
//...
encoder->ProcessOutput(0,1,&output,&status);
//
CComPtr<IMFMediaBuffer> spMediaBuffer;
CComPtr<IMFDXGIBuffer> spDXGIBuffer;
CComPtr<IDXGIResource> spDecodedTexture;
output.pSample->GetBufferByIndex(0, &spMediaBuffer);
spMediaBuffer->QueryInterface(IID_PPV_ARGS(&spDXGIBuffer);
spDXGIBuffer->GetResource(IID_PPV_ARGS(&spDecodedTexture);
//....
CComPtr<ID3D11Texture2D> source;
spDXGIBuffer->QueryInterface<ID3D11Texture2D>(&source);
//
CComPtr<ID3D11Resource> dest;
swapChain->GetBuffer(0, __uuidof(ID3D11Resource), (void**)&dest);
deviceContext->CopyResource(dest, source);
deviceContext->CopyResource(g_pDecodedTexture, source);
}
在渲染线程中
void Render()
{
//...
deviceContext->PSSetShaderResources(0, 1, &g_pTextureRV);
//..
m_deviceContext->VSSetShaderResources(0, 1, &g_pTextureRV);
//..
immediateContext->DrawIndexed(...);
//..
immediateContext->DrawIndexed(...);
//..
immediateContext->DrawIndexed(...);
//..
immediateContext->DrawIndexed(...);
//
Present();
}
您可以试试这个:在解码器之后插入帧率转换器 DSP。请确保您的输入格式与 DSP 兼容。将帧速率设置为 60 fps。
这样做,我认为你可以保持同步方法。
如果要手动以 60 fps 显示,我们需要更多代码来查看问题出在哪里。
我想有效地使用我正在从媒体基础解码的实时视频。 最初,我是 运行 在解码每一帧后同步渲染功能。传入的帧率约为 25-30 fps,但我想以 60fps 的速度渲染图形(游戏)内容。 如果我异步执行此操作,我将得到损坏的输出/黑屏/两者或由于激进锁定而导致帧率非常低。由于 GPU 操作是异步的,因此我无法找到合理的关键部分。这通常是如何完成的?我可以使用我的临时表面之一(source、dest 或 g_pDecodedTexture)作为同步点,并使用 CRITICAL_SECTION 环绕写入 it/them,但我不知道关键在哪里部分应该继续呈现(阅读)线程。如果我包围整个渲染函数,我的帧率会很低,如果我不这样做,我会得到不正确的输出。也许还有另一种更合适的同步方法。
在渲染设置时
hr = g_d3dDevice->CreateShaderResourceView(g_pDecodedTexture, &shaderResourceViewDesc, &g_pTextureRV);
在解码线程中
void Decode()
{
MFT_OUTPUT_DATA_BUFFER output = { 0 };
//...
encoder->ProcessOutput(0,1,&output,&status);
//
CComPtr<IMFMediaBuffer> spMediaBuffer;
CComPtr<IMFDXGIBuffer> spDXGIBuffer;
CComPtr<IDXGIResource> spDecodedTexture;
output.pSample->GetBufferByIndex(0, &spMediaBuffer);
spMediaBuffer->QueryInterface(IID_PPV_ARGS(&spDXGIBuffer);
spDXGIBuffer->GetResource(IID_PPV_ARGS(&spDecodedTexture);
//....
CComPtr<ID3D11Texture2D> source;
spDXGIBuffer->QueryInterface<ID3D11Texture2D>(&source);
//
CComPtr<ID3D11Resource> dest;
swapChain->GetBuffer(0, __uuidof(ID3D11Resource), (void**)&dest);
deviceContext->CopyResource(dest, source);
deviceContext->CopyResource(g_pDecodedTexture, source);
}
在渲染线程中
void Render()
{
//...
deviceContext->PSSetShaderResources(0, 1, &g_pTextureRV);
//..
m_deviceContext->VSSetShaderResources(0, 1, &g_pTextureRV);
//..
immediateContext->DrawIndexed(...);
//..
immediateContext->DrawIndexed(...);
//..
immediateContext->DrawIndexed(...);
//..
immediateContext->DrawIndexed(...);
//
Present();
}
您可以试试这个:在解码器之后插入帧率转换器 DSP。请确保您的输入格式与 DSP 兼容。将帧速率设置为 60 fps。
这样做,我认为你可以保持同步方法。
如果要手动以 60 fps 显示,我们需要更多代码来查看问题出在哪里。