- Video jerks a bit .. is this because the play edge is too close to the block edge and it runs empty before new frames arrive? """ setValkkaLogLevel(loglevel_debug) def cb(mstime): print("mstime callback", mstime) # create OpenGLThread (for drawing video) and AVThread (for decoding) glthread = OpenGLThread(name="gl_thread") ctx = core.FrameFifoContext() avthread = core.AVThread( "avthread", glthread.getInput(), ctx) av_in_filter = avthread.getFrameFilter() avthread.startCall() avthread.decodingOnCall() # create an X-window window_id = glthread.createWindow() # map frames with slot 1 to that window glthread.newRenderGroup(window_id) context_id = glthread.newRenderContext(1, window_id, 0) valkkafs = ValkkaFS.loadFromDirectory(dirname="/home/sampsa/tmp/testvalkkafs") # manager = ValkkaFSManager(valkkafs, cb)
class MyGui(QtWidgets.QMainWindow): debug = False # debug=True def __init__(self, pardic, valkkafs, parent=None): super(MyGui, self).__init__() self.pardic = pardic self.valkkafs = valkkafs self.initVars() self.setupUi() if (self.debug): return self.openValkka() self.start_streams() def initVars(self): pass def setupUi(self): 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"] # self.rec_window = QtWidgets.QMainWindow(self) # self.rec_window = QtWidgets.QTabWidget(None) self.rec_window = MyTabWidget(None) self.rec_window.setGeometry(QtCore.QRect(50, 50, 800, 800)) self.rec_window.show() self.rec_video_tab = QtWidgets.QWidget(None) self.rec_video_lay = QtWidgets.QVBoxLayout(self.rec_video_tab) self.rec_calendar_tab = QtWidgets.QWidget(None) self.rec_calendar_lay = QtWidgets.QVBoxLayout(self.rec_calendar_tab) self.rec_window.addTab(self.rec_video_tab, "Video") self.rec_window.addTab(self.rec_calendar_tab, "Calendar") self.rec_video_area = QtWidgets.QWidget(self.rec_video_tab) self.rec_video_area.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) self.rec_video_area_lay = QtWidgets.QGridLayout(self.rec_video_area) self.rec_video_lay.addWidget(self.rec_video_area) # timeline self.timelinewidget = TimeLineWidget(datetime.date.today(), parent=self.rec_video_area) # self.timelinewidget.setLogLevel(logging.DEBUG) self.rec_video_lay.addWidget(self.timelinewidget) # buttons self.buttons = QtWidgets.QWidget(self.rec_video_area) self.buttons_lay = QtWidgets.QHBoxLayout(self.buttons) self.play_button = QtWidgets.QPushButton("play", self.buttons) self.stop_button = QtWidgets.QPushButton("stop", self.buttons) self.zoom_to_fs_button = QtWidgets.QPushButton("limits", self.buttons) self.buttons_lay.addWidget(self.play_button) self.buttons_lay.addWidget(self.stop_button) self.buttons_lay.addWidget(self.zoom_to_fs_button) self.rec_video_lay.addWidget(self.buttons) # calendar self.calendarwidget = CalendarWidget(datetime.date.today(), parent=self.rec_calendar_tab) self.rec_calendar_lay.addWidget(self.calendarwidget) def openValkka(self): self.valkkafsmanager = ValkkaFSManager( self.valkkafs, # read = False, # debugging # cache = False, # debugging # write = False # debugging ) self.playback_controller = PlaybackController( calendar_widget=self.calendarwidget, timeline_widget=self.timelinewidget, valkkafs_manager=self.valkkafsmanager, play_button=self.play_button, stop_button=self.stop_button, zoom_to_fs_button=self.zoom_to_fs_button) 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", # reserve stacks of YUV video frames for various resolutions n_720p=self.pardic["n_720p"], 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"]) 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 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) if use_live: chain_live = ValkkaFSLiveFilterchain( # decoding and branching the stream happens here valkkafsmanager=self.valkkafsmanager, id_rec=cs, # identifies the stream in ValkkaFS livethread=self.livethread, address=address, slot=cs, affinity=a, # verbose =True verbose=False, msreconnect=10000, # Reordering buffer time for Live555 packets in MILLIseconds # 0 means default reordering_mstime=0 # reordering_mstime =300 ) rec_slot = cs + 100 # live and rec slot numbers must be kept separated .. chain_rec = ValkkaFSFileFilterchain( # decoding and branching the stream happens here valkkafsmanager=self.valkkafsmanager, id_rec=cs, # identifies the stream in ValkkaFS slot=rec_slot, affinity=a, # verbose =True verbose=False) # send yuv to OpenGLThread if use_live: chain_live.connect_to_yuv("yuv_to_opengl_" + str(cs), self.openglthread.getInput()) chain_rec.connect_to_yuv("yuv_to_opengl_" + str(cs), self.openglthread.getInput()) # important .. otherwise chain will go out of context and get # garbage collected .. if use_live: self.chains.append(chain_live) self.chains.append(chain_rec) if ("no_qt" in self.pardic): # create our own x-windowses win_id = self.openglthread.createWindow(show=True) win_id_rec = 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(self.w) win_id = int(fr.winId()) fr_rec = TestWidget0(self.rec_video_area) win_id_rec = int(fr_rec.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(self.w, win_id, TestWidget0) fr = widget_pair.getWidget() self.widget_pairs.append(widget_pair) win_id_rec = self.openglthread.createWindow(show=False) widget_pair = WidgetPair(self.rec_video_area, win_id_rec, TestWidget0) fr_rec = widget_pair.getWidget() self.widget_pairs.append(widget_pair) # """ nrow = self.pardic["videos per row"] print(pre, "setupUi: layout index, address : ", cw // nrow, cw % nrow, address) self.lay.addWidget(fr, cw // nrow, cw % nrow) self.rec_video_area_lay.addWidget(fr_rec, cw // nrow, cw % nrow) self.videoframes.append(fr) self.videoframes.append(fr_rec) # present frames with slot number cs at window win_id # rec_slot = cs # debug print(pre, "setupUi: live:", cs, win_id) print(pre, "setupUi: rec :", rec_slot, win_id_rec) token = self.openglthread.connect(slot=cs, window_id=win_id) tokens.append(token) token = self.openglthread.connect(slot=rec_slot, window_id=win_id_rec) tokens.append(token) cw += 1 cs += 1 if use_live: chain_live.decodingOn( ) # tell the decoding thread to start its job chain_rec.decodingOn() a += 1 def closeValkka(self): self.livethread.close() self.valkkafsmanager.close() for chain in self.chains: chain.close() self.chains = [] self.widget_pairs = [] self.videoframes = [] self.openglthread.close() # time.sleep(5) def start_streams(self): pass def stop_streams(self): pass def closeEvent(self, e): print("\n", pre, "closeEvent!\n") self.stop_streams() self.closeValkka() self.rec_window.forceClose() # self.rec_window.close() e.accept()