Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Python 4-channel rtsp(rtmp) streaming program QThread slow problem
Forum Updated to NodeBB v4.3 + New Features

Python 4-channel rtsp(rtmp) streaming program QThread slow problem

Scheduled Pinned Locked Moved Unsolved Qt for Python
11 Posts 4 Posters 2.5k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • U UOUQT

    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.

    threadMod.py

    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()
    

    main.py

      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
    alt text

    jsulmJ Offline
    jsulmJ Offline
    jsulm
    Lifetime Qt Champion
    wrote on last edited by
    #2

    @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.

    https://forum.qt.io/topic/113070/qt-code-of-conduct

    JonBJ U 2 Replies Last reply
    1
    • jsulmJ jsulm

      @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.

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #3

      @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.

      jeremy_kJ U 2 Replies Last reply
      1
      • U UOUQT

        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.

        threadMod.py

        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()
        

        main.py

          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
        alt text

        jeremy_kJ Offline
        jeremy_kJ Offline
        jeremy_k
        wrote on last edited by
        #4

        @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.py

        
        class 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.

        main.py

          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.

        Asking a question about code? http://eel.is/iso-c++/testcase/

        1 Reply Last reply
        0
        • JonBJ JonB

          @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.

          jeremy_kJ Offline
          jeremy_kJ Offline
          jeremy_k
          wrote on last edited by
          #5

          @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.

          Asking a question about code? http://eel.is/iso-c++/testcase/

          1 Reply Last reply
          0
          • JonBJ JonB

            @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.

            U Offline
            U Offline
            UOUQT
            wrote on last edited by
            #6

            @JonB Note that in many cases (and virtually all cases where your "expensive operation" is a calculation implemented in Python), multiple threads will not actually run concurrently due to Python's Global Interpreter Lock (GIL).

            JonBJ 1 Reply Last reply
            0
            • U UOUQT

              @JonB Note that in many cases (and virtually all cases where your "expensive operation" is a calculation implemented in Python), multiple threads will not actually run concurrently due to Python's Global Interpreter Lock (GIL).

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #7

              @UOUQT
              Yes, this does not surprise me in Python, which is why I wrote

              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.

              Not sure why you are addressing this comment to me.

              U 1 Reply Last reply
              0
              • jsulmJ jsulm

                @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.

                U Offline
                U Offline
                UOUQT
                wrote on last edited by UOUQT
                #8
                This post is deleted!
                1 Reply Last reply
                0
                • JonBJ JonB

                  @UOUQT
                  Yes, this does not surprise me in Python, which is why I wrote

                  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.

                  Not sure why you are addressing this comment to me.

                  U Offline
                  U Offline
                  UOUQT
                  wrote on last edited by
                  #9

                  @JonB
                  I'm not familiar with python programming language...
                  How do I change it to single-threaded?

                  JonBJ 1 Reply Last reply
                  0
                  • U UOUQT

                    @JonB
                    I'm not familiar with python programming language...
                    How do I change it to single-threaded?

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by
                    #10

                    @UOUQT
                    Remove the threads, or reduce to only using one thread.

                    I did not say running single-threaded was desirable. I said that your comment about Python's GIL might reduce your intended multi-thread performance to single-thread.

                    U 1 Reply Last reply
                    0
                    • JonBJ JonB

                      @UOUQT
                      Remove the threads, or reduce to only using one thread.

                      I did not say running single-threaded was desirable. I said that your comment about Python's GIL might reduce your intended multi-thread performance to single-thread.

                      U Offline
                      U Offline
                      UOUQT
                      wrote on last edited by
                      #11

                      @JonB

                      When running 4 live streams with a single thread, the delay for each channel increased.
                      Probably because of cv2.read 4 times in one thread

                      I don't know if this is the correct coding.

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved