我现在在具有以下配置的管道上工作了几天: - 2个实时输入流(RTMP) - 进入一个合成器 - 输出到另一个RTMP流
在它们之间有一些转换器,队列等,它工作得很好。
但我的问题是其中一个RTMP输入在启动时可能无法使用,因此管道无法启动,因以下错误而崩溃: - 错误:无法从流中读取任何数据 - 错误:内部数据流错误
使用第一个输入启动流的正确方法是什么,即使第二个输入尚未就绪?
我尝试了几种方法:动态更改管道,使用pad探测器,监听错误消息,但是到目前为止我无法使其工作。
谢谢, PL
答案 0 :(得分:0)
由于你没有发布任何代码,我猜你的概念性回答是正确的。
rtspsrc的选项很少,您可以控制它何时失败 - 超过超时或超过最大值的试验次数。那些(不确定是否全部):
retry - this may be not very useful if it deals only with ports ..
timeout - if you want to try with UDP some longer time you can enlarge this one
tcp-timeout - this is important, try to play with it - make it much larger
connection-speed - maybe it will help to make smaller this one
protocols - I have experience that for bad streams TCP was much better for me
实际概念(我不是专家,把它作为问题的另一种观点):
您可以创建两个分箱 - 每个分段一个。我会使用rtspsrc和decodebin并阻塞decodebin的输出焊盘,直到我有所有的焊盘,然后我会连接到合成器。
当你收到任何错误时(它应该在等待所有打击垫的阶段)然后你将bin置于NULL状态(我的意思是GStreamer状态称为NULL)和PLAYING / PAUSED再次.. 那么你必须正确使用pad probles(不知道那是什么:D)..你可以发布你的代码吗? 也许尝试丢弃错误消息,以免分解管道..
另外,你只有视频输入吗?
我想不,你可以使用audiomixer进行音频..也就是合成器有很好的OpenGL版本,它的速度要快得多glvideomixer
..但它可能会引入另一个与OpenGL相关的问题..如果你有英特尔GPU那么你就是可能很安全。
答案 1 :(得分:0)
感谢@otopolsky的输入。 我不确定你对rtspsrc属性的评论,因为我使用的是rtmpsrc。
无论如何,我试图遵循将输入流放入箱中的想法。 为了我的演示代码,我只针对一个输入流进行了操作,将所有音频内容放在一边。
管道如下:
rtmpsrc => decodebin => videoscale => videorate => capsfilter
=> compositor.sink_0 => capsfilter => x264enc => flvmux => rtmpsink
一旦管道处于PLAYING状态,我就构建了bin,从而确保bin被动态地添加到管道中。 bin获得了第二个输入的所有元素:
rtmpsrc => decodebin => videoscale => videorate => capsfilter
我还为垃圾箱设置了一个鬼垫,我使用一个探针来完成垃圾箱和管道之间的实际连接:
def _prob_block(self, pad, info, data):
pad.remove_probe(info.id)
src_pad = self.bin.get_static_pad('src')
sink_pad = self.compositor.get_request_pad('sink_1')
src_pad.link(sink_pad)
return Gst.PadProbeReturn.OK
ghost_pad = Gst.GhostPad.new('src', self.capsfilter_video_ben.get_static_pad('src'))
self.bin.add_pad(ghost_pad)
ghost_pad.add_probe(Gst.PadProbeType.BLOCK_DOWNSTREAM, self._prob_block, None)
然后,我的应用程序有这个伪代码:
def _activate_bin():
# ... this is where I create bin along with bin elements
# ... and create the ghost pad (see above)
# Then add the bin to the pipeline
pipe._pipeline.add(bin)
bin.set_state(Gst.State.PLAYING)
pipe = Pipeline()
GObject.timeout_add_seconds(10, _activate_bin)
pipe._pipeline.set_state(Gst.State.PLAYING)
这几乎完美无缺,管道以一个输入(sink_0)开始,该输入通过合成器然后进入rtmpsink(我实际上可以播放输出流)。 然后10秒钟后,我将bin添加到管道中(合成器的pad'spool_1')。在这里再一次,这完美无缺,直到我得到两个输入到合成器。这就是它开始冻结的地方。
从我可以阅读的内容来看,它可能来自延迟和/或时钟,但我无法解决问题。 有趣的是,当我使用两个输入流启动管道时,我没有问题。
你知道为什么它有不同的行为吗?