Aar*_*hif 7 python xlib gstreamer gtk3
我在Python3中使用Gstreamer在Gtk3中创建了一个视频播放器.除非我添加GtkMenuBar(位置2),否则它的工作原理.然后它将显示黑屏,或者因异常而失败.这个例外引用了XInitThreads我正在调用的(Place 1)(我从pitivi项目中获取了这个),但这似乎并没有产生差异.
问题:我如何使这项工作?
我想知道的其他事情:
系统:
例外:
[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
python3: ../../src/xcb_io.c:179: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.
Run Code Online (Sandbox Code Playgroud)
代码(以尽可能小的形式展示概念):
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gst', '1.0')
gi.require_version('GstVideo', '1.0')
from gi.repository import Gtk, xlib
from gi.repository import Gst, Gdk, GdkX11, GstVideo
Gst.init(None)
Gst.init_check(None)
# Place 1
from ctypes import cdll
x11 = cdll.LoadLibrary('libX11.so')
x11.XInitThreads()
# [xcb] Unknown request in queue while dequeuing
# [xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
# [xcb] Aborting, sorry about that.
# python3: ../../src/xcb_io.c:179: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.
# (foo.py:31933): Gdk-WARNING **: foo.py: Fatal IO error 11 (Resource temporarily unavailable) on X server :1.
class PipelineManager(object):
def __init__(self, window, pipeline):
self.window = window
if isinstance(pipeline, str):
pipeline = Gst.parse_launch(pipeline)
self.pipeline = pipeline
bus = pipeline.get_bus()
bus.set_sync_handler(self.bus_callback)
pipeline.set_state(Gst.State.PLAYING)
def bus_callback(self, bus, message):
if message.type is Gst.MessageType.ELEMENT:
if GstVideo.is_video_overlay_prepare_window_handle_message(message):
Gdk.threads_enter()
Gdk.Display.get_default().sync()
win = self.window.get_property('window')
if isinstance(win, GdkX11.X11Window):
message.src.set_window_handle(win.get_xid())
else:
print('Nope')
Gdk.threads_leave()
return Gst.BusSyncReply.PASS
pipeline = Gst.parse_launch('videotestsrc ! xvimagesink sync=false')
window = Gtk.ApplicationWindow()
header_bar = Gtk.HeaderBar()
header_bar.set_show_close_button(True)
# window.set_titlebar(header_bar) # Place 2
drawing_area = Gtk.DrawingArea()
drawing_area.connect('realize', lambda widget: PipelineManager(widget, pipeline))
window.add(drawing_area)
window.show_all()
def on_destroy(win):
try:
Gtk.main_quit()
except KeyboardInterrupt:
pass
window.connect('destroy', on_destroy)
Gtk.main()
Run Code Online (Sandbox Code Playgroud)
当在一个单独的问题上搜索文档时,我遇到了对gtksink小部件的引用。这似乎是将视频放在gtk窗口中的正确方法,但不幸的是,与此相关的所有教程都没有使用它。
使用gtksink小部件可解决所有问题,并大大降低了代码复杂度。
修改后的代码:
from pprint import pprint
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gst', '1.0')
gi.require_version('GstVideo', '1.0')
from gi.repository import Gtk, Gst
Gst.init(None)
Gst.init_check(None)
class GstWidget(Gtk.Box):
def __init__(self, pipeline):
super().__init__()
self.connect('realize', self._on_realize)
self._bin = Gst.parse_bin_from_description('videotestsrc', True)
def _on_realize(self, widget):
pipeline = Gst.Pipeline()
factory = pipeline.get_factory()
gtksink = factory.make('gtksink')
pipeline.add(gtksink)
pipeline.add(self._bin)
self._bin.link(gtksink)
self.pack_start(gtksink.props.widget, True, True, 0)
gtksink.props.widget.show()
pipeline.set_state(Gst.State.PLAYING)
window = Gtk.ApplicationWindow()
header_bar = Gtk.HeaderBar()
header_bar.set_show_close_button(True)
window.set_titlebar(header_bar) # Place 2
widget = GstWidget('videotestsrc')
widget.set_size_request(200, 200)
window.add(widget)
window.show_all()
def on_destroy(win):
try:
Gtk.main_quit()
except KeyboardInterrupt:
pass
window.connect('destroy', on_destroy)
Gtk.main()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
871 次 |
| 最近记录: |