如何从 python Gst.Bus 获取错误信息
How to get error messages from python Gst.Bus
我有一个程序预计会因错误而失败。我正在编写处理这些错误的逻辑。
程序执行时失败,pipeline.set_state(Gst.State.READY)。 return 代码证实了这一点。我正在寻找的是一种识别错误源的方法。
我正在尝试通过 bus.connect('message::error', on_error) 注册回调函数。永远不会调用回调。
我的印象是调试 错误 、GST_ERROR_OBJECT() 与 Gst.MessageType.ERROR 类型的消息不同。还有各种各样的消息传递方案和信号使我的调查变得困难。
./foo.py --gst-debug=3 产生大量输出。包括来自不干净的库代码的粪便。
0:00:00.020176932 20284 0x2d49390 ERROR jackclient gstjackaudioclient.c:35:jack_log_error: Cannot connect to server socket err = No such file or directory
0:00:00.020225574 20284 0x2d49390 ERROR jackclient gstjackaudioclient.c:35:jack_log_error: Cannot connect to server request channel
0:00:00.022293832 20284 0x2d49390 ERROR jackclient gstjackaudioclient.c:35:jack_log_error: jack server is not running or cannot be started
0:00:00.022422501 20284 0x2d49390 ERROR jackclient gstjackaudioclient.c:35:jack_log_error: JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for 4294967295, skipping unlock
0:00:00.022435733 20284 0x2d49390 ERROR jackclient gstjackaudioclient.c:35:jack_log_error: JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for 4294967295, skipping unlock
0:00:00.022444680 20284 0x2d49390 WARN jackclient gstjackaudioclient.c:379:gst_jack_audio_get_connection: could not create connection
0:00:00.022562482 20284 0x2d49390 WARN jacksink gstjackaudiosink.c:357:gst_jack_ring_buffer_open_device:<sink-actual-sink-jackaudio> error: Jack server not found
0:00:00.022573131 20284 0x2d49390 WARN jacksink gstjackaudiosink.c:357:gst_jack_ring_buffer_open_device:<sink-actual-sink-jackaudio> error: Cannot connect to the Jack server (status 17)
0:00:00.023123730 20284 0x2d49390 WARN default oss4-property-probe.c:303:gst_oss4_property_probe_get_values:<sink-actual-sink-oss4> Can't open file descriptor to probe available devices: No such file or directory
0:00:00.023150887 20284 0x2d49390 WARN oss4sink oss4-sink.c:514:gst_oss4_sink_open:<sink-actual-sink-oss4> error: Could not open audio device for playback.
0:00:00.023160358 20284 0x2d49390 WARN oss4sink oss4-sink.c:514:gst_oss4_sink_open:<sink-actual-sink-oss4> error: system error: No such file or directory
AL lib: (WW) alc_initconfig: Failed to initialize backend "pulse"
ALSA lib confmisc.c:768:(parse_card) cannot find card '0'
ALSA lib conf.c:4292:(_snd_config_evaluate) function snd_func_card_driver returned error: No such file or directory
ALSA lib confmisc.c:392:(snd_func_concat) error evaluating strings
ALSA lib conf.c:4292:(_snd_config_evaluate) function snd_func_concat returned error: No such file or directory
ALSA lib confmisc.c:1251:(snd_func_refer) error evaluating name
ALSA lib conf.c:4292:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory
ALSA lib conf.c:4771:(snd_config_expand) Evaluate error: No such file or directory
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Unknown PCM default
AL lib: (EE) ALCplaybackAlsa_open: Could not open playback device 'default': No such file or directory
0:00:00.048076943 20284 0x2d49390 WARN openal gstopenalsink.c:635:gst_openal_sink_open:<sink-actual-sink-openal> error: Could not open device.
0:00:00.048195277 20284 0x2d49390 WARN openal gstopenalsink.c:635:gst_openal_sink_open:<sink-actual-sink-openal> error: ALC error: Out of Memory
0:00:00.048822468 20284 0x2d49390 WARN oss gstosssink.c:399:gst_oss_sink_open:<sink-actual-sink-oss> error: Could not open audio device for playback.
0:00:00.048945169 20284 0x2d49390 WARN oss gstosssink.c:399:gst_oss_sink_open:<sink-actual-sink-oss> error: system error: No such file or directory
0:00:00.055983656 20284 0x2d49390 ERROR decklinkaudiosrc gstdecklinkaudiosrc.cpp:670:gst_decklink_audio_src_open:<audio> Failed to acquire input
Traceback (most recent call last):
File "./tim.py", line 40, in <module>
raise Exception('state change failed')
Exception: state change failed
这是代码。
#!/usr/bin/env python3
import sys
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstBase', '1.0')
gi.require_version('Gtk', '3.0')
from gi.repository import GObject, Gst, GstBase, Gtk, GObject
def on_error(bus, msg):
print('Error {}: {}, {}'.format(msg.src.name, *msg.parse_error()))
if __name__ == '__main__':
# exits on error
sys.argv = Gst.init(sys.argv)
pipeline = Gst.Pipeline.new("mypipeline")
assert(pipeline)
bus = pipeline.get_bus()
assert(bus)
bus.add_signal_watch()
bus.connect('message::error', on_error)
# bus.add_watch(GLib.PRIORITY_DEFAULT, on_error)
#audio = Gst.ElementFactory.make("audiotestsrc", "audio")
audio = Gst.ElementFactory.make('decklinkaudiosrc', "audio")
assert(audio)
ret = pipeline.add(audio)
assert(ret)
sink = Gst.ElementFactory.make("autoaudiosink", "sink")
assert(sink)
ret = pipeline.add(sink)
assert(ret)
ret = audio.link(sink)
assert(ret)
ret = pipeline.set_state(Gst.State.READY)
if ret == Gst.StateChangeReturn.FAILURE:
msg = bus.pop_filtered(Gst.MessageType.ERROR)
while msg:
on_error(bus, msg)
msg = bus.pop_filtered(Gst.MessageType.ERROR)
raise Exception('state change failed')
更新中,2018 年 3 月 14 日
我能够使用以下代码获得与 gst-launch-1.0 --gst-debug=2 -m decklinkaudiosrc ! autoaudiosink
相当的输出。了解状态更改消息也很有趣。
对我来说,这是调试基础设施独立于总线上观察到的消息系统的有力证据。我将搜索调试代码的挂钩并尝试观察这些消息。
msg = bus.pop()
while msg:
if msg.type == Gst.MessageType.ERROR:
on_error(bus, msg)
else:
print('{} {}: {}'.format(
Gst.MessageType.get_name(msg.type), msg.src.name,
msg.get_structure().to_string()))
msg = bus.pop()
我怀疑你需要 poll
公共汽车或 GMainLoop
运行。
有关投票,请参阅 https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstBus.html#gst-bus-poll
对于主循环,在应用程序结束时执行此操作:
loop = GLib.MainLoop()
loop.run()
您需要在顶部导入 GLib
。
或者,如果您想避免线程化,请从 GstBus
文档中获取此注释:
It is also possible to get messages from the bus without any thread
marshalling with the gst_bus_set_sync_handler() method. This makes it
possible to react to a message in the same thread that posted the
message on the bus. This should only be used if the application is
able to deal with messages from different threads.
我在这方面取得了很大进展。我可以使用 Gst.debug_add_log_function(on_debug, None)
.
注册回调
缺点是,Gst.debug_remove_log_function(Gst.debug_log_default)
在 Python 中不起作用。
我新添加的代码,
def on_debug(category, level, dfile, dfctn, dline, source, message, user_data):
if source:
print('Debug {} {}: {}'.format(
Gst.DebugLevel.get_name(level), source.name, message.get()))
else:
print('Debug {}: {}'.format(
Gst.DebugLevel.get_name(level), message.get()))
if __name__ == '__main__':
# exits on error
sys.argv = Gst.init(sys.argv)
if not Gst.debug_is_active():
Gst.debug_set_active(True)
level = Gst.debug_get_default_threshold()
if level < Gst.DebugLevel.ERROR:
Gst.debug_set_default_threshold(Gst.DebugLevel.WARNING)
Gst.debug_add_log_function(on_debug, None)
Gst.debug_remove_log_function(Gst.debug_log_default)
我按照这样的方式做了一些事情:
bus = pipeline.get_bus()
msg = bus.timed_pop_filtered(
Gst.CLOCK_TIME_NONE,
Gst.MessageType.ERROR | Gst.MessageType.EOS
)
if msg:
t = msg.type
if t == Gst.MessageType.ERROR:
err, dbg = msg.parse_error()
print("ERROR:", msg.src.get_name(), ":", err.message)
if dbg:
print("debugging info:", dbg)
elif t == Gst.MessageType.EOS:
print("End-Of-Stream reached")
else:
# this should not happen. we only asked for ERROR and EOS
print("ERROR: Unexpected message received.")
看起来订单很重要:
Gst.debug_remove_log_function(None)
Gst.debug_add_log_function(on_debug,None)
Gst.debug_set_default_threshold(Gst.DebugLevel.WARNING)
Gst.debug_set_active(True)
这让我可以控制 GStreamer 日志。
我有一个程序预计会因错误而失败。我正在编写处理这些错误的逻辑。
程序执行时失败,pipeline.set_state(Gst.State.READY)。 return 代码证实了这一点。我正在寻找的是一种识别错误源的方法。
我正在尝试通过 bus.connect('message::error', on_error) 注册回调函数。永远不会调用回调。
我的印象是调试 错误 、GST_ERROR_OBJECT() 与 Gst.MessageType.ERROR 类型的消息不同。还有各种各样的消息传递方案和信号使我的调查变得困难。
./foo.py --gst-debug=3 产生大量输出。包括来自不干净的库代码的粪便。
0:00:00.020176932 20284 0x2d49390 ERROR jackclient gstjackaudioclient.c:35:jack_log_error: Cannot connect to server socket err = No such file or directory
0:00:00.020225574 20284 0x2d49390 ERROR jackclient gstjackaudioclient.c:35:jack_log_error: Cannot connect to server request channel
0:00:00.022293832 20284 0x2d49390 ERROR jackclient gstjackaudioclient.c:35:jack_log_error: jack server is not running or cannot be started
0:00:00.022422501 20284 0x2d49390 ERROR jackclient gstjackaudioclient.c:35:jack_log_error: JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for 4294967295, skipping unlock
0:00:00.022435733 20284 0x2d49390 ERROR jackclient gstjackaudioclient.c:35:jack_log_error: JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for 4294967295, skipping unlock
0:00:00.022444680 20284 0x2d49390 WARN jackclient gstjackaudioclient.c:379:gst_jack_audio_get_connection: could not create connection
0:00:00.022562482 20284 0x2d49390 WARN jacksink gstjackaudiosink.c:357:gst_jack_ring_buffer_open_device:<sink-actual-sink-jackaudio> error: Jack server not found
0:00:00.022573131 20284 0x2d49390 WARN jacksink gstjackaudiosink.c:357:gst_jack_ring_buffer_open_device:<sink-actual-sink-jackaudio> error: Cannot connect to the Jack server (status 17)
0:00:00.023123730 20284 0x2d49390 WARN default oss4-property-probe.c:303:gst_oss4_property_probe_get_values:<sink-actual-sink-oss4> Can't open file descriptor to probe available devices: No such file or directory
0:00:00.023150887 20284 0x2d49390 WARN oss4sink oss4-sink.c:514:gst_oss4_sink_open:<sink-actual-sink-oss4> error: Could not open audio device for playback.
0:00:00.023160358 20284 0x2d49390 WARN oss4sink oss4-sink.c:514:gst_oss4_sink_open:<sink-actual-sink-oss4> error: system error: No such file or directory
AL lib: (WW) alc_initconfig: Failed to initialize backend "pulse"
ALSA lib confmisc.c:768:(parse_card) cannot find card '0'
ALSA lib conf.c:4292:(_snd_config_evaluate) function snd_func_card_driver returned error: No such file or directory
ALSA lib confmisc.c:392:(snd_func_concat) error evaluating strings
ALSA lib conf.c:4292:(_snd_config_evaluate) function snd_func_concat returned error: No such file or directory
ALSA lib confmisc.c:1251:(snd_func_refer) error evaluating name
ALSA lib conf.c:4292:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory
ALSA lib conf.c:4771:(snd_config_expand) Evaluate error: No such file or directory
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Unknown PCM default
AL lib: (EE) ALCplaybackAlsa_open: Could not open playback device 'default': No such file or directory
0:00:00.048076943 20284 0x2d49390 WARN openal gstopenalsink.c:635:gst_openal_sink_open:<sink-actual-sink-openal> error: Could not open device.
0:00:00.048195277 20284 0x2d49390 WARN openal gstopenalsink.c:635:gst_openal_sink_open:<sink-actual-sink-openal> error: ALC error: Out of Memory
0:00:00.048822468 20284 0x2d49390 WARN oss gstosssink.c:399:gst_oss_sink_open:<sink-actual-sink-oss> error: Could not open audio device for playback.
0:00:00.048945169 20284 0x2d49390 WARN oss gstosssink.c:399:gst_oss_sink_open:<sink-actual-sink-oss> error: system error: No such file or directory
0:00:00.055983656 20284 0x2d49390 ERROR decklinkaudiosrc gstdecklinkaudiosrc.cpp:670:gst_decklink_audio_src_open:<audio> Failed to acquire input
Traceback (most recent call last):
File "./tim.py", line 40, in <module>
raise Exception('state change failed')
Exception: state change failed
这是代码。
#!/usr/bin/env python3
import sys
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstBase', '1.0')
gi.require_version('Gtk', '3.0')
from gi.repository import GObject, Gst, GstBase, Gtk, GObject
def on_error(bus, msg):
print('Error {}: {}, {}'.format(msg.src.name, *msg.parse_error()))
if __name__ == '__main__':
# exits on error
sys.argv = Gst.init(sys.argv)
pipeline = Gst.Pipeline.new("mypipeline")
assert(pipeline)
bus = pipeline.get_bus()
assert(bus)
bus.add_signal_watch()
bus.connect('message::error', on_error)
# bus.add_watch(GLib.PRIORITY_DEFAULT, on_error)
#audio = Gst.ElementFactory.make("audiotestsrc", "audio")
audio = Gst.ElementFactory.make('decklinkaudiosrc', "audio")
assert(audio)
ret = pipeline.add(audio)
assert(ret)
sink = Gst.ElementFactory.make("autoaudiosink", "sink")
assert(sink)
ret = pipeline.add(sink)
assert(ret)
ret = audio.link(sink)
assert(ret)
ret = pipeline.set_state(Gst.State.READY)
if ret == Gst.StateChangeReturn.FAILURE:
msg = bus.pop_filtered(Gst.MessageType.ERROR)
while msg:
on_error(bus, msg)
msg = bus.pop_filtered(Gst.MessageType.ERROR)
raise Exception('state change failed')
更新中,2018 年 3 月 14 日
我能够使用以下代码获得与 gst-launch-1.0 --gst-debug=2 -m decklinkaudiosrc ! autoaudiosink
相当的输出。了解状态更改消息也很有趣。
对我来说,这是调试基础设施独立于总线上观察到的消息系统的有力证据。我将搜索调试代码的挂钩并尝试观察这些消息。
msg = bus.pop()
while msg:
if msg.type == Gst.MessageType.ERROR:
on_error(bus, msg)
else:
print('{} {}: {}'.format(
Gst.MessageType.get_name(msg.type), msg.src.name,
msg.get_structure().to_string()))
msg = bus.pop()
我怀疑你需要 poll
公共汽车或 GMainLoop
运行。
有关投票,请参阅 https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstBus.html#gst-bus-poll
对于主循环,在应用程序结束时执行此操作:
loop = GLib.MainLoop()
loop.run()
您需要在顶部导入 GLib
。
或者,如果您想避免线程化,请从 GstBus
文档中获取此注释:
It is also possible to get messages from the bus without any thread marshalling with the gst_bus_set_sync_handler() method. This makes it possible to react to a message in the same thread that posted the message on the bus. This should only be used if the application is able to deal with messages from different threads.
我在这方面取得了很大进展。我可以使用 Gst.debug_add_log_function(on_debug, None)
.
缺点是,Gst.debug_remove_log_function(Gst.debug_log_default)
在 Python 中不起作用。
我新添加的代码,
def on_debug(category, level, dfile, dfctn, dline, source, message, user_data):
if source:
print('Debug {} {}: {}'.format(
Gst.DebugLevel.get_name(level), source.name, message.get()))
else:
print('Debug {}: {}'.format(
Gst.DebugLevel.get_name(level), message.get()))
if __name__ == '__main__':
# exits on error
sys.argv = Gst.init(sys.argv)
if not Gst.debug_is_active():
Gst.debug_set_active(True)
level = Gst.debug_get_default_threshold()
if level < Gst.DebugLevel.ERROR:
Gst.debug_set_default_threshold(Gst.DebugLevel.WARNING)
Gst.debug_add_log_function(on_debug, None)
Gst.debug_remove_log_function(Gst.debug_log_default)
我按照这样的方式做了一些事情:
bus = pipeline.get_bus()
msg = bus.timed_pop_filtered(
Gst.CLOCK_TIME_NONE,
Gst.MessageType.ERROR | Gst.MessageType.EOS
)
if msg:
t = msg.type
if t == Gst.MessageType.ERROR:
err, dbg = msg.parse_error()
print("ERROR:", msg.src.get_name(), ":", err.message)
if dbg:
print("debugging info:", dbg)
elif t == Gst.MessageType.EOS:
print("End-Of-Stream reached")
else:
# this should not happen. we only asked for ERROR and EOS
print("ERROR: Unexpected message received.")
看起来订单很重要:
Gst.debug_remove_log_function(None)
Gst.debug_add_log_function(on_debug,None)
Gst.debug_set_default_threshold(Gst.DebugLevel.WARNING)
Gst.debug_set_active(True)
这让我可以控制 GStreamer 日志。