gst-launch-1.0 -v -e \
videotestsrc ! tee name=t0 \
t0. ! queue ! x264enc ! matroskamux ! filesink location="test.mkv" \
t0. ! queue ! queue ! autovideosink
正常工作,文件和屏幕显示均正常工作
gst-launch-1.0 -v -e \
videotestsrc ! tee name=t0 \
t0. ! queue ! x264enc ! matroskamux ! filesink location="test.mkv" \
t0. ! queue ! autovideosink
不起作用。
这是另一组例子。
gst-launch-1.0 -v -e \
videotestsrc ! tee name=t0 \
t0. ! queue ! autovideosink \
t0. ! queue ! autovideosink
作品。
gst-launch-1.0 -v -e \
videotestsrc ! tee name=t0 \
t0. ! queue ! autovideosink \
t0. ! autovideosink
不。为什么不?为什么发球台的两个输出都需要排队?在最坏的情况下,我希望一个autovideosink工作,另一个是空白,但一个显示一个帧,另一个是黑色。
但以下的工作正常。发生了什么事?
gst-launch-1.0 -v -e \
videotestsrc ! tee name=t0 \
t0. ! queue ! autovideosink \
t0. ! queue ! autovideosink \
t0. ! autovideosink
为什么添加第三个输出会否定对所有输出都需要队列?
gst-launch-1.0 --version
gst-launch-1.0 version 1.12.4
GStreamer 1.12.4
https://packages.gentoo.org/package/media-libs/gstreamer
有谁知道为什么队列的行为如此?
这是我正在尝试制作的管道。以上只是缩小的例子。
(注意:管道第一行中的怪异大写是为了确保我的Logitech c920相机输出h264而不是原始,我的Logitech BRIO输出1080p的视频jpeg,而不是原始的720p。这已经是经过测试,效果比简单的“decodebin”好得多。
gst-launch-1.0 -e \
v4l2src device=/dev/video0 ! 'video/x-h264;image/jpeg;video/x-raw' ! decodebin ! 'video/x-raw' ! tee name=t0 \
v4l2src device=/dev/video1 ! 'video/x-h264;image/jpeg;video/x-raw' ! decodebin ! 'video/x-raw' ! tee name=t1 \
v4l2src device=/dev/video2 ! 'video/x-h264;image/jpeg;video/x-raw' ! decodebin ! 'video/x-raw' ! tee name=t2 \
v4l2src device=/dev/video3 ! 'video/x-h264;image/jpeg;video/x-raw' ! decodebin ! 'video/x-raw' ! tee name=t3 \
matroskamux name=mux \
t0. ! queue ! autovideoconvert ! x264enc ! mux. \
t1. ! queue ! autovideoconvert ! x264enc ! mux. \
t2. ! queue ! autovideoconvert ! x264enc ! mux. \
t3. ! queue ! autovideoconvert ! x264enc ! mux. \
mux. ! queue ! filesink location="test.mkv" \
videomixer name=mix \
sink_0::zorder=1 sink_0::alpha=1.0 sink_0::ypos=0 sink_0::xpos=0 \
sink_1::zorder=1 sink_1::alpha=1.0 sink_1::ypos=0 sink_1::xpos=960 \
sink_2::zorder=1 sink_2::alpha=1.0 sink_2::ypos=540 sink_2::xpos=0 \
sink_3::zorder=1 sink_3::alpha=1.0 sink_3::ypos=540 sink_3::xpos=960 \
t0. ! queue ! autovideoconvert ! video/x-raw, width=960, height=540 ! mix.sink_0 \
t1. ! queue ! autovideoconvert ! video/x-raw, width=960, height=540 ! mix.sink_1 \
t2. ! queue ! autovideoconvert ! video/x-raw, width=960, height=540 ! mix.sink_2 \
t3. ! queue ! autovideoconvert ! video/x-raw, width=960, height=540 ! mix.sink_3 \
mix. ! queue ! autovideosink sync=false
通过在队列中添加max-size-bytes = 0 max-size-buffers = 0 max-size-time = 10000000000来解决这个问题。
对于没有进入gstreamer低级别比特的人来说,这是令人难以置信的反直觉。但是,如果它有效,我猜。
答案 0 :(得分:1)
了解GStreamer中PREROLLING
的概念:
https://gstreamer.freedesktop.org/documentation/design/preroll.html
一个sink元素只能在a之后完成对PAUSED的状态更改 缓冲区已在输入焊盘或焊盘上排队。
文档中没有强调的是,在所有接收器PAUSED
之后,管道只会从PLAYING
过渡到PREROLLED
。
另请注意,tee
没有线程,因此它会顺序推送下游的样本。
以下是发生的情况:接收器1接收样本,但不会开始播放,因为它等待直到管道中的所有其他接收器都收到样本,因此可以尊重音频/视频同步。
现在,接收器1正在等待它有效阻止tee
阻止它发送更多数据 - 在这种情况下,因此接收2.因为没有数据将到达接收器2,所以你处于死锁状态。
队列会自动在管道路径中添加一个线程作为副作用 - 防止死锁。
如果您只有一个队列,它实际上可以工作 - 这取决于您将接收器连接到发球台的顺序。如果首先传递带有队列的路径,它将不会死锁,并且tee可以将数据传递给另一个,并且状态更改将成功。 (与具有三个接收器的示例相同,如果所有路径都有队列但不是最后一个你可以使用它的话)
最好为所有tee
输出使用队列。
x264enc
示例特别棘手。你在这里遇到的问题是编码器消耗太多数据但没有产生任何(但是)有效地阻塞管道。
两种解决方法:
tune=zerolatency
作为x264enc
元素使用queue ! queue
,您实际上是通过将缓冲区大小加倍来执行大小写2.
。