在 Raspbian 上定义 gstreamer 视频 window 的问题
Issue defining gstreamer video window on Raspbian
在 python 中使用 Gstreamer 'playbin' 'set_window_handle' 代码告诉 Gstreamer 在其中呈现视频的 window id:
这适用于标准 Linux Mate 和 Raspberry Pi 3 运行ning Ubuntu-Mate。然而,运行ning 在同一个 Raspberry 上 运行ning 一个最新的 Raspbian OS,Gstreamer 完全忽略了特定 [=] 中 运行 的指令33=],而是在屏幕中间创建自己的 window。
如果新 window 能够被操纵、移动 and/or 并调整大小但它不能,这将不是问题。无法移动,无法关闭,鼠标指针消失在其后。
有谁知道这是 Raspbian、X windows 或 Gstreamer 中的错误,还是我没有发现必须实施的一些更改才能在 Raspbian [=27= 上运行]?
这是一个最小的工作示例,它说明了上述行为。
#!/usr/bin/env python
import os,time
import wx
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstVideo', '1.0')
from gi.repository import Gst
from gi.repository import GstVideo
class Player(wx.App):
def OnInit(self):
window = wx.Frame(None)
window.SetTitle("Gstreamer Player Test")
window.SetSize((-1,-1))
window.Bind(wx.EVT_CLOSE,self.close)
vbox = wx.BoxSizer(wx.VERTICAL)
hbox = wx.BoxSizer(wx.HORIZONTAL)
self.fileid = wx.TextCtrl(window,style=wx.TE_PROCESS_ENTER)
self.fileid.SetToolTipString("Enter full path to media file")
hbox.Add(self.fileid, 1)
self.start = wx.Button(window,label="Start")
hbox.Add(self.start, 0)
self.start.Bind(wx.EVT_BUTTON, self.control)
self.fileid.Bind(wx.EVT_TEXT_ENTER, self.control)
vbox.Add(hbox, 0, wx.EXPAND, 0)
self.video_window = wx.Panel(window)
vbox.Add(self.video_window,1,wx.EXPAND,5)
window.SetSizer(vbox)
window.Layout()
window.Show()
self.SetTopWindow(window)
Gst.init(None) #initialise gstreamer
self.player = Gst.ElementFactory.make("playbin", "player")
bus = self.player.get_bus()
bus.add_signal_watch() #hook up bus to signals from gstreamer
bus.enable_sync_message_emission()
bus.connect('message', self.on_message)
bus.connect('sync-message::element', self.on_sync_message)
return True
def control(self, event):
if self.start.GetLabel() == "Start":
fileid = self.fileid.GetValue()
if os.path.exists(fileid):
self.start.SetLabel("Stop")
fileid = "file://"+unicode(fileid)
self.player.set_property('uri', fileid)
self.player.set_state(Gst.State.PLAYING)
else:
print "File error - No such file"
else:
self.player.set_state(Gst.State.NULL)
self.start.SetLabel("Start")
def on_message(self, bus, message):
t = message.type
if t == Gst.MessageType.EOS: # media has ended
self.player.set_state(Gst.State.NULL)
self.button.SetLabel("Start")
elif t == Gst.MessageType.ERROR:
print "Player error"
self.player.set_state(Gst.State.NULL)
self.start.SetLabel("Start")
def on_sync_message(self, bus, message):
if message.get_structure() is None:
return True
message_name = message.get_structure().get_name()
if message_name == 'prepare-window-handle': #Assign the window id to display in
imagesink = message.src
imagesink.set_property('force-aspect-ratio', True) #Force size to fit window
X_id = self.video_window.GetHandle()
print ("Window Id:", X_id)
imagesink.set_window_handle(X_id)
return True
def close(self,event):
self.player.set_state(Gst.State.NULL)
time.sleep(0.1) #Allow a little time to reach Null state
event.Skip()
app = Player()
app.MainLoop()
答案是这是一个错误。
Bugzilla link
它是在 gstreamer 中还是在 Rpi 堆栈中似乎是一个有争议的问题。
解决方案是在playbin管道中指定videosink。
所以对于这个特定的程序应该读作如下:
#!/usr/bin/env python
import os,time
import wx
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstVideo', '1.0')
from gi.repository import Gst
from gi.repository import GstVideo
class Player(wx.App):
def OnInit(self):
window = wx.Frame(None)
window.SetTitle("Gstreamer Player Test")
window.SetSize((-1,-1))
window.Bind(wx.EVT_CLOSE,self.close)
vbox = wx.BoxSizer(wx.VERTICAL)
hbox = wx.BoxSizer(wx.HORIZONTAL)
self.fileid = wx.TextCtrl(window,style=wx.TE_PROCESS_ENTER)
self.fileid.SetToolTipString("Enter full path to media file")
hbox.Add(self.fileid, 1)
self.start = wx.Button(window,label="Start")
hbox.Add(self.start, 0)
self.start.Bind(wx.EVT_BUTTON, self.control)
self.fileid.Bind(wx.EVT_TEXT_ENTER, self.control)
vbox.Add(hbox, 0, wx.EXPAND, 0)
video_window = wx.Panel(window)
vbox.Add(video_window,1,wx.EXPAND,5)
window.SetSizer(vbox)
window.Layout()
window.Show()
self.SetTopWindow(window)
Gst.init(None) #initialise gstreamer
self.X_id = video_window.GetHandle()
self.player = Gst.ElementFactory.make("playbin", "player")
# self.ximagesink = Gst.ElementFactory.make("xvimagesink", None)
self.ximagesink = Gst.ElementFactory.make("ximagesink", None)
self.player.set_property('video-sink', self.ximagesink)
bus = self.player.get_bus()
bus.add_signal_watch() #hook up bus to signals from gstreamer
bus.enable_sync_message_emission()
bus.connect('message', self.on_message)
bus.connect('sync-message::element', self.on_sync_message)
return True
def control(self, event):
if self.start.GetLabel() == "Start":
fileid = self.fileid.GetValue()
if os.path.exists(fileid):
self.start.SetLabel("Stop")
fileid = "file://"+unicode(fileid)
self.player.set_property('uri', fileid)
self.player.set_state(Gst.State.PLAYING)
else:
print "File error - No such file"
else:
self.player.set_state(Gst.State.NULL)
self.start.SetLabel("Start")
def on_message(self, bus, message):
t = message.type
if t == Gst.MessageType.EOS: # media has ended
self.player.set_state(Gst.State.NULL)
self.button.SetLabel("Start")
elif t == Gst.MessageType.ERROR:
print "Player error"
self.player.set_state(Gst.State.NULL)
self.start.SetLabel("Start")
def on_sync_message(self, bus, message):
if message.get_structure() is None:
return True
message_name = message.get_structure().get_name()
if message_name == 'prepare-window-handle': #Assign the window id to display in
imagesink = message.src
# imagesink.set_property('force-aspect-ratio', True) #Defaults anyway
imagesink.set_window_handle(self.X_id)
return True
def close(self,event):
self.player.set_state(Gst.State.NULL)
time.sleep(0.1) #Allow a little time to reach Null state
event.Skip()
app = Player()
app.MainLoop()
但是,如果您在 LibreOffice 宏中使用 "com.sun.star.comp.avmedia.Manager_GStreamer" 遇到同样的问题,这对您没有任何好处,因为 Libreoffice 开发人员做出了与我相同的假设,而且似乎没有办法从 Libreoffice 中定义视频接收器。在这种情况下,我们只需等待错误修复进入一般版本即可。
注意事项:使用ximagesink
使用 xvimagesink
在 Raspbian 上出现错误,因为 Xv 软件存在没有适配器可用的问题。
使用 glimagesink
给我们带来了可怕的 window 卡在屏幕中间,似乎 eglesssink
已经悄悄退出服务,因为它不再包含在 gstreamer 插件中覆盆子。
在 python 中使用 Gstreamer 'playbin' 'set_window_handle' 代码告诉 Gstreamer 在其中呈现视频的 window id:
这适用于标准 Linux Mate 和 Raspberry Pi 3 运行ning Ubuntu-Mate。然而,运行ning 在同一个 Raspberry 上 运行ning 一个最新的 Raspbian OS,Gstreamer 完全忽略了特定 [=] 中 运行 的指令33=],而是在屏幕中间创建自己的 window。
如果新 window 能够被操纵、移动 and/or 并调整大小但它不能,这将不是问题。无法移动,无法关闭,鼠标指针消失在其后。
有谁知道这是 Raspbian、X windows 或 Gstreamer 中的错误,还是我没有发现必须实施的一些更改才能在 Raspbian [=27= 上运行]?
这是一个最小的工作示例,它说明了上述行为。
#!/usr/bin/env python
import os,time
import wx
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstVideo', '1.0')
from gi.repository import Gst
from gi.repository import GstVideo
class Player(wx.App):
def OnInit(self):
window = wx.Frame(None)
window.SetTitle("Gstreamer Player Test")
window.SetSize((-1,-1))
window.Bind(wx.EVT_CLOSE,self.close)
vbox = wx.BoxSizer(wx.VERTICAL)
hbox = wx.BoxSizer(wx.HORIZONTAL)
self.fileid = wx.TextCtrl(window,style=wx.TE_PROCESS_ENTER)
self.fileid.SetToolTipString("Enter full path to media file")
hbox.Add(self.fileid, 1)
self.start = wx.Button(window,label="Start")
hbox.Add(self.start, 0)
self.start.Bind(wx.EVT_BUTTON, self.control)
self.fileid.Bind(wx.EVT_TEXT_ENTER, self.control)
vbox.Add(hbox, 0, wx.EXPAND, 0)
self.video_window = wx.Panel(window)
vbox.Add(self.video_window,1,wx.EXPAND,5)
window.SetSizer(vbox)
window.Layout()
window.Show()
self.SetTopWindow(window)
Gst.init(None) #initialise gstreamer
self.player = Gst.ElementFactory.make("playbin", "player")
bus = self.player.get_bus()
bus.add_signal_watch() #hook up bus to signals from gstreamer
bus.enable_sync_message_emission()
bus.connect('message', self.on_message)
bus.connect('sync-message::element', self.on_sync_message)
return True
def control(self, event):
if self.start.GetLabel() == "Start":
fileid = self.fileid.GetValue()
if os.path.exists(fileid):
self.start.SetLabel("Stop")
fileid = "file://"+unicode(fileid)
self.player.set_property('uri', fileid)
self.player.set_state(Gst.State.PLAYING)
else:
print "File error - No such file"
else:
self.player.set_state(Gst.State.NULL)
self.start.SetLabel("Start")
def on_message(self, bus, message):
t = message.type
if t == Gst.MessageType.EOS: # media has ended
self.player.set_state(Gst.State.NULL)
self.button.SetLabel("Start")
elif t == Gst.MessageType.ERROR:
print "Player error"
self.player.set_state(Gst.State.NULL)
self.start.SetLabel("Start")
def on_sync_message(self, bus, message):
if message.get_structure() is None:
return True
message_name = message.get_structure().get_name()
if message_name == 'prepare-window-handle': #Assign the window id to display in
imagesink = message.src
imagesink.set_property('force-aspect-ratio', True) #Force size to fit window
X_id = self.video_window.GetHandle()
print ("Window Id:", X_id)
imagesink.set_window_handle(X_id)
return True
def close(self,event):
self.player.set_state(Gst.State.NULL)
time.sleep(0.1) #Allow a little time to reach Null state
event.Skip()
app = Player()
app.MainLoop()
答案是这是一个错误。
Bugzilla link
它是在 gstreamer 中还是在 Rpi 堆栈中似乎是一个有争议的问题。
解决方案是在playbin管道中指定videosink。
所以对于这个特定的程序应该读作如下:
#!/usr/bin/env python
import os,time
import wx
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstVideo', '1.0')
from gi.repository import Gst
from gi.repository import GstVideo
class Player(wx.App):
def OnInit(self):
window = wx.Frame(None)
window.SetTitle("Gstreamer Player Test")
window.SetSize((-1,-1))
window.Bind(wx.EVT_CLOSE,self.close)
vbox = wx.BoxSizer(wx.VERTICAL)
hbox = wx.BoxSizer(wx.HORIZONTAL)
self.fileid = wx.TextCtrl(window,style=wx.TE_PROCESS_ENTER)
self.fileid.SetToolTipString("Enter full path to media file")
hbox.Add(self.fileid, 1)
self.start = wx.Button(window,label="Start")
hbox.Add(self.start, 0)
self.start.Bind(wx.EVT_BUTTON, self.control)
self.fileid.Bind(wx.EVT_TEXT_ENTER, self.control)
vbox.Add(hbox, 0, wx.EXPAND, 0)
video_window = wx.Panel(window)
vbox.Add(video_window,1,wx.EXPAND,5)
window.SetSizer(vbox)
window.Layout()
window.Show()
self.SetTopWindow(window)
Gst.init(None) #initialise gstreamer
self.X_id = video_window.GetHandle()
self.player = Gst.ElementFactory.make("playbin", "player")
# self.ximagesink = Gst.ElementFactory.make("xvimagesink", None)
self.ximagesink = Gst.ElementFactory.make("ximagesink", None)
self.player.set_property('video-sink', self.ximagesink)
bus = self.player.get_bus()
bus.add_signal_watch() #hook up bus to signals from gstreamer
bus.enable_sync_message_emission()
bus.connect('message', self.on_message)
bus.connect('sync-message::element', self.on_sync_message)
return True
def control(self, event):
if self.start.GetLabel() == "Start":
fileid = self.fileid.GetValue()
if os.path.exists(fileid):
self.start.SetLabel("Stop")
fileid = "file://"+unicode(fileid)
self.player.set_property('uri', fileid)
self.player.set_state(Gst.State.PLAYING)
else:
print "File error - No such file"
else:
self.player.set_state(Gst.State.NULL)
self.start.SetLabel("Start")
def on_message(self, bus, message):
t = message.type
if t == Gst.MessageType.EOS: # media has ended
self.player.set_state(Gst.State.NULL)
self.button.SetLabel("Start")
elif t == Gst.MessageType.ERROR:
print "Player error"
self.player.set_state(Gst.State.NULL)
self.start.SetLabel("Start")
def on_sync_message(self, bus, message):
if message.get_structure() is None:
return True
message_name = message.get_structure().get_name()
if message_name == 'prepare-window-handle': #Assign the window id to display in
imagesink = message.src
# imagesink.set_property('force-aspect-ratio', True) #Defaults anyway
imagesink.set_window_handle(self.X_id)
return True
def close(self,event):
self.player.set_state(Gst.State.NULL)
time.sleep(0.1) #Allow a little time to reach Null state
event.Skip()
app = Player()
app.MainLoop()
但是,如果您在 LibreOffice 宏中使用 "com.sun.star.comp.avmedia.Manager_GStreamer" 遇到同样的问题,这对您没有任何好处,因为 Libreoffice 开发人员做出了与我相同的假设,而且似乎没有办法从 Libreoffice 中定义视频接收器。在这种情况下,我们只需等待错误修复进入一般版本即可。
注意事项:使用ximagesink
使用 xvimagesink
在 Raspbian 上出现错误,因为 Xv 软件存在没有适配器可用的问题。
使用 glimagesink
给我们带来了可怕的 window 卡在屏幕中间,似乎 eglesssink
已经悄悄退出服务,因为它不再包含在 gstreamer 插件中覆盆子。