视频中的奇怪间歇性错误 (GStreamer)

4 投票
1 回答
1140 浏览
提问于 2025-04-17 01:57

我有一个项目,使用的是Python 2.7、PyGTK 2.24和最新版本的PyGST。

在下面的代码中,我遇到了一个奇怪的间歇性错误。第一个错误比较长,视频播放得很好,但错误只会在我关闭视频窗口后出现。第二个错误则根本不让窗口打开。

import pygtk
pygtk.require('2.0')
import gtk, pango
import pygst
pygst.require('0.10')
import gst
import Trailcrest
import os, sys

class Video:

    def __init__(self):

        def on_message(bus, message): 
            if message.type == gst.MESSAGE_EOS: 
                # End of Stream 
                player.set_state(gst.STATE_NULL) 
            elif message.type == gst.MESSAGE_ERROR: 
                player.set_state(gst.STATE_NULL) 
                (err, debug) = message.parse_error() 
                print "Error: %s" % err, debug

        def on_sync_message(bus, message):
            if message.structure is None: 
                return False 
            if message.structure.get_name() == "prepare-xwindow-id":
                if sys.platform == "win32":
                    win_id = videowidget.window.handle
                else:
                    win_id = videowidget.window.xid
                assert win_id
                imagesink = message.src 
                imagesink.set_property("force-aspect-ratio", True)
                imagesink.set_xwindow_id(win_id) 

        win = gtk.Window()
        win.set_resizable(False)
        win.set_has_frame(False)
        win.set_position(gtk.WIN_POS_CENTER)

        fixed = gtk.Fixed()
        win.add(fixed)
        fixed.show()

        videowidget = gtk.DrawingArea()
        fixed.put(videowidget, 0, 0)
        videowidget.set_size_request(640, 480)
        videowidget.show()

        # Setup GStreamer 
        player = gst.element_factory_make("playbin", "MultimediaPlayer")
        bus = player.get_bus() 
        bus.add_signal_watch() 
        bus.enable_sync_message_emission() 
        #used to get messages that GStreamer emits 
        bus.connect("message", on_message) 
        #used for connecting video to your application 
        bus.connect("sync-message::element", on_sync_message)
        player.set_property("uri", "file://" + os.getcwd() + "/VID/SEQ-GAME-OPEN.ogv") 
        player.set_state(gst.STATE_PLAYING)

        win.show()

def main():
    gtk.gdk.threads_init()
    gtk.main()
    return 0

if __name__ == "__main__":
    Video()
    main()

程序 'Video.py' 收到了一个 X 窗口系统的错误。这可能是程序中的一个bug。错误信息是 'BadIDChoice(为这个连接选择了无效的资源ID)'。 (详细信息:序列号 373 错误代码 14 请求代码 1 次要代码 0) (给程序员的提示:通常,X错误是异步报告的;也就是说,你会在造成错误后过一段时间才收到错误信息。为了调试你的程序,可以使用 --sync 命令行选项来改变这种行为。这样你就可以在 gdk_x_error() 函数处获得有意义的回溯信息。)

关于这个,我简单说一下……我按照说明在命令行中运行了 "python Video.py --sync"(我在使用Kubuntu),结果又收到了那个信息。

这是另一个错误——这个错误完全阻止了播放。

python: ../../src/xcb_io.c:221: poll_for_event: 断言 `(((long) (event_sequence) - (long) (dpy->request)) <= 0)' 失败。程序被中止

这两个错误会交替出现,虽然不是完全规律。我可能会先遇到三个第一个错误,然后是两个第二个错误,再来一个第一个,一个第二个,两个第一个,等等。每次都是不同的。

到底发生了什么事?

1 个回答

3

你需要和X服务器同步,才能获取窗口的xid。

下面是具体的做法:

    def on_sync_message(bus, message):
        if message.structure is None:
            return False
        if message.structure.get_name() == "prepare-xwindow-id":
            gtk.gdk.threads_enter()
            gtk.gdk.display_get_default().sync()
            win_id = videowidget.window.xid
            imagesink = message.src
            imagesink.set_property("force-aspect-ratio", True)
            imagesink.set_xwindow_id(win_id)
            gtk.gdk.threads_leave()

撰写回答