Python 4-channel rtsp(rtmp) streaming program QThread slow problem
-
It is a 4 channel rtsp(rtmp) streaming program.
When running with QThread, if you stream 4 at the same time, the speed of the video will slow down and CPU usage will be 100%. I know it's a GIL problem
1~3 channel is no problem, but only when 4 channel is slow.
So I want to change to multiprocessing, but I don't know python properly
Can you change it to multiprocessing?I want to speed up a 4 channel cctv program.
from PyQt5.QtCore import QThread, pyqtSignal, Qt from PyQt5.QtGui import QImage import cv2 class StreamingThread(QThread): changePixmap = pyqtSignal(QImage) def __init__(self): super(StreamingThread, self).__init__() self.running = True self.camUrl = None self.Qsize = None self.cap = None def setRtsp(self, camUrl): self.camUrl = camUrl def setSize(self, Qsize): self.Qsize = Qsize def run(self): try: self.cap = cv2.VideoCapture(self.camUrl) if self.cap.isOpened(): while self.running: success, frame = self.cap.read() if success: rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w, ch = rgbImage.shape bytesPerLine = ch * w convertToQtFormat = QImage(rgbImage.data, w, h, bytesPerLine, QImage.Format_RGB888) p = convertToQtFormat.scaled(self.Qsize, Qt.KeepAspectRatio) self.changePixmap.emit(p) else: print("RTSP(RTMP) Video Streaming Fail") self.stop() except Exception as e: print(e) self.stop() def stop(self): if self.running: self.running = False print("Streaming Stop") self.quit()
def setChannel1(self): # Index 0: No Channel if self.chComboBox1.currentIndex() == 0: self.mStreamingThread1.terminate() sched = BackgroundScheduler() sched.add_job(self.clearChannel, 'date', run_date=datetime.datetime.now() + datetime.timedelta(seconds=1), args=[self.cctvStreaming1]) sched.start() else: ip, url, channel, boxId = self.findUrl(self.chComboBox1) if url != '' and channel != '': self.mStreamingThread1.terminate() self.mStreamingThread1.wait(1) self.mStreamingThread1.setRtsp(url) self.mStreamingThread1.setSize(self.cctvStreaming1.size()) self.mStreamingThread1.changePixmap.connect(self.setImage1) self.mStreamingThread1.start() self.show() logger.info("Channel1 Streaming Success") def setChannel2(self): # Index 0: No Channel if self.chComboBox2.currentIndex() == 0: self.mStreamingThread2.terminate() sched = BackgroundScheduler() sched.add_job(self.clearChannel, 'date', run_date=datetime.datetime.now() + datetime.timedelta(seconds=1), args=[self.cctvStreaming2]) sched.start() else: ip, url, channel, boxId = self.findUrl(self.chComboBox2) if url != '' and channel != '': self.mStreamingThread2.terminate() self.mStreamingThread2.wait(1) self.mStreamingThread2.setRtsp(url) self.mStreamingThread2.setSize(self.cctvStreaming2.size()) self.mStreamingThread2.changePixmap.connect(self.setImage2) self.mStreamingThread2.start() self.show() logger.info("Channel2 Streaming Success") @pyqtSlot(QImage) def setImage1(self, image): self.cctvStreaming1.setPixmap(QPixmap.fromImage(image)) @pyqtSlot(QImage) def setImage2(self, image): self.cctvStreaming2.setPixmap(QPixmap.fromImage(image))
Program Image
-
@UOUQT said in Python 4-channel rtsp(rtmp) streaming program QThread slow problem:
So I want to change to multiprocessing, but I don't know python properly
Why do you think multi processing will be faster than multi threading?
If you want to check multi processing then change your code to only use one thread and then start your Python app 4 times. -
@jsulm said in Python 4-channel rtsp(rtmp) streaming program QThread slow problem:
Why do you think multi processing will be faster than multi threading?
I have no idea whether it is a better approach, but if the OP is right about " I know it's a GIL problem" that could mean the the multi-threaded approach could effectively devolve to single-threaded in Python.
@UOUQT
If you want to try a multi-process approach from Qt you can use QProcess, or you can use Python's own process-spawning library. It might be better/the same/worse....1~3 channel is no problem, but only when 4 channel is slow.
Just a thought: do you have a quad-core processor? Maybe you won't be able to run a 4th thread/process simultaneously.
-
@UOUQT said in Python 4-channel rtsp(rtmp) streaming program QThread slow problem:
It is a 4 channel rtsp(rtmp) streaming program.
When running with QThread, if you stream 4 at the same time, the speed of the video will slow down and CPU usage will be 100%. I know it's a GIL problem
[...]
threadMod.pyclass StreamingThread(QThread): def run(self): try: self.cap = cv2.VideoCapture(self.camUrl) if self.cap.isOpened(): while self.running: success, frame = self.cap.read()
Is VideoCapture.read() blocking while waiting for the next thread? If not, have you looked at how much processing time each channel is consuming, to verify that it isn't possible to process multiple channels in a single thread?
The OpenCV documentation mentions using grab() and retrieve() instead to handle multiple cameras with tightly synchronized frames.
def setChannel1(self):
setChannel1 and setChannel2 are nearly identical. For the sanity of readers, if not yourself, merge them and use a parameter to select which channel to control. The same goes for the setImage1 and 2.
-
@JonB said in [Python 4-channel rtsp(rtmp) streaming program QThread slow problem]
@UOUQT
If you want to try a multi-process approach from Qt you can use QProcess, or you can use Python's own process-spawning library. It might be better/the same/worse....multiprocessing is a python package that uses child processes to emulate python threads while escaping the cpython global lock. I haven't done anything significant with it, but presumably this results in side effects that are visible to user code.
-
@UOUQT
Yes, this does not surprise me in Python, which is why I wrotebut if the OP is right about " I know it's a GIL problem" that could mean the the multi-threaded approach could effectively devolve to single-threaded in Python.
Not sure why you are addressing this comment to me.