2016-10-17 6 views
5

나는 파이썬 3에서 Gstreamer를 사용하여 Gtk3에서 비디오 플레이어를 만들었습니다. GtkMenuBar (장소 2)를 추가 할 때를 제외하고 작동합니다. 그런 다음 검정색 화면이 표시되거나 예외가 발생하여 실패합니다. 예외는 XInitThreads을 참조하는데, 이것은 (장소 1) (pitivi 프로젝트에서 가져 왔습니다.)하지만 이것은 diffrence를 만드는 것처럼 보이지 않습니다.메뉴 모음이있는 창에서 Gtk로 비디오 재생

질문 : 어떻게해야합니까? 내가 알고 싶습니다

다른 것들 :

  1. 왜 도구 모음이 휴식 것?
  2. 이것은 분명히 X가 아닌 모든 요소를 ​​손상시킬 것입니다.이 논리를 추상화 한 사전 구성 요소가 있습니까? 그리고 누락 된 교차 플랫폼입니까?

시스템 :

  • python3
  • Gtk3
  • 우분투 16.04

예외 :

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

코드 (POS 작게 형태 sible) 개념을 설명합니다 :

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

내가 질문에 대답 할 수는 없지만이 훌륭한 질문이다. 주제에 관해서는 문서에서 간단한 것이 아닌 특별한 문제가 완벽한 MCVE를 제공하고 오류 메시지, 시스템 정보, 코드 목적 등을 보여줍니다. 이것은 질문하는 방법의 예입니다. – oldtechaa

답변

2

별도의 문제에 대한 문서를 검색, 나는 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()