Python中GStreamer的splitmuxsrc元素链接失败问题排查
问题描述
我在Python3.6中尝试实现以下GStreamer命令行管道:
splitmuxsrc location=clip000*.mp4 ! video/x-h264,alignment=au ! h264parse ! avdec_h264 ! videoconvert ! xvimagesink
该命令行可正常运行,但转换为Python代码后出现如下错误:
Error: gst-stream-error-quark: Internal data stream error. (1), gstsplitmuxsrc.c(598): gst_splitmux_pad_loop (): /GstPipeline:pipeline0/GstSplitMuxSrc:muxsrc:
streaming stopped, reason not-linked (-1)
直接链接splitmuxsrc与h264parse无效,且splitmuxsrc没有静态src pad,尝试获取其video类型的request pad也无法成功。
附原Python代码:
import gi gi.require_version('Gst', '1.0') from gi.repository import Gst, GObject # Initialize GStreamer Gst.init(None) # Create GStreamer pipeline pipeline = Gst.Pipeline() # Create elements muxsrc = Gst.ElementFactory.make("splitmuxsrc", "muxsrc") h264parse = Gst.ElementFactory.make("h264parse", "h264parse") avdec_h264 = Gst.ElementFactory.make("avdec_h264", "avdec_h264") videoconvert = Gst.ElementFactory.make("videoconvert", "videoconvert") xvimagesink = Gst.ElementFactory.make("xvimagesink", "xvimagesink") # Add elements to the pipeline pipeline.add(muxsrc) pipeline.add(h264parse) pipeline.add(avdec_h264) pipeline.add(videoconvert) pipeline.add(xvimagesink) # Link elements muxsrc.link(h264parse) h264parse.link(avdec_h264) avdec_h264.link(videoconvert) videoconvert.link(xvimagesink) # Set properties if needed muxsrc.set_property("location", "clip000*.mp4") # Set up the main loop loop = GObject.MainLoop() # Bus callback function def bus_callback(bus, message, loop): t = message.type if t == Gst.MessageType.EOS: print("End of Stream") loop.quit() elif t == Gst.MessageType.ERROR: err, debug = message.parse_error() print("Error: {}, {}".format(err, debug)) loop.quit() return True # Create and set up the bus bus = pipeline.get_bus() bus.add_signal_watch() bus.connect("message", bus_callback, loop) # Start the pipeline pipeline.set_state(Gst.State.PLAYING) # Run the main loop try: loop.run() except KeyboardInterrupt: pass # Stop the pipeline pipeline.set_state(Gst.State.NULL)
解决方案
问题核心是splitmuxsrc的动态pad处理逻辑和属性设置顺序错误,修改后的代码如下:
import gi gi.require_version('Gst', '1.0') from gi.repository import Gst, GObject # Initialize GStreamer Gst.init(None) # Create GStreamer pipeline pipeline = Gst.Pipeline() # Create elements muxsrc = Gst.ElementFactory.make("splitmuxsrc", "muxsrc") h264parse = Gst.ElementFactory.make("h264parse", "h264parse") avdec_h264 = Gst.ElementFactory.make("avdec_h264", "avdec_h264") videoconvert = Gst.ElementFactory.make("videoconvert", "videoconvert") xvimagesink = Gst.ElementFactory.make("xvimagesink", "xvimagesink") # Add elements to the pipeline pipeline.add(muxsrc) pipeline.add(h264parse) pipeline.add(avdec_h264) pipeline.add(videoconvert) pipeline.add(xvimagesink) # 先链接splitmuxsrc之外的后续元素链 h264parse.link(avdec_h264) avdec_h264.link(videoconvert) videoconvert.link(xvimagesink) # 先设置splitmuxsrc的文件路径属性,确保元素提前识别文件列表 muxsrc.set_property("location", "clip000*.mp4") # 处理splitmuxsrc的动态pad创建事件 def pad_added_handler(src, new_pad, sink_element): # 获取目标元素的静态sink pad sink_pad = sink_element.get_static_pad("sink") if sink_pad.is_linked(): print("Pad已链接,跳过") return # 校验新pad的媒体格式是否匹配H264 caps = new_pad.get_current_caps() if caps.to_string().startswith("video/x-h264"): # 执行pad链接 if new_pad.link(sink_pad) != Gst.PadLinkReturn.OK: print("Pad链接失败!") # 给splitmuxsrc绑定pad-added信号回调 muxsrc.connect("pad-added", pad_added_handler, h264parse) # Set up the main loop loop = GObject.MainLoop() # Bus callback function def bus_callback(bus, message, loop): t = message.type if t == Gst.MessageType.EOS: print("流已结束") loop.quit() elif t == Gst.MessageType.ERROR: err, debug = message.parse_error() print("错误: {}, {}".format(err, debug)) loop.quit() return True # Create and set up the bus bus = pipeline.get_bus() bus.add_signal_watch() bus.connect("message", bus_callback, loop) # Start the pipeline pipeline.set_state(Gst.State.PLAYING) # Run the main loop try: loop.run() except KeyboardInterrupt: pass # Stop the pipeline pipeline.set_state(Gst.State.NULL)
修改关键要点
- 调整属性设置顺序:先给
splitmuxsrc设置location属性再启动管道,确保元素能提前解析文件列表,为后续动态pad创建做准备。 - 处理动态Pad:
splitmuxsrc不会预先生成静态src pad,而是在启动后根据文件内容动态创建。通过监听pad-added信号,在新pad出现时校验格式并链接到h264parse。 - 预链接后续元素链:提前把
h264parse到xvimagesink的元素链接完成,避免动态pad链接时出现依赖缺失问题。
内容的提问来源于stack exchange,提问作者just-my-name
相关产品推荐
相关产品推荐

