class MyGui(QtWidgets.QMainWindow): debug = False # debug=True def __init__(self, pardic, parent=None): super(MyGui, self).__init__() # print(pre,"Qapp=",QtCore.QCoreApplication.instance()) self.pardic = pardic self.initVars() self.setupUi() if (self.debug): return self.openValkka() self.start_streams() def initVars(self): pass def setupUi(self): self.desktop_handler = DesktopHandler() print(self.desktop_handler) self.setGeometry(QtCore.QRect(100, 100, 800, 800)) self.w = QtWidgets.QWidget(self) self.setCentralWidget(self.w) self.lay = QtWidgets.QGridLayout(self.w) self.videoframes = [] self.widget_pairs = [] self.addresses = self.pardic["cams"] def openValkka(self): self.livethread = LiveThread( # starts live stream services (using live555) name="live_thread", # verbose=True, verbose=False, affinity=self.pardic["live affinity"]) self.gpu_handler = GPUHandler(self.pardic) self.chains = [] a = self.pardic["dec affinity start"] cw = 0 # widget / window index cs = 1 # slot / stream count ntotal = len(self.addresses) * self.pardic["replicate"] nrow = self.pardic["videos per row"] ncol = max((ntotal // self.pardic["videos per row"]) + 1, 2) for address in self.addresses: # now livethread and openglthread are running if (a > self.pardic["dec affinity stop"]): a = self.pardic["dec affinity start"] print(pre, "openValkka: setting decoder thread on processor", a) chain = OpenFilterchain( # decoding and branching the stream happens here livethread=self.livethread, address=address, slot=cs, affinity=a, # verbose =True verbose=False, msreconnect=10000, # flush_when_full =True flush_when_full=False, # time_correction =TimeCorrectionType_dummy, # Timestamp correction type: TimeCorrectionType_none, TimeCorrectionType_dummy, or TimeCorrectionType_smart (default) time_correction=TimeCorrectionType_smart, recv_buffer_size= 0, # Operating system socket ringbuffer size in bytes # 0 means default # recv_buffer_size =1024*800, # 800 KB reordering_mstime= 0 # Reordering buffer time for Live555 packets in MILLIseconds # 0 means default # reordering_mstime =300 ) # send stream from all OpenFilterchain to all GPUs for glthread in self.gpu_handler.openglthreads: chain.connect(glthread.name, glthread.getInput( )) # OpenGLThread.getInput() returns the input FrameFilter self.chains.append( chain ) # important .. otherwise chain will go out of context and get garbage collected .. for cc in range(0, self.pardic["replicate"]): print(pre, "setupUi: layout index, address : ", cw // nrow, cw % nrow, address) # self.lay.addWidget(fr,cw//nrow,cw%nrow) # floating windows instead container = VideoContainer(cs, self.gpu_handler) container.getWidget().setGeometry( self.desktop_handler.getGeometry(nrow, ncol, cw % nrow, cw // nrow)) container.getWidget().show() self.videoframes.append(container) cw += 1 cs += 1 # TODO: crash when repeating the same slot number ..? chain.decodingOn() # tell the decoding thread to start its job a += 1 def closeValkka(self): self.livethread.close() for chain in self.chains: chain.close() self.chains = [] self.widget_pairs = [] self.videoframes = [] self.gpu_handler.close() def start_streams(self): pass def stop_streams(self): pass def closeEvent(self, e): print(pre, "closeEvent!") self.stop_streams() self.closeValkka() e.accept()
class MyGui(QtWidgets.QMainWindow): debug = False # debug=True def __init__(self, pardic, parent=None): super(MyGui, self).__init__() # print(pre,"Qapp=",QtCore.QCoreApplication.instance()) self.pardic = pardic self.initVars() self.setupUi() if (self.debug): return self.openValkka() self.start_streams() def initVars(self): pass def setupUi(self): self.desktop_handler = DesktopHandler() print(self.desktop_handler) self.setGeometry(QtCore.QRect(100, 100, 800, 800)) self.w = QtWidgets.QWidget(self) self.setCentralWidget(self.w) self.lay = QtWidgets.QGridLayout(self.w) self.videoframes = [] self.widget_pairs = [] self.addresses = self.pardic["cams"] def openValkka(self): self.livethread = LiveThread( # starts live stream services (using live555) name="live_thread", # verbose=True, verbose=False, affinity=self.pardic["live affinity"]) self.openglthread = OpenGLThread( # starts frame presenting services name="mythread", n_720p=self.pardic[ "n_720p"], # reserve stacks of YUV video frames for various resolutions n_1080p=self.pardic["n_1080p"], n_1440p=self.pardic["n_1440p"], n_4K=self.pardic["n_4K"], # naudio =self.pardic["naudio"], # obsolete # verbose =True, verbose=False, msbuftime=self.pardic["msbuftime"], affinity=self.pardic["gl affinity"], x_connection=":0.0" # x_connection =":0.1" # works .. video appears on the other xscreen ) """ # this results in a segfault print("> starting second OpenGLThread") # testing: start another OpenGLThread self.openglthread2=OpenGLThread( # starts frame presenting services name ="mythread2", n_720p =self.pardic["n_720p"], # reserve stacks of YUV video frames for various resolutions n_1080p =self.pardic["n_1080p"], n_1440p =self.pardic["n_1440p"], n_4K =self.pardic["n_4K"], # naudio =self.pardic["naudio"], # obsolete # verbose =True, verbose =False, msbuftime=self.pardic["msbuftime"], affinity=self.pardic["gl affinity"], x_connection =":0.1" # works .. video appears on the other xscreen ) print("> second OpenGLThread started") """ if (self.openglthread.hadVsync()): w = QtWidgets.QMessageBox.warning( self, "VBLANK WARNING", "Syncing to vertical refresh enabled\n THIS WILL DESTROY YOUR FRAMERATE\n Disable it with 'export vblank_mode=0' for nvidia proprietary drivers, use 'export __GL_SYNC_TO_VBLANK=0'" ) tokens = [] self.chains = [] a = self.pardic["dec affinity start"] cw = 0 # widget / window index cs = 1 # slot / stream count ntotal = len(self.addresses) * self.pardic["replicate"] nrow = self.pardic["videos per row"] ncol = max((ntotal // self.pardic["videos per row"]) + 1, 2) for address in self.addresses: # now livethread and openglthread are running if (a > self.pardic["dec affinity stop"]): a = self.pardic["dec affinity start"] print(pre, "openValkka: setting decoder thread on processor", a) chain = BasicFilterchain( # decoding and branching the stream happens here livethread=self.livethread, openglthread=self.openglthread, address=address, slot=cs, affinity=a, # verbose =True verbose=False, msreconnect=10000, # flush_when_full =True flush_when_full=False, # time_correction =TimeCorrectionType_dummy, # Timestamp correction type: TimeCorrectionType_none, TimeCorrectionType_dummy, or TimeCorrectionType_smart (default) time_correction=TimeCorrectionType_smart, recv_buffer_size= 0, # Operating system socket ringbuffer size in bytes # 0 means default # recv_buffer_size =1024*800, # 800 KB reordering_mstime= 0 # Reordering buffer time for Live555 packets in MILLIseconds # 0 means default # reordering_mstime =300 ) self.chains.append( chain ) # important .. otherwise chain will go out of context and get garbage collected .. for cc in range(0, self.pardic["replicate"]): if ("no_qt" in self.pardic): # create our own x-windowses win_id = self.openglthread.createWindow(show=True) else: # *** Choose one of the following sections *** # (1) Let Valkka create the windows/widget # use this: we get a window with correct parametrization # win_id =self.openglthread.createWindow(show=False) # fr =getForeignWidget(self.w, win_id) if (valkka_xwin == False): # (2) Let Qt create the widget fr = TestWidget0(None) win_id = int(fr.winId()) else: # """ # (3) Again, let Valkka create the window, but put on top a translucent widget (that catches mouse gestures) win_id = self.openglthread.createWindow(show=False) widget_pair = WidgetPair(None, win_id, TestWidget0) fr = widget_pair.getWidget() self.widget_pairs.append(widget_pair) # """ print(pre, "setupUi: layout index, address : ", cw // nrow, cw % nrow, address) # self.lay.addWidget(fr,cw//nrow,cw%nrow) # floating windows instead container = VideoContainer(None, fr, n=0) container.getWidget().setGeometry( self.desktop_handler.getGeometry( nrow, ncol, cw % nrow, cw // nrow)) container.getWidget().show() self.videoframes.append(container) token = self.openglthread.connect( slot=cs, window_id=win_id ) # present frames with slot number cs at window win_id tokens.append(token) cw += 1 cs += 1 # TODO: crash when repeating the same slot number ..? chain.decodingOn() # tell the decoding thread to start its job a += 1 def closeValkka(self): self.livethread.close() for chain in self.chains: chain.close() self.chains = [] self.widget_pairs = [] self.videoframes = [] self.openglthread.close() def start_streams(self): pass def stop_streams(self): pass def closeEvent(self, e): print(pre, "closeEvent!") self.stop_streams() self.closeValkka() e.accept()