2016-10-17 14 views
5

Tôi đã tạo trình phát video trong Gtk3 bằng Gstreamer bằng Python3. Nó hoạt động ngoại trừ khi tôi thêm một GtkMenuBar (nơi 2). Sau đó nó sẽ hiển thị một màn hình màu đen, hoặc thất bại với một ngoại lệ. Ngoại lệ tham chiếu đến XInitThreads, mà tôi đang gọi (Place 1) (tôi lấy nó từ dự án pitivi) nhưng điều này dường như không tạo ra sự khác biệt.Phát video trong Gtk trong cửa sổ có thanh thực đơn

Câu hỏi: Làm thế nào để tôi thực hiện công việc này?

Những điều khác tôi muốn biết:

  1. Tại sao các thanh menu sẽ phá vỡ này?
  2. Điều này rõ ràng sẽ phá vỡ mọi thứ không phải X, có một số thành phần dựng sẵn tóm tắt logic này và là nền tảng mà tôi đang thiếu?

hệ thống:

  • python3
  • Gtk3
  • Ubuntu 16,04

Trường hợp ngoại lệ:

[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. 

Mã này (trong một hình thức nhỏ như pos sible để chứng minh khái niệm):

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() 
+1

Tôi không thể trả lời câu hỏi, nhưng đây là một câu hỏi tuyệt vời. Về chủ đề, một vấn đề cụ thể, không đơn giản trong tài liệu, cung cấp MCVE hoàn hảo, hiển thị thông báo lỗi, thông tin hệ thống, mục đích mã, v.v. Đây là ví dụ về cách đặt câu hỏi. – oldtechaa

Trả lời

2

Khi tìm kiếm qua tài liệu về một vấn đề riêng biệt, tôi đi qua một tham chiếu đến các widget gtksink. Đây có vẻ là cách chính xác để đưa video vào cửa sổ gtk, nhưng tiếc là không có hướng dẫn nào trong số này sử dụng video đó.

Sử dụng tiện ích gtksink khắc phục tất cả sự cố và giảm đáng kể độ phức tạp của mã.

Mã sửa đổi:

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() 
Các vấn đề liên quan