开发者

GStreamer bus sends None message

开发者 https://www.devze.com 2023-03-27 13:07 出处:网络
I\'ve been using pygst on a project and it\'s been working fine. I\'m trying to migrate it to the new introspection system (GI), but I\'ve been getting a different behavior.

I've been using pygst on a project and it's been working fine. I'm trying to migrate it to the new introspection system (GI), but I've been getting a different behavior.

In the old pygst I have something like this:

... # 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

The message parameter has an attribute .type which can be used for selective processing (I'm only interested in the end of stream (EOS) and error). Using the new system I have:

... # 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

However, the handler always receives the parameter message as None. I've tried filtering these out, but I still get nothing (i.e. all messages are None).

I've read a lot of the GStreamer documentation (especially on GstBus, add_signal_watch() and playbin2) but I didn't find anything related to this behavior. I've checked the Gst gir file and I've seen that add_watch() cannot be introspected, so that's a dead end. The glib main loop in this above example is just to make things shorter without a full GTK example, but the real thing uses Gtk.main() (giving exactly the same behavior).

I'm using GStreamer 0.10.35.0 (as informed by Gst.version()) on Arch Linux 64, but I've tested the same behavior on GStreamer 0.10.32.0 on Ubuntu 11.04 32-bit.

Is there any alternative to bus.connect()? Am I using it in the wrong way? I've spent quite a few hours hunting down this bug, I would really appreciate any insight on this. Thanks! =)


I'm pretty sure the accepted answer is incorrect. The only difference between add_signal_watch_full and add_signal_watch is that the former lets you set the priority of the event source, while the latter just calls the former with G_PRIORITY_DEFAULT. You can verify this in the C source code, line number 940. The priority level just affects the order of events fired, should not affect whether the are fired and certainly not the contents of the signal message, which is the issue here. I've even tested it with various values for priority, I'll eat my hat if there is a way that this works. :-)

The real answer is that it doesn't work. PyGObject and GStreamer 0.10 don't work well together. See:

  • GStreamer mailing list thread
  • PyGObject bug, as linked above.
  • A useful page from the Novacut Wiki

The latter says: "Note that although you can sort-of use GStreamer0.10 with PyGI, key functionality is fundamentally broken and wont ever be fixed in GStreamer0.10 (because it would require API breakage)."

Your options, then, are:

  • Require GStreamer 1.0.
  • Use the old PyGST bindings.
  • Use PyGObject with GStreamer 0.10, but without the ability to check for messages like EOS. Only very basic stuff work.


I ended up using add_signal_watch_full(), which is unfortunately more verbose. It works fine though, and I can receive messages on my handler.


If you don't plan on using GTK with the program, you will have to run a gobject.Mainloop() in order to get messages from the bus. This, like any other mainloop, will freeze the whole program (if it is not threaded), so I usually put something something like:

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

at the end of a program that doesn't need a GUI, but does need Gstreamer.


I was having this exact same problem but in C.

After long days of debugging, I found that this was happening because my executable was linking to both 0.10 and 1.0, indirectly by other shared libraries I use.

Removing the shared libraries that linked to 0.10 solved my problem.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号