我明白一个人不应该从gtk中的其他线程更新UI,或者面临后果,但我不确定在使用gstreamer时我怎么能避免这种情况.
我的应用程序在视频流初始化过程中不时崩溃,并提出以下建议:
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
python: ../../src/xcb_io.c:274: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
在我的代码中,我在GUI类的开头添加了gtk.thread_init()调用:
import pygtk, gtk, gobject
gtk.gdk.threads_init()
(我也试过gobject.threads_init(),但这似乎没什么不同).在一个单独的类中,它在一个单独的线程中运行,我启动一个gstreamer流到tcpserversink(这个gstreamer线程已经是第三个线程,如果有人保持计数).然后另一个线程在最终将数据推送到xvimagesink之前接收此数据.
xvimagesink需要一个视口,我相信这个gstreamer回调函数有时gtk会疯狂,当我分配它时:
def on_sync_message(self, bus, message):
...
if message_name == "prepare-xwindow-id":
# Assign the viewport
imagesink = message.src
imagesink.set_property("force-aspect-ratio", True)
imagesink.set_xwindow_id(self.window_handle.window.xid)
self.window_handle是指向GUI初始化期间分配的self.movie_window = gtk.DrawingArea()的指针.
TL; DR是否有一种安全的方式使用gtk和gstreamer,因为我在调用gst.Pipeline(“name”)时无法避免线程.set_state(gst.STATE_PLAYING)和视图将是GTK绘图区域?
解决方法:
我认为你的问题是你从两个线程访问不受保护的Xlib / xcb – 一次是从你的Gtk UI中一次,一次是在执行你的gstreamer后端回调的线程中 – 这默认是你告诉gstreamer使用的主循环(或线程默认主循环).
gtk.gdk.threads_init()在类型系统初始化后已经被调用(如果我没记错的话,如果我错了,请纠正我).
使用g_idle_add(或使用具有更高优先级的GSource)(线程安全)和回调,该回调调度Gtk主循环中的UI更改(由gtk_main()运行).