使用 GStreamer 和 NVENC 编码 OpenGL 纹理?
Posted
技术标签:
【中文标题】使用 GStreamer 和 NVENC 编码 OpenGL 纹理?【英文标题】:Encode OpenGL texture using GStreamer & NVENC? 【发布时间】:2020-01-24 19:39:42 【问题描述】:我有一个将数据渲染成 rgba 纹理的 openGL 应用程序。我想使用 gstreamer 框架对其进行编码和流式传输(使用 nvenc 插件进行 h264 编码)。
我正在查看文档以解决这些问题:
-
如何将应用的现有 openGL 上下文导出到 nvenc 元素。
如何将纹理 ID 传递给来源?
同步将如何工作。即 nvenc 必须等待渲染完成,同样应用程序必须等待 nvenc 完成从纹理中读取。我假设它会涉及使用同步栅栏或 glMemoryBarriers。
任何示例代码都会非常有帮助。
我确实想避免将任何纹理复制到 cpu 内存。 Nvidia 的 NVENC sdk 提到它使用 CUDA 上下文进行调用,并且可以使用 cudaGraphicsGLRegisterImage 调用将 openGL 纹理导入到 CUDA 上下文中。所以我的期望是,从app到视频的编码帧可以不用任何副本就可以完成。
【问题讨论】:
【参考方案1】:我知道这是一个老问题,但以防万一其他人遇到这个问题......
如果您的 NVENC 调用和 OpenGL 应用程序在同一个线程中,则无需对上下文执行任何操作。
如果没有,您可能应该创建两个 OpenGL 上下文,一个用于渲染,一个用于编码。这两个上下文应该共享对象,如https://www.khronos.org/opengl/wiki/OpenGL_Context 中所述。
您也可以只创建一个上下文并在线程之间传输上下文,方法是将其设置为“当前”到访问 OpenGL 对象的线程,但我发现这两个上下文更容易。
Texture id 是一个整数,直接传过去就行了。
NvEncMapInputResource“提供同步保证,在输入缓冲区用于编码之前,提交的任何图形或计算工作都已完成”。 NvEncEncodePicture 具有“同步编码模式”。
截至今天,NVENC 在 linux 上支持 OpenGL 编码设备,因此您不必在 CUDA 中注册 OpenGL 纹理。 NVENC可以直接访问OpenGL纹理,所以客户端没有内存拷贝。
如果你在 windows 上工作,我相信你可以创建一个 CUDA 编码设备,然后从 OpenGL 纹理中获取一个 CUarray,NVENC 可以访问 CUarray。
OpenGL 和 CUDA 编码设备的示例代码可以在 NVENC SDK 示例中找到。
编辑:
NvEncMapInputResource 的同步保证似乎只适用于单线程情况(或在相同的 GL 上下文中?)。如果渲染和编码发生在不同的线程和上下文中,则必须在映射之前添加同步对象。
【讨论】:
以上是关于使用 GStreamer 和 NVENC 编码 OpenGL 纹理?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 NVidia NVEnc 硬件编码器通过 UDP 流式传输 H.264 视频?