{"id":3262,"url":"https://patchwork.libcamera.org/api/patches/3262/?format=json","web_url":"https://patchwork.libcamera.org/patch/3262/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20200323142205.28342-20-laurent.pinchart@ideasonboard.com>","date":"2020-03-23T14:22:03","name":"[libcamera-devel,19/21] qcam: viewfinder: Avoid memory copy when conversion isn't needed","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"38d01867a31fd0711cacd3749f8ec8f106fa2c4d","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/?format=json","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/3262/mbox/","series":[{"id":760,"url":"https://patchwork.libcamera.org/api/series/760/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=760","date":"2020-03-23T14:21:44","name":"qcam: Bypass format conversion when not required","version":1,"mbox":"https://patchwork.libcamera.org/series/760/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/3262/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/3262/checks/","tags":{},"headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 3237162BE3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 23 Mar 2020 15:22:25 +0100 (CET)","from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id C69EEA31\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 23 Mar 2020 15:22:24 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1584973344;\n\tbh=USHdb1T8Gag3w1vXyqq1i+XOI3qduUfmdx1fQpIY3nA=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=qMRWzQAkJW8NtydIOAL9nE123VcCqrVCrCPZBqfCf4Pnxblu2SUTctZlGeW4bOmL+\n\tOWmmhpgL9RDy5Dib/obJCKgPiWxeJDnfVWoG1u6TmI7gq1h/kuoAecp8tVBoyH0M86\n\tBJlcn5nqZVaPfsFxkXHauP07HasJpPCKhc7iDAiU=","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"libcamera-devel@lists.libcamera.org","Date":"Mon, 23 Mar 2020 16:22:03 +0200","Message-Id":"<20200323142205.28342-20-laurent.pinchart@ideasonboard.com>","X-Mailer":"git-send-email 2.24.1","In-Reply-To":"<20200323142205.28342-1-laurent.pinchart@ideasonboard.com>","References":"<20200323142205.28342-1-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","Subject":"[libcamera-devel] [PATCH 19/21] qcam: viewfinder: Avoid memory copy\n\twhen conversion isn't needed","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Mon, 23 Mar 2020 14:22:28 -0000"},"content":"If the frame buffer format is identical to the display format, the\nviewfinder still invokes the converter to perform what is essentially a\nslow memcpy(). Make is possible to skip that operation by creating a\nQImage referencing the buffer memory instead. A reference to the frame\nbuffer is kept internally, and released when the next buffer is queued,\npushing the current one out.\n\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n src/qcam/viewfinder.cpp | 59 +++++++++++++++++++++++++++++------------\n src/qcam/viewfinder.h   |  1 +\n 2 files changed, 43 insertions(+), 17 deletions(-)","diff":"diff --git a/src/qcam/viewfinder.cpp b/src/qcam/viewfinder.cpp\nindex 31b358da47dc..4c35659e24aa 100644\n--- a/src/qcam/viewfinder.cpp\n+++ b/src/qcam/viewfinder.cpp\n@@ -7,6 +7,8 @@\n \n #include \"viewfinder.h\"\n \n+#include <utility>\n+\n #include <QImage>\n #include <QImageWriter>\n #include <QMutexLocker>\n@@ -16,7 +18,7 @@\n #include \"format_converter.h\"\n \n ViewFinder::ViewFinder(QWidget *parent)\n-\t: QWidget(parent)\n+\t: QWidget(parent), buffer_(nullptr)\n {\n }\n \n@@ -27,17 +29,23 @@ ViewFinder::~ViewFinder()\n int ViewFinder::setFormat(const libcamera::PixelFormat &format,\n \t\t\t  const QSize &size)\n {\n-\tint ret;\n+\timage_ = QImage();\n+\n+\t/*\n+\t * If format conversion is needed, configure the converter and allocate\n+\t * the destination image.\n+\t */\n+\tif (format != DRM_FORMAT_ARGB8888) {\n+\t\tint ret = converter_.configure(format, size);\n+\t\tif (ret < 0)\n+\t\t\treturn ret;\n \n-\tret = converter_.configure(format, size);\n-\tif (ret < 0)\n-\t\treturn ret;\n+\t\timage_ = QImage(size, QImage::Format_RGB32);\n+\t}\n \n \tformat_ = format;\n \tsize_ = size;\n \n-\timage_ = QImage(size_, QImage::Format_RGB32);\n-\n \tupdateGeometry();\n \treturn 0;\n }\n@@ -49,19 +57,36 @@ void ViewFinder::render(libcamera::FrameBuffer *buffer, MappedBuffer *map)\n \t\treturn;\n \t}\n \n-\tQMutexLocker locker(&mutex_);\n-\n-\t/*\n-\t * \\todo We're not supposed to block the pipeline handler thread\n-\t * for long, implement a better way to save images without\n-\t * impacting performances.\n-\t */\n+\tunsigned char *memory = static_cast<unsigned char *>(map->memory);\n+\tsize_t size = buffer->metadata().planes[0].bytesused;\n+\n+\t{\n+\t\tQMutexLocker locker(&mutex_);\n+\n+\t\tif (format_ == DRM_FORMAT_ARGB8888) {\n+\t\t\t/*\n+\t\t\t * If the frame format is identical to the display\n+\t\t\t * format, create a QImage that references the frame\n+\t\t\t * and store a reference to the frame buffer. The\n+\t\t\t * previously stored frame buffer, if any, will be\n+\t\t\t * released.\n+\t\t\t */\n+\t\t\timage_ = QImage(memory, size_.width(), size_.height(),\n+\t\t\t\t\tsize / size_.height(), QImage::Format_RGB32);\n+\t\t\tstd::swap(buffer, buffer_);\n+\t\t} else {\n+\t\t\t/*\n+\t\t\t * Otherwise, convert the format and release the frame\n+\t\t\t * buffer immediately.\n+\t\t\t */\n+\t\t\tconverter_.convert(memory, size, &image_);\n+\t\t}\n+\t}\n \n-\tconverter_.convert(static_cast<unsigned char *>(map->memory),\n-\t\t\t   buffer->metadata().planes[0].bytesused, &image_);\n \tupdate();\n \n-\trenderComplete(buffer);\n+\tif (buffer)\n+\t\trenderComplete(buffer);\n }\n \n QImage ViewFinder::getCurrentImage()\ndiff --git a/src/qcam/viewfinder.h b/src/qcam/viewfinder.h\nindex 54c0fa9dd7a0..b5153160f70e 100644\n--- a/src/qcam/viewfinder.h\n+++ b/src/qcam/viewfinder.h\n@@ -52,6 +52,7 @@ private:\n \tlibcamera::PixelFormat format_;\n \tQSize size_;\n \n+\tlibcamera::FrameBuffer *buffer_;\n \tQImage image_;\n \tQMutex mutex_; /* Prevent concurrent access to image_ */\n };\n","prefixes":["libcamera-devel","19/21"]}