Get the window handle in PyGI

后端 未结 2 687
面向向阳花
面向向阳花 2021-01-16 12:54

In my program I use PyGObject/PyGI and GStreamer to show a video in my GUI. The video is shown in a Gtk.DrawingArea and therefore I need to get it\'s window-han

相关标签:
2条回答
  • 2021-01-16 13:22

    I finally got it. To address the "window handle"-issue I use the workaround/hack by Marwin Schmitt (see here):

    def _on_video_realize(self, widget):
        # The window handle must be retrieved first in GUI-thread and before
        # playing pipeline.
        video_window = self._drawing_area.get_property('window')
        if sys.platform == "win32":
            if not video_window.ensure_native():
                print("Error - video playback requires a native window")
            ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
            ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object]
            drawingarea_gpointer = ctypes.pythonapi.PyCapsule_GetPointer(video_window.__gpointer__, None)
            gdkdll = ctypes.CDLL ("libgdk-3-0.dll")
            self._video_window_handle = gdkdll.gdk_win32_window_get_handle(drawingarea_gpointer)
        else:
            self._video_window_handle = video_window.get_xid()
    

    But there was also the problem, that the "sync-message"-handler was never called. I found out that not all video sinks support embedded video, see here. For example the d3dvideosink does support embedded video, but I was running Windows in a virtual machine and even though 3D hardware acceleration was activated it probably didn't work. Running the same code on a non-virtualized Windows leads to a callback to the "sync-message"-handler where the previously fetched window-handle can be set:

    def _on_player_sync_message(self, bus, message):
        if message.get_structure() is None:
            return
        if not GstVideo.is_video_overlay_prepare_window_handle_message(message):
            return
        imagesink = message.src
        imagesink.set_property("force-aspect-ratio", True)
        imagesink.set_window_handle(self._video_window_handle)
    

    Playback on Windows works fine now.

    0 讨论(0)
  • 2021-01-16 13:30

    Have you tried:

    def OnSyncMessage(self, bus, msg):
        if msg.get_structure() is None:
            return True
        message_name = msg.get_structure().get_name()
        if message_name == 'prepare-window-handle':
            imagesink = msg.src
            imagesink.set_property('force-aspect-ratio', True)
            imagesink.set_window_handle(self.DrawingArea.GetHandle())
        return True    
    
    0 讨论(0)
提交回复
热议问题