Using Gstreamer 'playbin' in python the 'set_window_handle' code tells Gstreamer the window id in which to render the video:
This works in standard Linux Mate and also on a Raspberry Pi 3 running Ubuntu-Mate. However, running on the same Raspberry but running an up to date Raspbian OS, Gstreamer totally ignores the instruction to run in a specific window, instead it creates its own window, smack in the middle of the screen.
This wouldn't be an issue, if the new window was capable of being manipulated, moved and/or resized but it can't. It cannot be moved, it cannot be closed and the mouse pointer vanishes behind it.
Does anyone know if this is a bug in Raspbian, X windows or Gstreamer or have I not spotted some change that has to be implemented for this to work on the Raspbian OS?
Here is a minimal, working example, which illustrates the behaviour described above.
#!/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()