将 gstreamer 管道转换为 python 代码

convert gstreamer pipeline to python code

我正在尝试使用 gi 库将 gstreamer 管道转换为 python 代码。

这是在终端中 运行 成功的管道:

gst-launch-1.0 rtspsrc location="rtsp://admin:123456@192.168.0.150:554/H264?ch=1&subtype=0&proto=Onvif" latency=300 ! rtph264depay ! h264parse ! nvv4l2decoder drop-frame-interval=1 ! nvvideoconvert ! video/x-raw,width=1920,height=1080,formate=I420 ! queue !  nveglglessink window-x=0 window-y=0 window-width=1080 window-height=720

但是当 运行使用 python 代码连接相同的管道时,没有输出 window 显示 rtsp 流并且在终端上也没有错误。终端卡住了,直到我按下 ctrl+c。

这是我用于 运行 gstreamer 命令的代码:

import gi

gi.require_version("Gst", "1.0")

from gi.repository import Gst, GObject


def main(device):
    GObject.threads_init()
    Gst.init(None)

    pipeline = Gst.Pipeline()

    source = Gst.ElementFactory.make("rtspsrc", "video-source")
    source.set_property("location", device)
    source.set_property("latency", 300)
    pipeline.add(source)

    depay = Gst.ElementFactory.make("rtph264depay", "depay")
    pipeline.add(depay)
    source.link(depay)

    parse = Gst.ElementFactory.make("h264parse", "parse")
    pipeline.add(parse)
    depay.link(parse)

    decoder = Gst.ElementFactory.make("nvv4l2decoder", "decoder")
    decoder.set_property("drop-frame-interval", 2)
    pipeline.add(decoder)
    parse.link(decoder)

    convert = Gst.ElementFactory.make("nvvideoconvert", "convert")
    pipeline.add(convert)
    decoder.link(convert)

    caps = Gst.Caps.from_string("video/x-raw,width=1920,height=1080,formate=I420")
    filter = Gst.ElementFactory.make("capsfilter", "filter")
    filter.set_property("caps", caps)
    pipeline.add(filter)
    convert.link(filter)

    queue = Gst.ElementFactory.make("queue", "queue")
    pipeline.add(queue)
    filter.link(queue)

    sink = Gst.ElementFactory.make("nveglglessink", "video-sink")
    sink.set_property("window-x", 0)
    sink.set_property("window-y", 0)
    sink.set_property("window-width", 1280)
    sink.set_property("window-height", 720)

    pipeline.add(sink)

    queue.link(sink)

    loop = GObject.MainLoop()

    pipeline.set_state(Gst.State.PLAYING)

    try:
        loop.run()
    except:
        pass

    pipeline.set_state(Gst.State.NULL)

if __name__ == "__main__":
    main("rtsp://admin:123456@192.168.0.150:554/H264?ch=1&subtype=0&proto=Onvif")

有谁知道错在哪里?谢谢!

它不起作用的原因是因为 rtspsrc 的源板是所谓的 "Sometimes pad"。 link 这里解释得很好,但基本上你无法提前知道 rtspsrc 上有多少可用的 pad,因为这取决于 RTSP 服务器提供的 SDP。

因此,您应该收听 rtspsrc"pad-added" 信号,在那里您可以 link 管道的其余部分到刚刚出现在回调。

如此总结:

def main(device):
    GObject.threads_init()
    Gst.init(None)

    pipeline = Gst.Pipeline()
    source = Gst.ElementFactory.make("rtspsrc", "video-source")
    source.set_property("location", device)
    source.set_property("latency", 300)
    source.connect("pad-added", on_rtspsrc_pad_added)
    pipeline.add(source)

    # We will add/link the rest of the pipeline later
    loop = GObject.MainLoop()

    pipeline.set_state(Gst.State.PLAYING)

    try:
        loop.run()
    except:
        pass

    pipeline.set_state(Gst.State.NULL)

def on_rtspsrc_pad_added(rtspsrc, pad, *user_data):
    # Create the rest of your pipeline here and link it 
    depay = Gst.ElementFactory.make("rtph264depay", "depay")
    pipeline.add(depay)
    rtspsrc.link(depay)

    # and so on ....