Gstreamer из python's gst.Проблема 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:workspacegggsrctest2.py", line 37, in <module>
    main()
  File "H:workspacegggsrctest2.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 не имеет каких-либо исходных колодок (то есть: нет выходы).

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

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

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

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

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

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