调用ID3D11DeviceContext::CopySubresourceRegion渲染摄像头视频遇ERROR #281
解决DirectX CopySubresourceRegion资源格式不匹配(ERROR #281)问题
1. 对齐Media Foundation帧格式与DirectX纹理格式
- 强制
IMFSourceReader输出与DirectX纹理一致的像素格式:摄像头默认多输出YUV格式(如MFVideoFormat_NV12),若你的D3D纹理用DXGI_FORMAT_B8G8R8A8_UNORM,需将SourceReader输出类型设为MFVideoFormat_RGB32(MF与DXGI格式的映射需严格对应)。IMFMediaType* pOutputType = nullptr; MFCreateMediaType(&pOutputType); pOutputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); pOutputType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32); pSourceReader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, nullptr, pOutputType); pOutputType->Release(); - 回调中验证帧格式:获取
IMFSample的媒体类型,确认实际输出格式与设置一致,避免MF自动 fallback 到不兼容格式。IMFMediaType* pFrameType = nullptr; pSample->GetMediaType(&pFrameType); GUID subType; pFrameType->GetGUID(MF_MT_SUBTYPE, &subType); // 检查subType是否等于MFVideoFormat_RGB32(或你指定的格式) pFrameType->Release();
2. 修正DirectX纹理创建参数
- 确保中间 staging 纹理(用于接收CPU帧数据)与交换链纹理的格式、维度完全匹配:
- staging 纹理需设为
D3D11_USAGE_STAGING并开启D3D11_CPU_ACCESS_WRITE,交换链纹理为D3D11_USAGE_DEFAULT。 - 禁止使用
DXGI_FORMAT_UNKNOWN,必须明确指定格式。
D3D11_TEXTURE2D_DESC stagingDesc = {}; stagingDesc.Width = frameWidth; stagingDesc.Height = frameHeight; stagingDesc.MipLevels = 1; stagingDesc.ArraySize = 1; stagingDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // 与MF输出、交换链格式一致 stagingDesc.SampleDesc.Count = 1; stagingDesc.Usage = D3D11_USAGE_STAGING; stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; pD3DDevice->CreateTexture2D(&stagingDesc, nullptr, &pStagingTexture); - staging 纹理需设为
3. 规范CopySubresourceRegion调用参数
- 确认源/目标资源的子资源索引、区域尺寸匹配,且格式完全一致:
- 获取交换链后台缓冲区时,需验证其格式与staging纹理是否相同,不匹配则不能直接拷贝。
ID3D11Texture2D* pBackBuffer = nullptr; pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pBackBuffer); D3D11_TEXTURE2D_DESC backDesc, stagingDesc; pBackBuffer->GetDesc(&backDesc); pStagingTexture->GetDesc(&stagingDesc); if (backDesc.Format != stagingDesc.Format) { // 格式不匹配,需重新设置MF输出格式或转换纹理 // 例如重新创建适配格式的staging纹理 } pImmediateContext->CopySubresourceRegion(pBackBuffer, 0, 0, 0, 0, pStagingTexture, 0, nullptr); pBackBuffer->Release();
4. 处理YUV到RGB的格式转换(若摄像头输出YUV)
- 若需保留YUV原始格式,不能直接拷贝到RGB纹理,需通过DirectX着色器完成转换:
- 创建YUV格式的纹理和着色器资源视图(SRV)。
- 编写像素着色器实现YUV转RGB的算法。
- 将SRV绑定到渲染管线,通过DrawCall输出到交换链。
5. 启用调试层定位细节问题
- 创建D3D设备时添加
D3D11_CREATE_DEVICE_DEBUG标志,调试层会输出精确的资源格式不匹配日志,指明哪两个资源格式冲突:UINT createDeviceFlags = 0; #ifdef _DEBUG createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, nullptr, 0, D3D11_SDK_VERSION, &pD3DDevice, nullptr, &pImmediateContext); - 直接检查
CopySubresourceRegion的返回HRESULT,用FormatMessage获取详细错误描述,避免仅依赖调试错误码。
内容的提问来源于stack exchange,提问作者c00000fd
相关产品推荐
相关产品推荐

