如何从python Gst.Bus获取错误消息

时间:2018-03-12 20:45:55

标签: python-3.x gstreamer python-gstreamer

我有一个预计会因错误而失败的程序。我正在编写处理这些错误的逻辑。

在执行pipeline.set_state(Gst.State.READY)时程序失败。返回代码确认了这一点。我正在寻找的是一种识别错误来源的方法。

我正在尝试通过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()

4 个答案:

答案 0 :(得分:1)

我正在这样做:

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.")

答案 1 :(得分:1)

看起来订单很重要

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日志。

答案 2 :(得分:0)

我怀疑你需要poll总线或GMainLoop正在运行。

对于民意调查,请参阅https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstBus.html#gst-bus-poll

对于主循环,请在应用程序结束时执行此操作:

loop = GLib.MainLoop()
loop.run()

您需要在顶部导入GLib

或者,如果您想避免线程,请从GstBus文档中获取此注释:

  

也可以在没有任何线程的情况下从总线获取消息   使用gst_bus_set_sync_handler()方法进行编组。这样做   可能对发布的同一个帖子中的消息做出反应   公交车上的消息。仅在应用程序使用时才应使用此选项   能够处理来自不同线程的消息。

答案 3 :(得分:0)

我在这方面取得了很多进展。我可以使用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)