Python 等价于 gst_element_link_many?

Python equivalence for gst_element_link_many?

我似乎无法在 Python 的 gst 管道中 link 超过 3 个元素。例如,我尝试在 Python.

中实现以下 cli 命令
gst-launch-1.0 filesrc location=cooldance.ogg ! oggdemux ! theoradec ! videoconvert ! autovideosink

由于C函数gst_element_link_many()没有Python等价关系,我试着一一联系起来:

import sys, os
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst

class TestPlayer(object):
    
    def __init__(self):
        
        self.player = Gst.Pipeline.new("player")

        source = Gst.ElementFactory.make("filesrc", "file-source")
        demux = Gst.ElementFactory.make("oggdemux", "demux1")
        decode = Gst.ElementFactory.make("theoradec", "decode1")
        sink = Gst.ElementFactory.make("autovideosink", "sink1")
        
        source.set_property("location", "/ione/gsttest/sample.ogg")

        # Try to implement this pipeline using multiple links.
        #self.player = Gst.parse_launch ("filesrc location=sample.ogg ! oggdemux ! theoradec ! autovideosink")
        
        self.player.add(source)
        self.player.add(demux)
        self.player.add(decode)
        self.player.add(sink)

        # link elements one by one.
        source.link(demux)
        demux.link(decode)
        decode.link(sink)
        
        ret = self.player.set_state(Gst.State.PLAYING)
        if ret == Gst.StateChangeReturn.FAILURE:
            print("ERROR: Unable to set the pipeline to the playing state")
            sys.exit(1)

        bus = self.player.get_bus()
        terminate = False
        while True:
            msg = bus.timed_pop_filtered(
                Gst.CLOCK_TIME_NONE,
                Gst.MessageType.EOS | Gst.MessageType.ERROR)  # listen on these types,.

            if not msg:
                continue

            t = msg.type
            if t == Gst.MessageType.ERROR:  # exit if error.
                err, dbg = msg.parse_error()
                print("ERROR:", msg.src.get_name(), " ", err.message)
                if dbg:
                    print("debugging info:", dbg)
                terminate = True
            elif t == Gst.MessageType.EOS:  # exit if EOS
                print("End-Of-Stream reached")
                terminate = True

            if terminate:
                break

        self.player.set_state(Gst.State.NULL)

if __name__ == '__main__':
    Gst.init(None)
    p = TestPlayer()

但是脚本失败并显示以下错误消息:

ERROR: demux1   Internal data stream error.
debugging info: gstoggdemux.c(4961): gst_ogg_demux_loop (): /GstPipeline:player/GstOggDemux:demux1:
streaming stopped, reason not-linked (-1)

我在 github 上找到了一些样本,但它们都失败了,并出现了类似的错误。请指教

您的问题源于对延迟 linking 的不正确理解。

gstreamer 中的垫可以 linked 当且仅当它们同意它们的格式。对于某些元素,所有可能的填充格式都是已知的 ahead-of-time。这意味着它们可以提前 linked,具有 link_maylink 等功能。例如,从 gst-inspect-1.0 oggdemux 的 pad 部分,我们看到这个:

Pad Templates:
  SINK template: 'sink'
    Availability: Always
    Capabilities:
      application/ogg
      audio/ogg
      video/ogg
      application/kate

这是一个可以 link 静态的水槽垫。 oggdemux 总会有一个水槽垫,它可以是此处列出的 4 种功能之一。

然而,关于它的 src 模板却不能这样说:

  SRC template: 'src_%08x'
    Availability: Sometimes
    Capabilities:
      ANY

由于ogg的内部结构,无法提前知道确切的src pad数量。相反,在管道功能期间,ogg-demux 根据需要添加焊盘。也许它有视频和音频数据,所以它会即时创建两个 pad,一个用于音频,一个用于视频。也许在 运行 的时候它没有任何音频,所以它只制作视频板,反之亦然。

因为 oggdemux 动态分配它的一些垫,你不能提前静态地 link 它。对于如何处理此问题,您有两种选择。

选项 1:

切换到只有静电垫的东西。 h264parse 就是一个例子。从gst-inspect-1.0我们看到:

Pad Templates:
  SRC template: 'src'
    Availability: Always
    Capabilities:
      video/x-h264
                 parsed: true
          stream-format: { (string)avc, (string)avc3, (string)byte-stream }
              alignment: { (string)au, (string)nal }

  SINK template: 'sink'
    Availability: Always
    Capabilities:
      video/x-h264

它总是有一个 src 和一个 sink,并且它们总是输出完全相同的格式。这可以link提前静态编辑,没有问题。

选项 2:

您可以在 ogg-demux 上安装回调并等待它发出 pad-added 信号。在此信号上,您可以回调 link 新垫。这有利于支持动态管道,并避免 allocations/links 不需要制作。这也是 gst-launch-1.0 内部正在做的事情。但是,请注意。这是很多额外的工作,它更脆弱,而且可能不是你想要的。如果您可以摆脱它,请尝试使用选项 1。但是,可以说您不在乎并且无论如何都想这样做。祝你好运! gstreamer docs 包含实现此行为所需的所有信息。


注意:oggdemux 可能不是您管道中唯一带有有时垫的元素,请确保检查所有元素

注意 2:如果您将环境变量 GST_DEBUG 设置得足够高(可能是 4,也许是 5?),然后 运行 使用 gst-launch-1.0 的管道,日志输出将描述动态垫 linking 的详细信息,这对于了解您的管道实际在做什么应该非常有帮助。