GStreamer总线发送无消息

时间:2011-08-10 01:50:57

标签: python gstreamer

我一直在项目中使用pygst,它一直运行良好。我正在尝试将其迁移到新的内省系统(GI),但我一直在采取不同的行为。

在旧的pygst我有这样的事情:

... # other imports
import pygst
pygst.require('0.10')
import gst
... # other imports

gobjects.threads_init()

...

def my_handler(bus, message):
    # handle the message

...

player = gst.element_factory_make('playbin2', 'my_player')
bus = player.get_bus()
bus.connect('message', my_handler)
bus.add_signal_watch()
...
player.set_state(gst.STATE_PLAYING)
# start the main Glib loop

消息参数有一个属性 .type ,可用于选择性处理(我只对流结束(EOS)和错误感兴趣)。使用我的新系统:

... # other imports
from gi.repository import Gst
import glib
import gobject
.... # other imports

gobject.threads_init()

loop = glib.MainLoop(None, False)

def bus_handler(bus, message):
    print message
    # handle the message
...

Gst.init_check(None)
player = Gst.ElementFactory.make('playbin2', 'my_player')
player.set_property('uri', 'file:///home/kenji/button.ogg')
bus = player.get_bus()
bus.connect('message', bus_handler)
bus.add_signal_watch()
player.set_state(Gst.State.PLAYING)
# start the main loop

但是,处理程序始终将消息作为接收。我已经尝试过滤掉这些,但我仍然没有得到任何结果(即所有消息都是)。

我已经阅读了很多GStreamer文档(特别是关于GstBus,add_signal_watch()和playbin2),但我没有找到任何与此行为相关的内容。我已经检查了Gst gir 文件,我发现add_watch()无法被内省,所以这是一个死胡同。上面这个例子中的glib主循环只是为了在没有完整的GTK示例的情况下简化,但真实的东西使用Gtk.main()(给出完全相同的行为)。

我在Arch Linux 64上使用GStreamer 0.10.35.0(由Gst.version()通知),但我在Ubuntu 11.04 32位上测试了GStreamer 0.10.32.0上的相同行为。

有没有替代bus.connect()的方法?我是以错误的方式使用它吗?我花了不少时间来寻找这个bug,我真的很感激任何有关这方面的见解。谢谢! =)

4 个答案:

答案 0 :(得分:1)

我最终使用add_signal_watch_full(),遗憾的是更加冗长。它工作正常,我可以在我的处理程序上接收消息。

答案 1 :(得分:1)

我很确定接受的答案是不正确的。 add_signal_watch_fulladd_signal_watch之间的唯一区别是前者允许您设置事件源的优先级,而后者只是使用G_PRIORITY_DEFAULT调用前者。您可以在C source code中对行号940进行验证。优先级只会影响触发事件的顺序,不应影响是否触发,当然也不会影响信号消息的内容,这是此处的问题。我甚至用各种优先级值测试它,如果有一种方法,我会吃我的帽子。 : - )

真正的答案是它不起作用。 PyGObject和GStreamer 0.10不能很好地协同工作。参见:

后者说:“请注意,虽然你可以 sort-of 使用GStreamer0.10与PyGI,但关键功能从根本上被打破,并且永远不会在GStreamer0.10中修复(因为它需要API断裂)。“

您的选择是:

  • 需要GStreamer 1.0。
  • 使用旧的PyGST绑定。
  • 将PyGObject与GStreamer 0.10一起使用,但无法检查EOS等消息。只有非常基本的东西工作。

答案 2 :(得分:0)

如果您不打算在程序中使用GTK,则必须运行gobject.Mainloop()才能从总线获取消息。像任何其他主循环一样,这将冻结整个程序(如果它没有线程),所以我通常会添加类似的东西:

g_loop = threading.Thread(target=gobject.MainLoop().run)
g_loop.daemon = True
g_loop.start()

在程序结束时不需要GUI,但确实需要Gstreamer。

答案 3 :(得分:0)

我遇到了同样的问题但在C中。

经过长时间的调试后,我发现发生这种情况是因为我的可执行文件链接到了0.10和1.0,间接由我使用的其他共享库。

删除链接到0.10的共享库解决了我的问题。