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