0

当我有多个 gstreamer 进程同时运行时,我无法从 appsrc 保存到 filesink。只有一个 gstreamer 进程会正确写入,而其他进程都将写入几乎是空的文件。在文件接收器操作期间似乎存在写入争用。

注意:我在 MAC OS 10.11.6 上使用 gstreamer1.0 (v1.8.2) 和 python3 (v3.5.2)。

这是我的代码实际上在做什么:

在后台,我从单个视频流中读取帧,将每个帧转换为大小为 1920x800x3 的 BGR numpy 数组,并将每个帧存储在循环缓冲区中。我已经构建了一个“gstreamer_writer 函数”,它从这个循环缓冲区中读取帧,将这些帧转换为字节流,并将这个流提供给 appsrc。

这通过实例化一个新的多进程(multiprocessing.Process)并将其指向“gstreamer_writer 函数”来工作。这对于单个多进程/函数调用完全正常。Appsrc 已正确输入字节流,我使用以下 gstreamer 管道将这些 BGR 帧保存到具有 h264 编码的 mp4 中:

appsrc format=3 name=app emit-signals=true do-timestamp=true is-live=true blocksize=4608000 max-bytes=0 caps=video/x-raw,format=BGR,width=1920,height=800 ! videoconvert ! video/x-raw,format=I420,width=1920,height=800 ! vtenc_h264 ! mp4mux ! filesink location=test1.mp4

但是,如果我实例化两个或多个多进程并将它们指向函数,则只有一个文件接收器可以正常工作。例如,如果一个正在写入“test1.mp4”而另一个正在写入“test2.mp4”,那么其中一个视频将被正确写入,而另一个将失败并写入一个几乎为空的 mp4 (~500kb)。它并不总是相同的 mp4,50% 的时间 test1.mp4 正确编写,50% 的时间 test2.mp4 正确编写。看起来有某种竞争条件或写入争用阻止了两个 mp4 正确写入文件。

需要注意的一点是,每个多进程都从同一个环形缓冲区访问相同的帧。我认为这可能会导致 gstreamer 出现问题。但是,如果我使用 autovideosink 显示流而不是将它们写入文件,我可以显示任意数量的流/多进程。这意味着数据正在正确地通过管道传递,并且仅在写入阶段失败。我使用 gstreamer 命令对此进行了测试:

appsrc format=3 name=app emit-signals=true do-timestamp=true is-live=true blocksize=4608000 max-bytes=0 caps=video/x-raw,format=BGR,width=1920,height=800 ! videoconvert ! video/x-raw,format=I420,width=1920,height=800 ! vtenc_h264 ! avdec_h264 ! autovideosink

如果有人对我如何解决这个问题有任何建议,我将不胜感激。我希望这是一个简单的改变,但你永远不会知道 gstreamer!

谢谢!

4

1 回答 1

0

太长的评论,如果我是正确的,这可以解决你的问题..

在文件接收器之前添加队列:

appsrc format=3 name=app emit-signals=true do-timestamp=true is-live=true blocksize=4608000 max-bytes=0 caps=video/x-raw,format=BGR,width=1920,height=800 ! videoconvert ! video/x-raw,format=I420,width=1920,height=800 ! queue ! vtenc_h264 ! mp4mux ! queue ! filesink location=test1.mp4

队列有两个功能: + 在消费元素之前创建一个缓冲区(哪个编码器是 - 它需要很多帧才能开始编码) + 将进一步处理分离到新线程中 - 以便文件接收器将在新线程中处理数据。

高温高压

于 2016-08-12T07:01:40.950 回答