def c__activate(self,
                    n_buffer: int = None,
                    image_dimensions: tuple = None,
                    shmem_name: str = None):

        # if not defined, use default values
        # if n_buffer is None: n_buffer = self.n_buffer
        # if image_dimensions is None: image_dimensions = self.image_dimensions
        # if shmem_name is None: shmem_name = self.shmem_name

        self.logger.debug("c__activate")
        self.listening = True
        # self.image_dimensions = image_dimensions
        self.client = ShmemRGBClient(
            name=shmem_name,
            n_ringbuffer=n_buffer,  # size of ring buffer
            width=image_dimensions[0],
            height=image_dimensions[1],
            # client timeouts if nothing has been received in 1000 milliseconds
            mstimeout=int(self.timeout * 1000),
            verbose=self.shmem_verbose)

        self.shmem_name = shmem_name
        self.n_buffer = n_buffer
        self.image_dimensions = image_dimensions

        self.postActivate_()
Exemple #2
0
    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")
Exemple #3
0
    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 preRun_(self):
     """Create the shared memory client after fork
 """
     super().preRun_()
     self.client = ShmemRGBClient(
         name=self.shmem_name,
         n_ringbuffer=self.n_buffer,  # size of ring buffer
         width=self.image_dimensions[0],
         height=self.image_dimensions[1],
         mstimeout=
         1000,  # client timeouts if nothing has been received in 1000 milliseconds
         verbose=False)
 def create_client_(self):
     self.client = ShmemRGBClient(
         name=self.shmem_name,
         n_ringbuffer=self.n_buffer,  # size of ring buffer
         width=self.image_dimensions[0],
         height=self.image_dimensions[1],
         # client timeouts if nothing has been received in 1000 milliseconds
         mstimeout=1000,
         verbose=False)
     self.postCreateClient_()
    def c__registerClient(self,
                          n_buffer: int = None,
                          image_dimensions: tuple = None,
                          shmem_name: str = None,
                          ipc_index: int = None):
        """Shared mem info is given.  Now we can create the shmem client

        There can be several shmem clients
        """
        self.logger.debug("c__registerClient")

        event_fd, pipe = singleton.ipc.get2(ipc_index)
        singleton.ipc.wait(
            ipc_index)  # wait till the shmem server has been created
        # this flag is controlled by QShmemClientProcess.c__setMasterProcess
        singleton.ipc.clear(ipc_index)
        shmem_client = ShmemRGBClient(
            name=shmem_name,
            n_ringbuffer=n_buffer,  # size of ring buffer
            width=image_dimensions[0],
            height=image_dimensions[1],
            # client timeouts if nothing has been received in 1000 milliseconds
            mstimeout=1000,
            verbose=False)
        shmem_client.useEventFd(event_fd)

        fd = event_fd.getFd()

        client = self.Client(fd=fd, pipe=pipe, shmem_client=shmem_client)

        self.clients[ipc_index] = client
        self.clients_by_fd[fd] = client
        self.logger.debug("c__registerClient: fd=%s", fd)
        self.rlis.append(fd)

        if len(self.clients) == 1:
            self.logger.debug("c__registerClient: first client registered")
            self.firstClientRegistered_()

        self.logger.debug("c__registerClient: number of clients is %s",
                          len(self.clients))
 def create_client_(self):
     print(
         "inside create_client of multiprocess \n shmem name is {} for process number "
         .format(self.shmem_name))
     self.client = ShmemRGBClient(
         name=self.shmem_name,
         n_ringbuffer=self.n_buffer,  # size of ring buffer
         width=self.image_dimensions[0],
         height=self.image_dimensions[1],
         # client timeouts if nothing has been received in 1000 milliseconds
         mstimeout=1000,
         verbose=False)
     self.postCreateClient_()
Exemple #8
0
 def activate_(self, n_buffer, image_dimensions, shmem_name):
     """Shared mem info is given.  Now we can create the shmem client
     """
     self.active = True
     self.image_dimensions = image_dimensions
     self.client = ShmemRGBClient(
         name=shmem_name,
         n_ringbuffer=n_buffer,  # size of ring buffer
         width=image_dimensions[0],
         height=image_dimensions[1],
         # client timeouts if nothing has been received in 1000 milliseconds
         mstimeout=1000,
         verbose=False)
     self.postActivate_()
Exemple #9
0
 def c__activateRGB24Client(self,
                            name=None,
                            n_ringbuffer=None,
                            width=None,
                            height=None,
                            ipc_index=None
                            ):
     """This will activate a shared memory client that reads RGB24 frames
     from shared memory libValkka c++ side (as defined in your filterchain)
     """
     print("c__activateRGB24Client called with", name, n_ringbuffer, width, height)
     client = ShmemRGBClient(
         name=name,
         n_ringbuffer=n_ringbuffer,
         width=width,
         height=height,
         mstimeout=self.mstimeout,
         verbose=False
     )
     eventfd = getEventFd(ipc_index)
     client.useEventFd(eventfd)  # do not forget!
     # let's get a posix file descriptor, i.e. a plain integer:
     fd = eventfd.getFd()
     self.client_by_fd[fd] = client
Exemple #10
0
The parameters used both in the server side (above) and on the client side (below) **must be exactly the same** and the client program should be started *after* the server program (and while the server is running).  Otherwise undefined behaviour will occur.  

The used shmem_name(s) should be same in both server and client, but different for another server/client pair.
<rtf>"""
from valkka.api2 import ShmemRGBClient

width  =1920//4
height =1080//4

shmem_name    ="lesson_4"      # This identifies posix shared memory - must be same as in the server side
shmem_buffers =10              # Size of the shmem ringbuffer

client=ShmemRGBClient(
  name          =shmem_name, 
  n_ringbuffer  =shmem_buffers,   
  width         =width,
  height        =height,
  mstimeout     =1000,        # client timeouts if nothing has been received in 1000 milliseconds
  verbose       =False
)

"""<rtf>
The *mstimeout* defines the semaphore timeout in milliseconds, i.e. the time when the client returns even if no frame was received:
<rtf>"""
while True:
  index, meta = client.pullFrame()
  # index, meta = client.pullFrameThread() # alternative method for multithreading
  if index is None:
    print("timeout")
  else:
    data = client.shmem_list[index][0:meta.size]
    print("data   : ",data[0:min(10,meta.size)])
class QShmemProcess(QMultiProcess):
    """A multiprocess with Qt signals and reading RGB images from shared memory.  Shared memory client is instantiated on demand (by calling activate)
    """
    timeout = 1.0

    class Signals(QtCore.QObject):
        pong = QtCore.Signal(object)  # demo outgoing signal

    # **** define here backend methods that correspond to incoming slots
    # ****

    def c__ping(self, message=""):
        print("c__ping:", message)
        self.send_out__(MessageObject("pong", lis=[1, 2, 3]))

    def c__activate(self,
                    n_buffer: int = None,
                    image_dimensions: tuple = None,
                    shmem_name: str = None):

        # if not defined, use default values
        # if n_buffer is None: n_buffer = self.n_buffer
        # if image_dimensions is None: image_dimensions = self.image_dimensions
        # if shmem_name is None: shmem_name = self.shmem_name

        self.logger.debug("c__activate")
        self.listening = True
        # self.image_dimensions = image_dimensions
        self.client = ShmemRGBClient(
            name=shmem_name,
            n_ringbuffer=n_buffer,  # size of ring buffer
            width=image_dimensions[0],
            height=image_dimensions[1],
            # client timeouts if nothing has been received in 1000 milliseconds
            mstimeout=int(self.timeout * 1000),
            verbose=self.shmem_verbose)

        self.shmem_name = shmem_name
        self.n_buffer = n_buffer
        self.image_dimensions = image_dimensions

        self.postActivate_()

    def c__deactivate(self):
        """Init shmem variables to None
        """
        self.logger.debug("c__deactivate")
        self.preDeactivate_()
        self.listening = False
        # self.image_dimensions = None
        self.client = None  # shared memory client created when activate is called

    # ****

    parameter_defs = {
        # "n_buffer"          : (int, 10),
        # "image_dimensions"  : (tuple, (1920//4, 1080//4)),
        # "image_dimensions"  : tuple,
        "shmem_verbose": (bool, False),
        # "shmem_name"        : None
    }

    def __init__(self, name="QShmemProcess", **kwargs):
        super().__init__(name)
        parameterInitCheck(QShmemProcess.parameter_defs, kwargs, self)
        """
        if self.shmem_name is None:
            self.shmem_name = "valkkashmemclient"+str(id(self))
        else:
            assert(isinstance(self.shmem_name, str))
        self.shmem_name_default = self.shmem_name
        """

    def preRun_(self):
        self.logger.debug("preRun_")
        self.c__deactivate()  # init variables

    def postRun_(self):
        """Clear shmem variables
        """
        self.c__deactivate()

    def run(self):
        self.preRun_()

        while self.loop:
            if self.listening:
                self.cycle_()
                self.readPipes__(timeout=0)  # timeout = 0 == just poll
            else:
                self.readPipes__(timeout=self.timeout)  # timeout of 1 sec

        self.postRun_()
        # indicate front end qt thread to exit
        self.back_pipe.send(None)
        self.logger.debug("bye!")

    def cycle_(self):
        """Receives frames from the shmem client and does something with them

        Typically launch qt signals
        """
        index, meta = self.client.pullFrame()
        if (index is None):
            self.logger.debug("Client timed out..")
            return

        self.logger.debug("Client index = %s", index)
        if meta.size < 1:
            return

        data = self.client.shmem_list[index][0:meta.size]
        img = data.reshape((meta.height, meta.width, 3))
        """ # WARNING: the x-server doesn't like this, i.e., we're creating a window from a separate python multiprocess, so the program will crash
        print(self.pre,"Visualizing with OpenCV")
        cv2.imshow("openCV_window",img)
        cv2.waitKey(1)
        """
        self.logger.debug("got frame %s", img.shape)
        # res=self.analyzer(img) # does something .. returns something ..

    def postActivate_(self):
        """Whatever you need to do after creating the shmem client.  Overwrite in child classes
        """
        pass

    def preDeactivate_(self):
        """Whatever you need to do prior to deactivating the shmem client.  Overwrite in child classes
        """
        pass

    # *** frontend ***

    def activate(self, **kwargs):
        # save values to front-end also:
        self.shmem_name = kwargs["shmem_name"]
        self.n_buffer = kwargs["n_buffer"]
        self.image_dimensions = kwargs["image_dimensions"]
        # this sets the values at back-end:
        self.sendMessageToBack(MessageObject("activate", **kwargs))

    def deactivate(self):
        self.sendMessageToBack(MessageObject("deactivate"))

    def ping(self, message=""):
        """Test call
        """
        self.sendMessageToBack(MessageObject("ping", message=message))
Exemple #12
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()
Exemple #13
0
class QValkkaShmemProcess(ValkkaProcess):
    """A multiprocess with Qt signals and reading RGB images from shared memory
    """

    incoming_signal_defs = {  # each key corresponds to a front- and backend methods
        "test_": {
            "test_int": int,
            "test_str": str
        },
        "stop_": [],
        "ping_": {
            "message": str
        }
    }

    outgoing_signal_defs = {"pong_o": {"message": str}}

    # For each outgoing signal, create a Qt signal with the same name.  The
    # frontend Qt thread will read processes communication pipe and emit these
    # signals.
    class Signals(QtCore.QObject):
        # pong_o  =QtCore.pyqtSignal(object)
        pong_o = QtCore.Signal(object)

    parameter_defs = {
        "n_buffer": (int, 10),
        "image_dimensions": tuple,
        "shmem_name": str,
        "verbose": (bool, False)
    }

    def __init__(self, name, affinity=-1, **kwargs):
        super().__init__(name, affinity, **kwargs)
        self.signals = self.Signals()
        parameterInitCheck(QValkkaShmemProcess.parameter_defs, kwargs, self)
        typeCheck(self.image_dimensions[0], int)
        typeCheck(self.image_dimensions[1], int)

    def report(self, *args):
        if (self.verbose):
            print(self.pre, *args)

    def preRun_(self):
        """Create the shared memory client immediately after fork
        """
        self.report("preRun_")
        super().preRun_()
        self.client = ShmemRGBClient(
            name=self.shmem_name,
            n_ringbuffer=self.n_buffer,  # size of ring buffer
            width=self.image_dimensions[0],
            height=self.image_dimensions[1],
            # client timeouts if nothing has been received in 1000 milliseconds
            mstimeout=1000,
            verbose=False)

    def cycle_(self):
        index, isize = self.client.pull()
        if (index is None):
            print(self.pre, "Client timed out..")
        else:
            print(self.pre, "Client index, size =", index, isize)
            data = self.client.shmem_list[index]
            img = data.reshape(
                (self.image_dimensions[1], self.image_dimensions[0], 3))
            """ # WARNING: the x-server doesn't like this, i.e., we're creating a window from a separate python multiprocess, so the program will crash
            print(self.pre,"Visualizing with OpenCV")
            cv2.imshow("openCV_window",img)
            cv2.waitKey(1)
            """
            print(self.pre, ">>>", data[0:10])

            # res=self.analyzer(img) # does something .. returns something ..

    # *** backend methods corresponding to incoming signals ***

    def stop_(self):
        self.running = False

    def test_(self, test_int=0, test_str="nada"):
        print(self.pre, "test_ signal received with", test_int, test_str)

    def ping_(self, message="nada"):
        print(self.pre, "At backend: ping_ received", message,
              "sending it back to front")
        self.sendSignal_(name="pong_o", message=message)

    # ** frontend methods launching incoming signals

    def stop(self):
        self.sendSignal(name="stop_")

    def test(self, **kwargs):
        dictionaryCheck(self.incoming_signal_defs["test_"], kwargs)
        kwargs["name"] = "test_"
        self.sendSignal(**kwargs)

    def ping(self, **kwargs):
        dictionaryCheck(self.incoming_signal_defs["ping_"], kwargs)
        kwargs["name"] = "ping_"
        self.sendSignal(**kwargs)

    # ** frontend methods handling received outgoing signals ***
    def pong_o(self, message="nada"):
        print(self.pre, "At frontend: pong got message", message)
        ns = Namespace()
        ns.message = message
        self.signals.pong_o.emit(ns)