GStreamer系列之管道¶
管道是带有其自己的bus和clock的高级bin,如果你的程序只包含bin一样的对象,这就是 你想要的。你可以如下创建一个管道对象:
mypipeline = Gst.Pipeline()
其实管道就是一个容器,你可以把其他对象放进去,然后指定要播放的文件并设置管道
的状态为 Gst.State.Playing
,这样就会有多媒体流在管道里流到了。
例如,如下的一个音乐播放器的例子,使用了我们自己的mp3解码器代替了上一章中的playbin。
你可以直接使用 gst-lanuch-1.0
来测试管道:
$ gst-launch-1.0 filesrc location=ydcyxf.mp3 ! mad ! audioconvert ! alsasink
使用ASCII的图表可以形象地表示上面这行代码:
Gst.Pipeline
_____________________________________________________________________
| |
| _________ _______ ______________ __________ |
| | | | | | | | | |
file.mp3 ->-|---| filesrc |-->--| mad |-->--| audioconvert |-->--| alsasink |---|->- Audio Output
| |_________| |_______| |______________| |__________| |
| |
|_____________________________________________________________________|
以下是python代码的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | import sys, os
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject, Gtk
GObject.threads_init()
Gst.init(None)
class PipeMain(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title='MP3-Player')
self.resize(400, 200)
self.connect('delete-event', Gtk.main_quit)
vbox = Gtk.VBox()
self.add(vbox)
self.entry = Gtk.Entry()
vbox.pack_start(self.entry, False, True, 1)
self.button = Gtk.Button('Start')
self.button.connect('clicked', self.start_stop)
vbox.add(self.button)
self.show_all()
self.player = Gst.Pipeline()
source = Gst.ElementFactory.make('filesrc', 'file-source')
decoder = Gst.ElementFactory.make('mad', 'mp3-decoder')
conv = Gst.ElementFactory.make('audioconvert', 'converter')
sink = Gst.ElementFactory.make('alsasink', 'alsa-output')
self.player.add(source)
self.player.add(decoder)
self.player.add(conv)
self.player.add(sink)
source.link(decoder)
decoder.link(conv)
conv.link(sink)
bus = self.player.get_bus()
bus.add_signal_watch()
bus.connect('message', self.on_message)
def start_stop(self, w):
if self.button.get_label() == 'Start':
filepath = self.entry.get_text()
print(filepath)
if os.path.isfile(filepath):
self.button.set_label('Stop')
self.player.get_by_name('file-source').set_property('location', filepath)
self.player.set_state(Gst.State.PLAYING)
else:
self.player.set_state(Gst.State.NULL)
self.button.set_label('Start')
def on_message(self, bus, msg):
t = msg.type
if t == Gst.MessageType.EOS:
self.player.set_state(Gst.State.NULL)
self.button.set_label('Start')
elif t == Gst.MessageType.ERROR:
self.player.set_state(Gst.State.NULL)
self.button.set_label('Start')
err, debug = msg.parse_error()
print('Error:%s' % err)
if __name__ == '__main__':
PipeMain()
Gtk.main()
|