python - GStreamer 零拷贝只读缓冲区复制
问题描述
我有一个带有 appsink 的 GStreamer 管道
filesrc location=test.mp4 ! decodebin ! video/x-raw ! queue max-size-bytes=0 max-size-time=100000000 ! appsink name=appSink sync=false max-buffers=1 drop=false
我从应用程序接收器中提取样本,然后获取缓冲区,将其映射为只读并存储映射信息(以便稍后访问原始内存)。
sample: Gst.Sample = self.__sink.pull_sample()
self.__buffer: Gst.Buffer = sample.get_buffer()
self.__buffer_map: Gst.MapInfo = self.__buffer.map(Gst.MapFlags.READ)
然后我想在输出管道中使用相同的数据(不复制它),例如:
appsrc name=appSrc block=true ! video/x-raw,format=(string)NV12,width=1920,height=1080,framerate=30/1 ! videoconvert ! ximagesink
要做到这一点,这是我能想到的最好的:
shared_buffer_memory = self.__buffer.get_all_memory()
buf = Gst.Buffer.new()
buf.insert_memory(-1, shared_buffer_memory)
self.__src.push_buffer(buf)
#sleep(0.05)
如果我这样做,我会正确看到第一帧,但所有其他帧都是绿色的。没关系,因为 buf 的底层内存超出范围并同时释放。如果我将 sleep(0.05) 放在 push_buffer 之后,它会显示所有帧,但我认为缓冲区后面的内存是双重释放的:
** (python3.9:6745): CRITICAL **: 09:23:54.645: gst_vaapi_image_unmap: assertion 'image != NULL' failed
我想从应用程序接收器中获取帧,然后将它们推送到输出管道而不复制。这样做的最佳方法是什么?(在我的情况下,单个管道不适合)。
解决方案
答案不是我的,我是在#gstreamer IRC 频道上得到的:
该文档说明了以下内容:
AppSrc.push_buffer(buffer):将缓冲区添加到应用程序元素将推送到其源垫的缓冲区队列中。此函数获取缓冲区的所有权。
这就是误导我的原因。在 Python 中,应该很容易地将同一个缓冲区推送到多个 AppSrc。
推荐阅读
- docker - 如何使用 dockerode 推送图像?(图像未推送但没有错误)
- ajax - 有没有办法通过返回 emptyresult() 的 MVC 操作在 ajax 成功响应中获得任何东西
- javascript - 获取请求失败并出现错误:连接 ECONNREFUSED
- php - 从 CodeIgniter 中的视图调用路由
- javascript - 位置相同时链接组件更新浏览器历史记录
- javascript - 反应整页js如何使用silentMoveTo函数
- asp.net - Microsoft Teams:如何在没有机器人的情况下从外部应用程序向用户发送消息/卡片
- macos - 如何使用 io.open 在 Lua/MacOS 中访问 .suit 字体文件?.ttf/.otf 工作正常,西装不行
- python - Python 无法安装 Box2D swig.exe 失败,错误代码为 1
- angular - Angular 在对象中使用服务或在构造函数中使用服务创建对象