我正在尝试用 python 创建一个简单的 Gstreamer 管道,它将从网络摄像头获取输入并将其显示在视频窗口上。
以下代码按预期工作:
import gi
gi.require_version("Gst", "1.0")
from gi.repository import Gst, GLib
from threading import Thread
Gst.init()
main_loop = GLib.MainLoop()
pipeline = Gst.parse_launch("v4l2src ! decodebin ! videoconvert ! autovideosink")
main_loop_tread = Thread(target=main_loop.run)
main_loop_tread.start()
pipeline.set_state(Gst.State.PLAYING)
但是,当我尝试使用手动创建的管道执行相同的操作时,管道不会显示任何窗口。我的相机灯仍然亮着,但没有弹出视频窗口。另外,如果我用 appsink 重新设置自动视频接收器,我得到的每个缓冲区都是 None。
import gi
gi.require_version("Gst", "1.0")
from gi.repository import Gst, GLib
from threading import Thread
Gst.init()
main_loop = GLib.MainLoop()
pipeline = Gst.Pipeline()
main_loop_tread = Thread(target=main_loop.run)
main_loop_tread.start()
src = Gst.ElementFactory.make("v4l2src")
decode = Gst.ElementFactory.make("decodebin")
convert = Gst.ElementFactory.make("videoconvert")
sink = Gst.ElementFactory.make("autovideosink")
pipeline.add(src)
pipeline.add(decode)
pipeline.add(convert)
pipeline.add(sink)
src.link(decode)
decode.link(convert)
convert.link(sink)
pipeline.set_state(Gst.State.PLAYING)
第二个代码示例有什么问题?
我用
GST_DEBUG=3
标志运行你的代码并看到警告
$ GST_DEBUG=3 python3 python_gstreamer.py
0:00:00.010488893 2604612 0x55d4f997cc00 FIXME default gstutils.c:4025:gst_pad_create_stream_id_internal:<videotestsrc0:src> Creating random stream-id, consider implementing a deterministic way of creating a stream-id
0:00:00.011231276 2604612 0x55d4f997cc00 WARN basesrc gstbasesrc.c:3127:gst_base_src_loop:<videotestsrc0> error: Internal data stream error.
0:00:00.011236130 2604612 0x55d4f997cc00 WARN basesrc gstbasesrc.c:3127:gst_base_src_loop:<videotestsrc0> error: streaming stopped, reason not-linked (-1)
然后我用
GST_DEBUG=4
运行它以查找更多详细信息,我注意到 decodebin
元素没有正确链接到 videoconvert
元素。
$ GST_DEBUG=4 python3 python_gstreamer.py
...
0:00:00.008857654 2606874 0x564edfcf68a0 INFO GST_ELEMENT_PADS gstutils.c:1816:gst_element_link_pads_full: trying to link element decodebin0:(any) to element videoconvert0:(any)
0:00:00.008860541 2606874 0x564edfcf68a0 INFO GST_PADS gstpad.c:4357:gst_pad_peer_query:<videoconvert0:src> pad has no peer
0:00:00.008934791 2606874 0x564edfcf68a0 INFO GST_ELEMENT_PADS gstelement.c:1013:gst_element_get_static_pad: no such pad 'src_%u' in element "decodebin0"
0:00:00.008941910 2606874 0x564edfcf68a0 INFO GST_ELEMENT_PADS gstutils.c:1270:gst_element_get_compatible_pad:<decodebin0> Could not find a compatible pad to link to videoconvert0:sink
...
显然,您必须处理由decodebin发出的“pad-added”信号,然后将新的pad链接到下一个接收器元素。
import gi
gi.require_version("Gst", "1.0")
from gi.repository import Gst, GLib
from threading import Thread
Gst.init()
def pad_added_handler(src, new_pad, convert):
sink_pad = convert.get_static_pad("sink")
if sink_pad.is_linked():
return
new_pad.link(sink_pad)
main_loop = GLib.MainLoop()
pipeline = Gst.Pipeline()
main_loop_tread = Thread(target=main_loop.run)
main_loop_tread.start()
src = Gst.ElementFactory.make("v4l2src")
decode = Gst.ElementFactory.make("decodebin")
convert = Gst.ElementFactory.make("videoconvert")
sink = Gst.ElementFactory.make("autovideosink")
pipeline.add(src)
pipeline.add(decode)
pipeline.add(convert)
pipeline.add(sink)
src.link(decode)
convert.link(sink)
decode.connect("pad-added", pad_added_handler, convert)
pipeline.set_state(Gst.State.PLAYING)