0

在 python 中使用 Gstreamer 'playbin' 'set_window_handle' 代码告诉 Gstreamer 渲染视频的窗口 ID:

这适用于标准 Linux Mate,也适用于运行 Ubuntu-Mate 的 Raspberry Pi 3。然而,在同一个 Raspberry 上运行但运行的是最新的 Raspbian 操作系统,Gstreamer 完全忽略了在特定窗口中运行的指令,而是创建了自己的窗口,在屏幕中间。
如果新窗口能够被操纵、移动和/或调整大小但它不能,这不会是一个问题。它不能移动,不能关闭,鼠标指针消失在它后面。
有谁知道这是否是 Raspbian、X windows 或 Gstreamer 中的错误,或者我没有发现必须实施一些更改才能在 Raspbian OS 上运行?
这是一个最小的工作示例,它说明了上述行为。

#!/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()
4

1 回答 1

0

答案是它是一个错误。
Bugzilla 链接

无论是在 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 中定义视频接收器。在这种情况下,我们只需要等到错误修复进入通用版本。

注意:在 Raspbian 上使用ximagesink
usingxvimagesink会出错,因为 Xv 软件存在没有可用适配器的问题。
Usingglimagesink给我们带来了卡在屏幕中间的可怕窗口,它似乎eglesssink已经悄悄地退出服务,因为它不再包含在 Raspberry 上的 gstreamer 插件中。

于 2016-07-09T07:42:48.347 回答