GStreamer系列之概览¶
playbin是一个高级别的,自动化的音视频播放器,一般来说,它会播放发送给他的任何 支持的多媒体数据。
playbin的内部看起来是这个样子的:
playbin
____________________________________________________________________
| ________________ _______________ |
| | | | | |
| ->-| optional stuff |->-| autoaudiosink |->-|->- Audio Output
| ________________ | |________________| |_______________| |
| | |-- |
uri ->-|->-| uridecodebin | |
| |________________|-- ________________ _______________ |
| | | | | | |
| ->-| optional stuff |->-| autovideosink |->-|->- Video Output
| |________________| |_______________| |
|____________________________________________________________________|
“uri” 属性可以使用任何GStreamer插件支持的协议。playbin支持你将sink换成其他的,就 像我们在下面的例子中做的。一般来说,playbin总是会自动设置好你所要的一切,因此你 不要指定那些playbin没有实现的特性,开箱即用就不错的。
Example 1:播放起来¶
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 | import sys, os
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, Gtk, GObject
GObject.threads_init()
Gst.init(None)
class PlayBin(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title='Audio Player')
self.set_default_size(300, -1)
self.connect('delete-event', Gtk.main_quit)
vbox = Gtk.VBox()
self.add(vbox)
self.entry = Gtk.Entry()
vbox.pack_start(self.entry, False, True, 0)
self.button = Gtk.ToggleButton('Start')
self.button.connect('clicked', self.start_stop)
vbox.add(self.button)
self.show_all()
# build a palyer
self.player = Gst.ElementFactory.make('playbin', 'player')
# we don't need video output
#fakesink = Gst.ElementFactory.make('fakesink', 'fakesink')
#self.player.set_property('video-sink', fakesink)
bus = self.player.get_bus()
bus.add_signal_watch()
bus.connect('message', self.on_message)
def start_stop(self, widget):
if self.button.get_active():
filepath = self.entry.get_text()
if os.path.isfile(filepath):
self.button.set_label('Stop')
self.player.set_property('uri', 'file://'+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, message):
t = message.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)
err, debug = message.parse_error()
print('Error: %s' %err, debug)
self.button.set_label('Start')
win = PlayBin()
Gtk.main()
|
由于playbin插件总是会自动播放音视频流,因此我们将视频重定向至 fakesink
,这
相当于Gstreamer中的 /dev/null
。你如果想要播放视频流,只需要注释掉这两行代码
#fakesink = Gst.ElementFactory.make('fakesink', 'fakesink')
#self.player.set_property('video-sink', fakesink)
Example 2:控制视频的显示¶
当然上面的例子在播放视频时总是会打开一个新的窗口,如果你想要在指定的窗口播放则
需要使用 enable_sync_message_emission()
方法。
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 | import sys, os
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, Gtk, GObject
# important!!! needed by window.get_xid(), xvimagesink.set_window_handle.
from gi.repository import GdkX11, GstVideo
GObject.threads_init()
Gst.init(None)
class PlayBin(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title='Audio Player')
self.set_default_size(500, 400)
self.connect('delete-event', Gtk.main_quit)
vbox = Gtk.VBox()
self.add(vbox)
hbox = Gtk.HBox()
vbox.pack_start(hbox, False, False, 0)
self.entry = Gtk.Entry()
hbox.pack_start(self.entry, True, True, 0)
self.button = Gtk.ToggleButton('Start')
self.button.connect('clicked', self.start_stop)
hbox.add(self.button)
self.movie = Gtk.DrawingArea()
vbox.add(self.movie)
# build a palyer
self.player = Gst.ElementFactory.make('playbin', 'player2')
bus = self.player.get_bus()
bus.add_signal_watch()
bus.connect('message', self.on_message)
bus.enable_sync_message_emission()
bus.connect('sync-message::element', self.on_sync_message)
self.show_all()
self.xid = self.movie.get_property('window').get_xid()
def start_stop(self, widget):
if self.button.get_active():
filepath = self.entry.get_text()
if os.path.isfile(filepath):
self.button.set_label('Stop')
self.player.set_property('uri', 'file://'+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, message):
t = message.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)
err, debug = message.parse_error()
print('Error: %s' %err, debug)
self.button.set_label('Start')
def on_sync_message(self, bus, message):
if message.get_structure().get_name() == 'prepare-window-handle':
message.src.set_window_handle(self.xid)
win = PlayBin()
Gtk.main()
|
Example 3:添加时间显示¶
我们可以让事情变的更有趣,我们将playbin的 videosink 切换为我们自己的GHostPad, 并在上面增加了一个时间显示的小元素。
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 72 73 74 75 76 77 78 79 80 81 | import sys, os
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, Gtk, GObject
# important!!! needed by window.get_xid(), xvimagesink.set_window_handle.
from gi.repository import GdkX11, GstVideo
GObject.threads_init()
Gst.init(None)
class PlayBin(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title='Audio Player')
self.set_default_size(500, 400)
self.connect('delete-event', Gtk.main_quit)
vbox = Gtk.VBox()
self.add(vbox)
hbox = Gtk.HBox()
vbox.pack_start(hbox, False, False, 0)
self.entry = Gtk.Entry()
hbox.pack_start(self.entry, True, True, 0)
self.button = Gtk.ToggleButton('Start')
self.button.connect('clicked', self.start_stop)
hbox.add(self.button)
self.movie = Gtk.DrawingArea()
vbox.add(self.movie)
# build a palyer
self.player = Gst.ElementFactory.make('playbin', 'player2')
mybin = Gst.Bin()
timeoverlay = Gst.ElementFactory.make('timeoverlay', 'timeoverlay')
mybin.add(timeoverlay)
pad = timeoverlay.get_static_pad('video_sink')
ghostpad = Gst.GhostPad.new('sink', pad)
mybin.add_pad(ghostpad)
videosink = Gst.ElementFactory.make('autovideosink', 'autovideosin')
mybin.add(videosink)
timeoverlay.link(videosink)
self.player.set_property('video-sink', mybin)
bus = self.player.get_bus()
bus.add_signal_watch()
bus.connect('message', self.on_message)
bus.enable_sync_message_emission()
bus.connect('sync-message::element', self.on_sync_message)
self.show_all()
self.xid = self.movie.get_property('window').get_xid()
def start_stop(self, widget):
if self.button.get_active():
filepath = self.entry.get_text()
if os.path.isfile(filepath):
self.button.set_label('Stop')
self.player.set_property('uri', 'file://'+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, message):
t = message.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)
err, debug = message.parse_error()
print('Error: %s' %err, debug)
self.button.set_label('Start')
def on_sync_message(self, bus, message):
if message.get_structure().get_name() == 'prepare-window-handle':
message.src.set_window_handle(self.xid)
win = PlayBin()
Gtk.main()
|