GStreamer1.18硬件解码时如何从nvh264dec输出缓冲区读取GPU数据
GStreamer 1.18 Python自定义插件读取nvh264dec GPU内存方案
nvh264dec输出的缓冲区默认是GstCudaBuffer类型,绑定了CUDA设备指针,没有主动触发特殊映射操作的话默认不会拷贝到主机端,你当前读到主机端数据是因为GStreamer默认的缓冲区普通映射操作触发了隐式的GPU到主机拷贝。
操作步骤
- 首先确认环境已经安装了带CUDA支持的
gst-plugins-bad组件,Python侧先加载对应版本的GstCuda模块:
import gi gi.require_version('Gst', '1.0') gi.require_version('GstCuda', '1.0') from gi.repository import Gst, GstCuda Gst.init(None)
- 自定义元件的sink pad协商阶段,需要明确声明支持CUDA内存类型,避免nvh264dec提前触发GPU到主机的数据拷贝。可以在sink pad模板中配置支持CUDA内存的caps,示例如下:
video/x-raw(memory:CudaMemory), format=(string)NV12, width=(int)[1, 2147483647], height=(int)[1, 2147483647], framerate=(fraction)[0/1, 2147483647/1] - 在chain函数中直接提取缓冲区的CUDA设备指针,不要调用默认的缓冲区map操作:
def do_chain(self, pad, buf): # 校验缓冲区是否为CUDA内存类型 if GstCuda.buffer_is_cuda_buffer(buf): # 提取缓冲区绑定的CUDA内存对象 cuda_mem = GstCuda.buffer_peek_cuda_memory(buf, 0) # 获取该内存对应的CUDA上下文 cuda_ctx = GstCuda.memory_get_context(cuda_mem) # 拿到GPU端设备指针,返回值为int类型的指针地址 dev_ptr = GstCuda.memory_get_device_pointer(cuda_mem) # 此处可对接你自己的CUDA处理逻辑:比如通过PyCUDA将dev_ptr转为DeviceAllocation对象直接在GPU侧读写数据 # 注意所有CUDA操作必须在cuda_ctx对应的上下文中执行 else: # fallback到普通系统内存的处理逻辑 pass return Gst.FlowReturn.OK
注意事项
- 拿到的
dev_ptr是GPU地址空间的指针,不能直接在主机侧访问,否则会触发段错误,必须通过CUDA相关的库(PyCUDA、CUDA Python等)操作 - 处理CUDA内存期间不要调用
buf.map(Gst.MapFlags.READ)这类普通映射操作,会触发隐式GPU到主机拷贝,产生额外性能开销 - 如果处理完的数据需要传递给下游元件,不需要拷回主机端,直接传递原缓冲区或者封装新的
GstCudaBuffer即可,支持CUDA内存的下游元件可以直接读取 - 若当前环境的GstCuda没有Python GI绑定,可以通过
ctypes调用libgstcuda-1.0.so的对应C接口获取设备指针,接口命名和上述GstCuda方法完全一致
内容的提问来源于stack exchange,提问作者Adam green
相关产品推荐
相关产品推荐

