大家好,我正在python中编写Gtk+GUI应用程序,该应用程序使用onvif Iam播放视频并移动相机,使用应用程序中SOAP服务的异步调用。但实际情况是,当我按下其中一个移动相机的按钮时,视频会挂起一秒钟,然后在按下按钮时它是可以的,但当它释放时,它会再次挂起。
Onvif连续移动类
class ContinuousMove(threading.Thread):
def __init__(self,onvif_service):
threading.Thread.__init__(self)
self.start()
self.onvif_service=onvif_service
self.position=self.onvif_service.get_client().factory.create('ns4:PTZVector')
self.profileToken=self.onvif_service.get_client().factory.create('ns4:ReferenceToken')
self.speed=self.onvif_service.get_client().factory.create('ns4:PTZSpeed')
self.timeout=self.onvif_service.get_client().factory.create('ns4:Timeout')
self.executor=concurrent.futures.ThreadPoolExecutor(max_workers=1)
def move(self,x,y,zoom):
future = self.executor.submit(self.__move__,x,y,zoom)
def __move__(self,x,y,zoom):
self.position.PanTilt._x=x
self.position.PanTilt._y=y
self.position.Zoom._x=zoom
self.profileToken='media_profile1'
self.onvif_service.get_client().service.ContinuousMove(self.profileToken,self.position)
正如你在这里看到的,我使用了conncurent.future模块和他们的类ThreadPoolExecutor进行异步调用
接下来,我在播放器类中创建ContinuousMove类的实例,该类扩展了Gtk.Window然后我创建按钮并设置事件回调。
class player(Gtk.Window):
#bunch of functions
def __init__(self):
Gtk.Window.__init__(self):
self.gui_init()
self.camera=ContinuousMove(onvif_service)
self.player=Player(self.previewArea)#class which constructs gstreamer pipeline and renders it on previewArea
def gui_init(self):
self.previewArea=Gtk.RenderArea()
self.buttonDown=Gtk.Button("DOWN")
self.buttonDown.connect("pressed",self.on_down_pressed)
def on_down_pressed(self,btn):
#instance of ContinuousMove
self.Camera.move(0,-0.1,0)
app=player()
app.show_all()
Gtk.main()
如果你能告诉我我在这里做错了什么,以及为什么视频挂起,我将不胜感激。
PS:
没有粘贴整个代码,因为它太庞大了。我希望你能从中理解问题。
编辑:
我添加了Player对象和RenderArea对象的init,因为我认为它与这个问题有关。我初始化Player对象并发送它RenderArea,这样它就可以向它渲染视频。现在的问题是按钮小部件会以某种方式阻止RenderArea小部件吗?
我会详细解释会发生什么。例如,当我按下DOWN按钮时,它会冻结视频一秒钟,看起来就像跳过了几帧。尝试了几乎所有的东西,但似乎都不起作用。问题既不是RenderArea,也不是Gstreamer问题是移动方法和/或按钮按下事件。
on_down_pressed()
看起来像一个事件处理程序。如果它被阻止,那么GUI就会"冻结"(不响应)。
with
-语句在阻止该方法的出口调用executor.shutdown(wait=True)
。为了避免Camera.move()
方法中的阻塞,请将ThreadPoolExecutor()
的创建移动到__init__()
,并只调用不在那里阻塞的executor.submit()
。