Gstreamer GST Python. Проблема LinkError

Я соединяю 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()

Здесь прибывает вопрос, почему ручной перестал работать, но проанализированный один успех? Что случилось с этим? Как я могу зафиксировать его?

Спасибо.

10
задан Fang-Pen Lin 7 June 2010 в 23:03
поделиться

1 ответ

ваша проблема здесь:

gst.element_link_many(filesrc, decode, convert, sink)

причина в том, что не все элементы имеют простые, статические входы и выходы. на данном этапе вашей программы, ваш decodebin не имеет никаких исходных пэдов (то есть: никаких выходов).

пэд похож на сосок - это вход/выход элемента. пэды могут появляться, исчезать или просто сидеть на месте. есть три класса пэдов: static pads (самый простой, и именно его вы ожидаете), request pads (которые появляются только тогда, когда вы их просите) и sometimes pads (которые появляются только тогда, когда элемент хочет, чтобы они появились). выходами decodebin являются sometimes pads.

если вы посмотрите вывод gst-inspect decodebin, вы сможете убедиться в этом:

Pad Templates:
  SINK template: 'sink'
    Availability: Always
    Capabilities:
      ANY

  SRC template: 'src%d'
    Availability: Sometimes
    Capabilities:
      ANY

в строке 26 вашей программы вы не можете связать decode ни с чем, потому что у него нет исходных пэдов для связи. исходные пэды в decodebin появляются только по мере декодирования входного потока: это не происходит мгновенно. может появиться любое количество исходных пэдов (например, один для аудио потока, два для видео потока с аудио, ни одного для не декодируемого потока).

вам нужно подождать, пока пэды будут созданы, а затем связать их. 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, который автоматически создает и связывает внутренний декодирующий файл.

20
ответ дан 3 December 2019 в 19:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: