如何使用挂件输入启动管道

时间:2016-07-01 15:58:21

标签: gstreamer python-gstreamer

我现在在具有以下配置的管道上工作了几天: - 2个实时输入流(RTMP) - 进入一个合成器 - 输出到另一个RTMP流

在它们之间有一些转换器,队列等,它工作得很好。

但我的问题是其中一个RTMP输入在启动时可能无法使用,因此管道无法启动,因以下错误而崩溃: - 错误:无法从流中读取任何数据 - 错误:内部数据流错误

使用第一个输入启动流的正确方法是什么,即使第二个输入尚未就绪?

我尝试了几种方法:动态更改管道,使用pad探测器,监听错误消息,但是到目前为止我无法使其工作。

谢谢, PL

2 个答案:

答案 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')。在这里再一次,这完美无缺,直到我得到两个输入到合成器。这就是它开始冻结的地方。

从我可以阅读的内容来看,它可能来自延迟和/或时钟,但我无法解决问题。 有趣的是,当我使用两个输入流启动管道时,我没有问题。

你知道为什么它有不同的行为吗?