2

我正在尝试使用 Desktop Duplication API 捕获桌面帧,并立即使用 NvPipe 对其进行编码,而无需通过 CPU 访问像素。

有什么方法可以将 ID3D11Texture2D 数据作为 NvPipe 的输入,或者其他一些有效的方法?我正在开发一个需要尽可能低延迟的 VR 解决方案,因此即使节省 1 毫秒也是一件大事。

编辑:在遵循@Soonts 的建议之后,我得到了这个似乎不起作用的代码:

    cudaArray *array;
    m_DeviceContext->CopySubresourceRegion(CopyBuffer, 0, 0, 0, 0, m_SharedSurf, 0, Box);
    cudaError_t err = cudaGraphicsD3D11RegisterResource(&_cudaResource, CopyBuffer, cudaGraphicsRegisterFlagsNone);
    err = cudaGraphicsResourceSetMapFlags(_cudaResource, cudaGraphicsMapFlagsReadOnly);
    cudaStream_t cuda_stream;
    cudaStreamCreate(&cuda_stream);
    err = cudaGraphicsMapResources(1, &_cudaResource, cuda_stream);
    err = cudaGraphicsSubResourceGetMappedArray(&array, _cudaResource, 0, 0);
    uint64_t compressedSize = NvPipe_Encode(encoder, array, dataPitch, buffer.data(), buffer.size(), width, height, false);

NvPipe_Encode 导致内存访问冲突并且什么都不做。我不知道我搞砸了哪一步,因为我似乎无法在网上找到任何关于任何函数或变量/结构的文档,并且将手表放在变量上除了它们在内存中的地址之外没有显示任何有价值的信息。

4

1 回答 1

2

我没有尝试过,但我认为应该可以使用 CUDA 互操作。

调用cudaGraphicsD3D11RegisterResource为 CUDA 互操作注册纹理。不确定是否可以注册从 DD 获得的 DWM 拥有的纹理。如果不能,请制作另一个(在默认池中),注册那个,并使用 ID3D11DeviceContext::CopyResource 更新每一帧。

调用cudaGraphicsResourceSetMapFlags以指定您希望从互操作的 CUDA 端进行只读访问。

调用cudaGraphicsMapResources以允许 CUDA 访问纹理。

打电话cudaGraphicsSubResourceGetMappedArray。现在您有了一个设备指针,其中包含可以提供给 NvPipe 的帧数据。

PS 其他选项是使用媒体基础而不是 NvPipe。不仅适用于 nVidia,适用于所有 GPU,在大多数系统上,MF 还使用硬件编码器。我不确定延迟,从未将 MF 用于对其过于敏感的任何事情,也从未使用过 NvPipe,不知道它们如何比较。

于 2019-05-30T14:20:59.213 回答