我一直在项目中使用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,我真的很感激任何有关这方面的见解。谢谢! =)
答案 0 :(得分:1)
我最终使用add_signal_watch_full()
,遗憾的是更加冗长。它工作正常,我可以在我的处理程序上接收消息。
答案 1 :(得分:1)
我很确定接受的答案是不正确的。 add_signal_watch_full
和add_signal_watch
之间的唯一区别是前者允许您设置事件源的优先级,而后者只是使用G_PRIORITY_DEFAULT
调用前者。您可以在C source code中对行号940进行验证。优先级只会影响触发事件的顺序,不应影响是否触发,当然也不会影响信号消息的内容,这是此处的问题。我甚至用各种优先级值测试它,如果有一种方法,我会吃我的帽子。 : - )
真正的答案是它不起作用。 PyGObject和GStreamer 0.10不能很好地协同工作。参见:
后者说:“请注意,虽然你可以 sort-of 使用GStreamer0.10与PyGI,但关键功能从根本上被打破,并且永远不会在GStreamer0.10中修复(因为它需要API断裂)。“
您的选择是:
答案 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的共享库解决了我的问题。