[libcamera-devel,v3,26/30] py: cam: cam_qt: mmap the fbs only once
diff mbox series

Message ID 20220527144447.94891-27-tomi.valkeinen@ideasonboard.com
State Accepted
Headers show
Series
  • More misc Python patches
Related show

Commit Message

Tomi Valkeinen May 27, 2022, 2:44 p.m. UTC
Instead of doing an mmap and munmap every time a Request is complete,
mmap all the buffers once at the start of the program.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
 src/py/cam/cam_qt.py | 39 +++++++++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 14 deletions(-)

Comments

Laurent Pinchart May 30, 2022, 9:26 a.m. UTC | #1
Hi Tomi,

Thank you for the patch.

On Fri, May 27, 2022 at 05:44:43PM +0300, Tomi Valkeinen wrote:
> Instead of doing an mmap and munmap every time a Request is complete,
> mmap all the buffers once at the start of the program.
> 
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  src/py/cam/cam_qt.py | 39 +++++++++++++++++++++++++--------------
>  1 file changed, 25 insertions(+), 14 deletions(-)
> 
> diff --git a/src/py/cam/cam_qt.py b/src/py/cam/cam_qt.py
> index b6412bdf..c1723b44 100644
> --- a/src/py/cam/cam_qt.py
> +++ b/src/py/cam/cam_qt.py
> @@ -52,6 +52,16 @@ class QtRenderer:
>  
>          self.windows = windows
>  
> +        buf_mmap_map = {}
> +
> +        for ctx in self.contexts:
> +            for stream in ctx.streams:
> +                for buf in ctx.allocator.buffers(stream):
> +                    mfb = libcamera.utils.MappedFrameBuffer(buf).mmap()
> +                    buf_mmap_map[buf] = mfb
> +
> +        self.buf_mmap_map = buf_mmap_map
> +
>      def run(self):
>          camnotif = QtCore.QSocketNotifier(self.cm.event_fd, QtCore.QSocketNotifier.Read)
>          camnotif.activated.connect(lambda _: self.readcam())
> @@ -81,7 +91,9 @@ class QtRenderer:
>          for stream, fb in buffers.items():
>              wnd = next(wnd for wnd in self.windows if wnd.stream == stream)
>  
> -            wnd.handle_request(stream, fb)
> +            mfb = self.buf_mmap_map[fb]
> +
> +            wnd.handle_request(stream, mfb)
>  
>          self.state.request_processed(ctx, req)
>  
> @@ -145,26 +157,25 @@ class MainWindow(QtWidgets.QWidget):
>  
>          controlsLayout.addStretch()
>  
> -    def buf_to_qpixmap(self, stream, fb):
> -        with libcamera.utils.MappedFrameBuffer(fb) as mfb:
> -            cfg = stream.configuration
> +    def buf_to_qpixmap(self, stream, mfb):
> +        cfg = stream.configuration
>  
> -            if cfg.pixel_format == libcam.formats.MJPEG:
> -                pix = QtGui.QPixmap(cfg.size.width, cfg.size.height)
> -                pix.loadFromData(mfb.planes[0])
> -            else:
> -                rgb = mfb_to_rgb(mfb, cfg)
> -                if rgb is None:
> -                    raise Exception('Format not supported: ' + cfg.pixel_format)
> +        if cfg.pixel_format == libcam.formats.MJPEG:
> +            pix = QtGui.QPixmap(cfg.size.width, cfg.size.height)
> +            pix.loadFromData(mfb.planes[0])
> +        else:
> +            rgb = mfb_to_rgb(mfb, cfg)
> +            if rgb is None:
> +                raise Exception('Format not supported: ' + cfg.pixel_format)
>  
> -                pix = rgb_to_pix(rgb)
> +            pix = rgb_to_pix(rgb)
>  
>          return pix
>  
> -    def handle_request(self, stream, fb):
> +    def handle_request(self, stream, mfb):
>          ctx = self.ctx
>  
> -        pix = self.buf_to_qpixmap(stream, fb)
> +        pix = self.buf_to_qpixmap(stream, mfb)
>          self.label.setPixmap(pix)
>  
>          self.frameLabel.setText('Queued: {}\nDone: {}\nFps: {:.2f}'

Patch
diff mbox series

diff --git a/src/py/cam/cam_qt.py b/src/py/cam/cam_qt.py
index b6412bdf..c1723b44 100644
--- a/src/py/cam/cam_qt.py
+++ b/src/py/cam/cam_qt.py
@@ -52,6 +52,16 @@  class QtRenderer:
 
         self.windows = windows
 
+        buf_mmap_map = {}
+
+        for ctx in self.contexts:
+            for stream in ctx.streams:
+                for buf in ctx.allocator.buffers(stream):
+                    mfb = libcamera.utils.MappedFrameBuffer(buf).mmap()
+                    buf_mmap_map[buf] = mfb
+
+        self.buf_mmap_map = buf_mmap_map
+
     def run(self):
         camnotif = QtCore.QSocketNotifier(self.cm.event_fd, QtCore.QSocketNotifier.Read)
         camnotif.activated.connect(lambda _: self.readcam())
@@ -81,7 +91,9 @@  class QtRenderer:
         for stream, fb in buffers.items():
             wnd = next(wnd for wnd in self.windows if wnd.stream == stream)
 
-            wnd.handle_request(stream, fb)
+            mfb = self.buf_mmap_map[fb]
+
+            wnd.handle_request(stream, mfb)
 
         self.state.request_processed(ctx, req)
 
@@ -145,26 +157,25 @@  class MainWindow(QtWidgets.QWidget):
 
         controlsLayout.addStretch()
 
-    def buf_to_qpixmap(self, stream, fb):
-        with libcamera.utils.MappedFrameBuffer(fb) as mfb:
-            cfg = stream.configuration
+    def buf_to_qpixmap(self, stream, mfb):
+        cfg = stream.configuration
 
-            if cfg.pixel_format == libcam.formats.MJPEG:
-                pix = QtGui.QPixmap(cfg.size.width, cfg.size.height)
-                pix.loadFromData(mfb.planes[0])
-            else:
-                rgb = mfb_to_rgb(mfb, cfg)
-                if rgb is None:
-                    raise Exception('Format not supported: ' + cfg.pixel_format)
+        if cfg.pixel_format == libcam.formats.MJPEG:
+            pix = QtGui.QPixmap(cfg.size.width, cfg.size.height)
+            pix.loadFromData(mfb.planes[0])
+        else:
+            rgb = mfb_to_rgb(mfb, cfg)
+            if rgb is None:
+                raise Exception('Format not supported: ' + cfg.pixel_format)
 
-                pix = rgb_to_pix(rgb)
+            pix = rgb_to_pix(rgb)
 
         return pix
 
-    def handle_request(self, stream, fb):
+    def handle_request(self, stream, mfb):
         ctx = self.ctx
 
-        pix = self.buf_to_qpixmap(stream, fb)
+        pix = self.buf_to_qpixmap(stream, mfb)
         self.label.setPixmap(pix)
 
         self.frameLabel.setText('Queued: {}\nDone: {}\nFps: {:.2f}'