Example #1
0
class VideoShmemThread(QtCore.QThread):
    """A Thread that creates a Valkka shmem client, reads frames from it & fires them as qt signals

    Connect VideoShmemThread to SimpleVideoWidget.set_pixmap_slot
    """
    class Signals(QtCore.QObject):
        pixmap = Signal(object)
        image = Signal(object)
        exit = Signal()

    def __init__(self,
                 shmem_name: str,
                 shmem_n_buffer: int,
                 width: int,
                 height: int,
                 verbose=False):
        super().__init__()
        self.pre = "VideoShmemThread: "
        self.shmem_name = shmem_name
        self.shmem_n_buffer = shmem_n_buffer
        self.width = width
        self.height = height
        self.verbose = verbose

        self.loop = True
        self.signals = self.Signals()
        self.signals.exit.connect(self.exit_slot_)

    def run(self):
        self.client = ShmemRGBClient(
            name=self.shmem_name,
            n_ringbuffer=self.shmem_n_buffer,
            width=self.width,
            height=self.height,
            # client timeouts if nothing has been received in 1000 milliseconds
            mstimeout=1000,
            # mstimeout=100,
            verbose=False)
        while self.loop:
            """
            print("Idling")
            time.sleep(1)
            """
            # """
            # print("pullFrameThread>")
            index, meta = self.client.pullFrameThread(
                # index, meta = self.client.pullFrame(
            )  # releases Python GIL while waiting for a frame
            # print("<pullFrameThread")
            if (index is None):
                # print(self.pre, "VideoShmemThread: client timed out..")
                pass
            else:
                # print(self.pre, "VideoShmemThread: client index, w, h =", index, meta.width, meta.height)
                data = self.client.shmem_list[index]
                # print(data[0:10])
                self.img = data.copy().reshape((meta.height, meta.width, 3))
                # print(img[0:10])
                """WARNING
                - reshape does not necessarily create a copy of the data, but uses memview instead
                - imagine that a memview is passed donwstreams, where it eventually goes to another python thread
                - ..but in that pullFrameThread call above, we have released the GIL, so it migh happen
                that the cpp code is modifying the data while the downstream python thread is accessing it simultaneously and
                - ..crassssh
                """
                """DEBUG: test without actually sending the object into Qt infrastructure
                # which one of these two lines is the problem?
                pixmap = numpy2QPixmap(img)
                self.signals.pixmap.emit(pixmap)
                """
                # send numpy array into the signal/slot system
                # instead of QPixmap..?
                #"""
                self.signals.image.emit(self.img)
                #"""
                # could also just send the
                # index of the shmem array
                # & do everything at the canvas widget
                #
                # 1) 12h test without pixmap or signal
                # 1b) use here self.pixmap instead of pixmap, in order to keep the reference
                # https://wiki.python.org/moin/PyQt/Threading%2C_Signals_and_Slots
                # 2) 12h test sending the img
                # 3) 12h test sending the index only
                #
            # """

        print(self.pre, "exit")

    def exit_slot_(self):
        self.loop = False

    def stop(self):
        self.requestStop()
        self.waitStop()

    def requestStop(self):
        self.signals.exit.emit()

    def waitStop(self):
        self.wait()
Example #2
0
class VideoShmemThread(QtCore.QThread):
    """A Thread that creates a Valkka shmem client, reads frames from it & fires them as qt signals

    Connect VideoShmemThread to SimpleVideoWidget.set_pixmap_slot
    """
    class Signals(QtCore.QObject):
        pixmap = QtCore.Signal(object)
        exit = QtCore.Signal()

    def __init__(self,
                 shmem_name: str,
                 shmem_n_buffer: int,
                 width: int,
                 height: int,
                 verbose=False):
        super().__init__()
        self.pre = "VideoShmemThread: "
        self.shmem_name = shmem_name
        self.shmem_n_buffer = shmem_n_buffer
        self.width = width
        self.height = height
        self.verbose = verbose

        self.loop = True
        self.signals = self.Signals()
        self.signals.exit.connect(self.exit_slot_)

    def run(self):
        self.client = ShmemRGBClient(
            name=self.shmem_name,
            n_ringbuffer=self.shmem_n_buffer,
            width=self.width,
            height=self.height,
            # client timeouts if nothing has been received in 1000 milliseconds
            mstimeout=1000,
            verbose=False)
        while self.loop:
            """
            print("Idling")
            time.sleep(1)
            """
            #"""
            index, meta = self.client.pullFrameThread(
            )  # releases Python GIL while waiting for a frame
            if (index is None):
                # print(self.pre, "VideoShmemThread: client timed out..")
                pass
            else:
                # print(self.pre, "VideoShmemThread: client index, w, h =", index, meta.width, meta.height)
                data = self.client.shmem_list[index]
                img = data.reshape((meta.height, meta.width, 3))
                pixmap = numpy2QPixmap(img)
                self.signals.pixmap.emit(pixmap)
            # """

        print(self.pre, "exit")

    def exit_slot_(self):
        self.loop = False

    def stop(self):
        self.requestStop()
        self.waitStop()

    def requestStop(self):
        self.signals.exit.emit()

    def waitStop(self):
        self.wait()