You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用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);
    

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着色器完成转换:
    1. 创建YUV格式的纹理和着色器资源视图(SRV)。
    2. 编写像素着色器实现YUV转RGB的算法。
    3. 将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 16:33:34