Gstreamer of python's gst.LinkError problem

匿名 (未验证) 提交于 2019-12-03 02:45:02

问题:

I am wiring a gstreamer application with Python. And I get a LinkError with following code:

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() 

And the error:

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 

It is very strange, with same pipeline, but built with parse_launch, it works. Here is the code:

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() 

Here comes the question, why the manual one failed, but the parsed one success? What's wrong with that? How can I fix it?

Thanks.

回答1:

your problem is here:

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

the reason is that not all elements have simple, static inputs and outputs. at this point in your program, your decodebin does not have any source pads (that is: no outputs).

a pad is like a nipple - it's an input / output to an element. pads can appear, disappear or just sit there. there are three classes of pads: static pads (the easiest and what you would expect), request pads (that appear only when you ask for them) and sometimes pads (that appear only when the element wants to make them appear). the outputs of decodebin are sometimes pads.

if you inspect the output of gst-inspect decodebin, you can see this for yourself:

Pad Templates:   SINK template: 'sink'     Availability: Always     Capabilities:       ANY    SRC template: 'src%d'     Availability: Sometimes     Capabilities:       ANY 

at line 26 of your program, you can't link decode to anything, because it doesn't have any source pads to link with. source pads on a decodebin appear only as the input stream is decoded: this doesn't happen instantaneously. any number of source pads may appear (e.g one for an audio stream, two for a video stream with audio, none for an un-decodable stream).

you need to wait until the pads are created, and then link them. decodebin emits a signal, "new-decoded-pad" to tell you when this happens (this is also documented in gst-inspect decodebin). you must connect a callback function to this signal, and link your decode and audioconvert in the callback. here is your corrected code:

#!/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 works because it takes care of all these niggly details for you. there is also the high level element playbin which automatically creates and links a decodebin internally.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!