Gstreamer проблемы gst.LinkError в python
Я связываю приложение gstreamer с Python. И я получаю LinkError со следующим кодом:
import pygst
pygst.require('0.10')
import gst
import pygtk
pygtk.require('2.0')
import gtk
# this is very important, without this, callbacks from gstreamer thread
# will messed our program up
gtk.gdk.threads_init()
def main():
pipeline = gst.Pipeline('pipleline')
filesrc = gst.element_factory_make("filesrc", "filesrc")
filesrc.set_property('location', 'C:/a.mp3')
decode = gst.element_factory_make("decodebin", "decode")
convert = gst.element_factory_make('audioconvert', 'convert')
sink = gst.element_factory_make("autoaudiosink", "sink")
pipeline.add(filesrc, decode, convert, sink)
gst.element_link_many(filesrc, decode, convert, sink)
pipeline.set_state(gst.STATE_PLAYING)
gtk.main()
main()
И ошибка:
ImportError: could not import gio
Traceback (most recent call last):
File "H:\workspace\ggg\src\test2.py", line 37, in <module>
main()
File "H:\workspace\ggg\src\test2.py", line 31, in main
gst.element_link_many(filesrc, decode, convert, sink)
gst.LinkError: failed to link decode with convert
Это очень странно, с тем же конвейером, но построен с помощью parse_launch, он работает. Вот код:
import pygst
pygst.require('0.10')
import gst
import pygtk
pygtk.require('2.0')
import gtk
# this is very important, without this, callbacks from gstreamer thread
# will messed our program up
gtk.gdk.threads_init()
def main():
player = gst.parse_launch('filesrc location=C:/a.mp3 ! decodebin ! audioconvert ! autoaudiosink')
player.set_state(gst.STATE_PLAYING)
gtk.main()
main()
Возникает вопрос: почему ручная работа не удалась, а разбиралась? Что в этом плохого? Как я могу это исправить?
Благодарю.
1 ответ
Ваша проблема здесь:
gst.element_link_many(filesrc, decode, convert, sink)
причина в том, что не все элементы имеют простые статические входы и выходы. на данный момент в вашей программе ваш декодер не имеет никаких пэдов источника (то есть: нет выходов).
пэд похож на сосок - это вход / выход для элемента. колодки могут появляться, исчезать или просто сидеть там. Существуют три класса пэдов: статические пэды (самые простые и ожидаемые), пэды запросов (которые появляются только тогда, когда вы их просите) и иногда пэды (которые появляются только тогда, когда элемент хочет, чтобы они появлялись). выходы decodebin
иногда бывают колодки.
если вы проверяете вывод gst-inspect decodebin
Вы можете убедиться в этом сами:
Pad Templates:
SINK template: 'sink'
Availability: Always
Capabilities:
ANY
SRC template: 'src%d'
Availability: Sometimes
Capabilities:
ANY
в строке 26 вашей программы вы не можете связать декодирование с чем-либо, потому что у него нет никаких исходных площадок для ссылки. пэды источника в декодере появляются только при декодировании входного потока: это не происходит мгновенно. может появиться любое количество пэдов источника (например, один для аудиопотока, два для видеопотока со звуком, ни один для не декодируемого потока).
вам нужно дождаться создания пэдов, а затем связать их. decodebin посылает сигнал "new-decoded-pad", чтобы сообщить вам, когда это происходит (это также описано в gst-inspect decodebin
). Вы должны подключить функцию обратного вызова к этому сигналу и связать свой декодер и аудиоконверт в обратном вызове. вот ваш исправленный код:
#!/usr/bin/python
import pygst
pygst.require('0.10')
import gst
import pygtk
pygtk.require('2.0')
import gtk
# this is very important, without this, callbacks from gstreamer thread
# will messed our program up
gtk.gdk.threads_init()
def on_new_decoded_pad(dbin, pad, islast):
decode = pad.get_parent()
pipeline = decode.get_parent()
convert = pipeline.get_by_name('convert')
decode.link(convert)
pipeline.set_state(gst.STATE_PLAYING)
print "linked!"
def main():
pipeline = gst.Pipeline('pipleline')
filesrc = gst.element_factory_make("filesrc", "filesrc")
filesrc.set_property('location', 'C:/a.mp3')
decode = gst.element_factory_make("decodebin", "decode")
convert = gst.element_factory_make('audioconvert', 'convert')
sink = gst.element_factory_make("autoaudiosink", "sink")
pipeline.add(filesrc, decode, convert, sink)
gst.element_link_many(filesrc, decode)
gst.element_link_many(convert, sink)
decode.connect("new-decoded-pad", on_new_decoded_pad)
pipeline.set_state(gst.STATE_PAUSED)
gtk.main()
main()
gst.parse_launch
работает, потому что он заботится обо всех этих сложных деталях для вас. есть также элемент высокого уровня playbin
который автоматически создает и связывает декодер внутри.