Шина GStreamer отправляет сообщение None

Я использую 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

Параметр message имеет атрибут .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

Однако обработчик всегда получает параметр message как None. Я пытался их отфильтровать, но все равно ничего не получаю (т. е. все сообщения имеют значение Нет).

Я прочитал много документации по GStreamer (особенно по GstBus, add_signal_watch() и playbin2), но не нашел ничего, связанного с этим поведением. Я проверил файл Gst gir и увидел, что add_watch() не может быть подвергнут самоанализу, так что это тупик. Основной цикл glib в приведенном выше примере просто делает вещи короче без полного примера GTK, но на самом деле используется Gtk.main() (что дает точно такое же поведение).

Я использую GStreamer 0.10.35.0 (как сообщает Gst.version()) в Arch Linux 64, но я тестировал такое же поведение на GStreamer 0.10.32.0 в 32-разрядной версии Ubuntu 11.04.

Есть ли альтернатива bus.connect()? Я использую его неправильно? Я потратил довольно много часов на поиски этой ошибки, я был бы очень признателен за любую информацию об этом. Спасибо! знак равно


person Kenji    schedule 10.08.2011    source источник
comment
Я обнаружил эту ошибку: bugzilla.gnome.org/show_bug.cgi?id=631901 В принципе, это еще не реализовано.   -  person Gary van der Merwe    schedule 26.07.2012
comment
Я могу подтвердить, что это исправлено в gstreamer 1.0.   -  person Gary van der Merwe    schedule 16.10.2012


Ответы (4)


Я почти уверен, что принятый ответ неверен. Единственная разница между add_signal_watch_full и add_signal_watch заключается в том, что первый позволяет установить приоритет источника события, а второй просто вызывает первый с помощью G_PRIORITY_DEFAULT. Вы можете убедиться в этом в исходном коде. , номер строки 940. Уровень приоритета влияет только на порядок запускаемых событий, не должен влиять на то, запускаются ли события, и, конечно же, не на содержание сигнального сообщения, что является здесь проблемой. Я даже тестировал его с различными значениями приоритета, я съем свою шляпу, если есть способ, которым это работает. :-)

Настоящий ответ заключается в том, что это не работает. PyGObject и GStreamer 0.10 плохо работают вместе. Видеть:

В последнем говорится: «Обратите внимание, что, хотя вы можете в каком-то смысле использовать GStreamer0.10 с PyGI, ключевая функциональность принципиально нарушена и никогда не будет исправлена ​​в GStreamer0.10 (поскольку это потребует поломки API). "

Тогда ваши варианты:

  • Требуется GStreamer 1.0.
  • Используйте старые привязки PyGST.
  • Используйте PyGObject с GStreamer 0.10, но без возможности проверки сообщений, таких как EOS. Работают только самые элементарные вещи.
person skagedal    schedule 31.05.2013

В итоге я использовал add_signal_watch_full(), который, к сожалению, более многословен. Однако он отлично работает, и я могу получать сообщения на свой обработчик.

person Kenji    schedule 14.11.2011
comment
К сожалению, это не сработало для меня. Не могли бы вы предоставить пример кода? - person Gary van der Merwe; 26.07.2012
comment
add_signal_watch_full(1) у меня работает. Я не знаю, зачем нужен 1 аргумент. - person mnrl; 03.06.2014

Если вы не планируете использовать GTK с программой, вам придется запустить gobject.Mainloop() для получения сообщений из шины. Это, как и любой другой основной цикл, заморозит всю программу (если она не многопоточная), поэтому я обычно добавляю что-то вроде:

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

в конце программы, которой не нужен графический интерфейс, но нужен Gstreamer.

person D K    schedule 02.09.2011
comment
Это не отвечает на вопрос. Комментарий из последней строки примера кода указывает на то, что Кенджи знает, что требуется основной цикл. И ваше решение не решает проблему. - person Gary van der Merwe; 26.07.2012

У меня была точно такая же проблема, но на C.

После долгих дней отладки я обнаружил, что это происходит из-за того, что мой исполняемый файл ссылается как на 0.10, так и на 1.0 косвенно через другие общие библиотеки, которые я использую.

Удаление общих библиотек, связанных с 0.10, решило мою проблему.

person Rangel Reale    schedule 04.08.2013