You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

267 lines
8.3 KiB

import asyncio
import re
import time
from threading import Thread
# import cv2
import numpy as np
from PyQt5.QtCore import QObject, pyqtSignal, QTimer, pyqtSlot, QThread, pyqtProperty
# from PyQt5.QtGui import QImage
# from PyQt5 import QtGui
from . import vision_service
class VideoStreamer(QObject):
newImage = pyqtSignal(object, int, int)
newRawImage = pyqtSignal(object)
reconnectInitiated = pyqtSignal()
reconnect = pyqtSignal()
camChangeStart = pyqtSignal()
camChangeEnd = pyqtSignal(int)
isCamChangingChanged = pyqtSignal(bool)
camReconnected = pyqtSignal(int)
beginOpenVideoCamera = pyqtSignal(str)
def __init__(self, parent: QObject = None):
super(QObject, self).__init__(parent)
self.__is_changing_camera = False
self.__stopped = False
self.__grabbed = False
self.__is_reconnecting = False
self.__frame = np.array([])
self.__cap = None
self.__tmp_cap = None
self.__rtsp_link = ''
self.__tmp_rtsp_link = ''
self.ip = ''
self.tUpdate = None
self.reconnectTimer = None
self.t = None
@pyqtProperty(bool, notify=isCamChangingChanged)
def isChangingCamera(self):
return self.__is_changing_camera
@pyqtSlot()
def beginReconnect(self):
print('RECONNECTING')
self.stopVideoCamera()
self.__is_reconnecting = True
# QTimer.singleShot(5000, self.reconnectVideo)
t = Thread(target=self.reconnectVideo, args=())
t.daemon = True
t.start()
# @pyqtSlot()
def reconnectVideo(self):
rtsp_link = self.__tmp_rtsp_link
print(f'reconnecting to {rtsp_link}')
self.stopVideoCamera()
while True:
self.reconnect.emit()
cap = vision_service.vision_service(rtsp_link)
cap.start_framing()
time.sleep(5)
if cap.get_is_framing():
print('cam is online')
self.camChangeEnd.emit(True)
time.sleep(0.1)
self.__cap = None
fps = cap.get_fps()
if fps == 0:
if not cap.get_is_framing():
return False
else:
fps = 60
self.__stopped = True
self.tUpdate.stop()
self.reconnectTimer.stop()
self.__cap = cap
self.__rtsp_link = rtsp_link
self.t = Thread(target=self.update, args=())
self.t.daemon = True
self.camReconnected.emit(int(1000 // fps))
self.__stopped = False
if not self.t.is_alive():
self.t.start()
self.__is_reconnecting = False
return True
def update(self):
while True:
if self.__stopped is True:
print('self.__stopped is True:')
self.__frame = None
break
if not self.__cap:
print('not self.__cap')
time.sleep(0.1)
continue
if self.__cap.get_is_framing():
self.__frame = self.__cap.get_frame()
time.sleep(0.066)
else:
time.sleep(0.1)
if not self.__is_reconnecting:
print('not self.__is_reconnecting')
self.__is_reconnecting = True
self.reconnectInitiated.emit() # TODO send error to client
# if self.__frame is False:
# print('[Exiting] No more frames to read')
# self.__stopped = True
# break
# self.__cap.release()
@pyqtSlot()
def run(self) -> None:
print('starting QThread')
self.tUpdate = QTimer(self)
self.reconnectTimer = QTimer(self)
# self.tUpdate.moveToThread(self)
# self.reconnectTimer.moveToThread(self)
self.t = Thread(target=self.update, args=())
self.t.daemon = True # daemon threads run in background
self.tUpdate.timeout.connect(self.streamVideo)
self.reconnectTimer.timeout.connect(self.reconnectVideo)
self.reconnectInitiated.connect(self.beginReconnect)
self.camReconnected.connect(self.tUpdate.start)
self.beginOpenVideoCamera.connect(self.openVideoCamera)
# self.exec_()
@pyqtSlot()
def streamVideo(self):
pass
# if (self.__frame is not None) and self.__frame.size != 0:
# height, width, channel = self.__frame.shape
# bytesPerLine = 3 * width
# qImg = QImage(self.__frame.data, width, height, bytesPerLine, QImage.Format_BGR888)
# self.newRawImage.emit(self.__frame)
# self.newImage.emit(qImg, width, height)
def get_frame(self):
return self.__frame
@pyqtSlot(result=bool)
def connectCam(self):
print('CONNECTING CAM')
fps = self.__tmp_cap.get_fps()
print('NEW CAP FPS:', fps)
if fps == 0:
if not self.__tmp_cap.get_is_framing():
return False
else:
fps = 60
self.__stopped = True
self.tUpdate.stop()
self.reconnectTimer.stop()
self.__rtsp_link = self.__tmp_rtsp_link
self.__cap = self.__tmp_cap
self.ip = re.findall("(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", self.__rtsp_link)[0]
self.t = Thread(target=self.update, args=())
self.t.daemon = True
self.tUpdate.start(int(1000 // fps))
self.__stopped = False
if not self.t.is_alive():
self.t.start()
self.__is_changing_camera = False
self.isCamChangingChanged.emit(self.__is_changing_camera)
return True
@pyqtSlot(result=bool)
def checkCam(self):
print('CHECKING CAMERA')
if self.__tmp_cap.get_is_framing():
print('camera is framing')
self.stopVideoCamera()
self.camChangeEnd.emit(True)
QTimer.singleShot(100, self.connectCam)
return True
else:
print('camera is not framing')
self.camChangeEnd.emit(False)
self.__is_changing_camera = False
self.isCamChangingChanged.emit(self.__is_changing_camera)
return False
@pyqtSlot(str, result=bool)
def changeCamera(self, rtsp_link):
self.__is_changing_camera = True
self.isCamChangingChanged.emit(self.__is_changing_camera)
self.__tmp_rtsp_link = rtsp_link
self.__tmp_cap = vision_service.vision_service(rtsp_link)
self.__tmp_cap.start_framing()
QTimer.singleShot(5000, self.checkCam)
self.camChangeStart.emit()
return True
# except:
# print('cannot stop framing')
# return False
@pyqtProperty(str)
def rtspLink(self):
return self.__rtsp_link
@pyqtSlot(result=bool)
@pyqtSlot(str, result=bool)
def openVideoCamera(self, rtsp_link: str = None):
if self.__cap is None:
if rtsp_link is not None:
self.__tmp_rtsp_link = rtsp_link
print('rtsp_link:', self.__tmp_rtsp_link)
self.__tmp_cap = vision_service.vision_service(self.__tmp_rtsp_link)
self.__tmp_cap.start_framing()
QTimer.singleShot(5000, self.checkCam)
self.camChangeStart.emit()
return True
return False
@pyqtSlot()
def clearVideoCamera(self):
self.__cap = None
self.__rtsp_link = ''
print('clearVideoCamera finished')
@pyqtSlot(result=bool)
def stopVideoCamera(self):
self.__stopped = True
self.t = Thread(target=self.update, args=())
self.t.daemon = True
print('stopping video camera')
self.tUpdate.stop()
self.reconnectTimer.stop()
if not self.__is_reconnecting:
QTimer.singleShot(100, self.clearVideoCamera)
try:
if self.__cap:
self.__cap.stop_framing()
return True
except Exception as e:
print('cannot stop framing', e)
return False
def __del__(self):
# self.__cap.release()
try:
self.__cap.stop_framing()
except:
print('cannot stop framing')
self.tUpdate.stop()
self.__stopped = True