GStreamer 零拷贝只读缓冲区复制
GStreamer zero copy read only buffer duplication
我有一个带有 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
我从 appsink 中提取样本,然后获取缓冲区,将其映射为只读并存储映射信息(以便稍后访问原始内存)。
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
我想从 appsink 获取帧,然后将它们推入输出管道而不复制。这样做的最佳方法是什么? (单个管道不适合我的情况)。
答案不是我的,我是在#gstreamer IRC 频道上得到的:
documentation 表示如下:
AppSrc.push_buffer(buffer): Adds a buffer to the queue of buffers that
the appsrc element will push to its source pad. This function takes
ownership of the buffer.
这就是误导我的原因。在 Python 中,应该可以轻松地将同一个缓冲区推送到多个 AppSrc。
这似乎是您想要在继续编写代码之前完成的线程,例如:
from threading import Thread
from time import sleep
def a():
print('start')
sleep(1)
print('middle')
sleep(1)
print('end')
c = Thread(target=a)
print('Hello')
c.start()
print('Bye')
sleep(3)
输出:
Hello
startBye
middle
end
说 c
是线程,你可以想办法在你的代码中的某一行添加 c.join()
这样程序就会知道在继续程序之前等待进程完成:
from threading import Thread
from time import sleep
def a():
print('start')
sleep(1)
print('middle')
sleep(1)
print('end')
c = Thread(target=a)
print('Hello')
c.start()
a.join()
print('Bye')
sleep(3)
输出:
Hello
start
middle
end
Bye
更新
查看您的代码结构:
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)
你说它 和 sleep(0.05)
一起工作,但没有它就不能正常工作。可能发生的原因是因为一个线程。为了使其工作,您需要通过在代码中的某处添加 .join()
来反转线程的影响。
我有一个带有 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
我从 appsink 中提取样本,然后获取缓冲区,将其映射为只读并存储映射信息(以便稍后访问原始内存)。
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
我想从 appsink 获取帧,然后将它们推入输出管道而不复制。这样做的最佳方法是什么? (单个管道不适合我的情况)。
答案不是我的,我是在#gstreamer IRC 频道上得到的:
documentation 表示如下:
AppSrc.push_buffer(buffer): Adds a buffer to the queue of buffers that the appsrc element will push to its source pad. This function takes ownership of the buffer.
这就是误导我的原因。在 Python 中,应该可以轻松地将同一个缓冲区推送到多个 AppSrc。
这似乎是您想要在继续编写代码之前完成的线程,例如:
from threading import Thread
from time import sleep
def a():
print('start')
sleep(1)
print('middle')
sleep(1)
print('end')
c = Thread(target=a)
print('Hello')
c.start()
print('Bye')
sleep(3)
输出:
Hello
startBye
middle
end
说 c
是线程,你可以想办法在你的代码中的某一行添加 c.join()
这样程序就会知道在继续程序之前等待进程完成:
from threading import Thread
from time import sleep
def a():
print('start')
sleep(1)
print('middle')
sleep(1)
print('end')
c = Thread(target=a)
print('Hello')
c.start()
a.join()
print('Bye')
sleep(3)
输出:
Hello
start
middle
end
Bye
更新
查看您的代码结构:
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)
你说它 和 sleep(0.05)
一起工作,但没有它就不能正常工作。可能发生的原因是因为一个线程。为了使其工作,您需要通过在代码中的某处添加 .join()
来反转线程的影响。