From patchwork Mon Mar 23 14:22:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 3262 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3237162BE3 for ; Mon, 23 Mar 2020 15:22:25 +0100 (CET) Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C69EEA31 for ; Mon, 23 Mar 2020 15:22:24 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1584973344; bh=USHdb1T8Gag3w1vXyqq1i+XOI3qduUfmdx1fQpIY3nA=; h=From:To:Subject:Date:In-Reply-To:References:From; b=qMRWzQAkJW8NtydIOAL9nE123VcCqrVCrCPZBqfCf4Pnxblu2SUTctZlGeW4bOmL+ OWmmhpgL9RDy5Dib/obJCKgPiWxeJDnfVWoG1u6TmI7gq1h/kuoAecp8tVBoyH0M86 BJlcn5nqZVaPfsFxkXHauP07HasJpPCKhc7iDAiU= From: Laurent Pinchart 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 Subject: [libcamera-devel] [PATCH 19/21] qcam: viewfinder: Avoid memory copy when conversion isn't needed X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 23 Mar 2020 14:22:28 -0000 If the frame buffer format is identical to the display format, the viewfinder still invokes the converter to perform what is essentially a slow memcpy(). Make is possible to skip that operation by creating a QImage referencing the buffer memory instead. A reference to the frame buffer is kept internally, and released when the next buffer is queued, pushing the current one out. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- src/qcam/viewfinder.cpp | 59 +++++++++++++++++++++++++++++------------ src/qcam/viewfinder.h | 1 + 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/qcam/viewfinder.cpp b/src/qcam/viewfinder.cpp index 31b358da47dc..4c35659e24aa 100644 --- a/src/qcam/viewfinder.cpp +++ b/src/qcam/viewfinder.cpp @@ -7,6 +7,8 @@ #include "viewfinder.h" +#include + #include #include #include @@ -16,7 +18,7 @@ #include "format_converter.h" ViewFinder::ViewFinder(QWidget *parent) - : QWidget(parent) + : QWidget(parent), buffer_(nullptr) { } @@ -27,17 +29,23 @@ ViewFinder::~ViewFinder() int ViewFinder::setFormat(const libcamera::PixelFormat &format, const QSize &size) { - int ret; + image_ = QImage(); + + /* + * If format conversion is needed, configure the converter and allocate + * the destination image. + */ + if (format != DRM_FORMAT_ARGB8888) { + int ret = converter_.configure(format, size); + if (ret < 0) + return ret; - ret = converter_.configure(format, size); - if (ret < 0) - return ret; + image_ = QImage(size, QImage::Format_RGB32); + } format_ = format; size_ = size; - image_ = QImage(size_, QImage::Format_RGB32); - updateGeometry(); return 0; } @@ -49,19 +57,36 @@ void ViewFinder::render(libcamera::FrameBuffer *buffer, MappedBuffer *map) return; } - QMutexLocker locker(&mutex_); - - /* - * \todo We're not supposed to block the pipeline handler thread - * for long, implement a better way to save images without - * impacting performances. - */ + unsigned char *memory = static_cast(map->memory); + size_t size = buffer->metadata().planes[0].bytesused; + + { + QMutexLocker locker(&mutex_); + + if (format_ == DRM_FORMAT_ARGB8888) { + /* + * If the frame format is identical to the display + * format, create a QImage that references the frame + * and store a reference to the frame buffer. The + * previously stored frame buffer, if any, will be + * released. + */ + image_ = QImage(memory, size_.width(), size_.height(), + size / size_.height(), QImage::Format_RGB32); + std::swap(buffer, buffer_); + } else { + /* + * Otherwise, convert the format and release the frame + * buffer immediately. + */ + converter_.convert(memory, size, &image_); + } + } - converter_.convert(static_cast(map->memory), - buffer->metadata().planes[0].bytesused, &image_); update(); - renderComplete(buffer); + if (buffer) + renderComplete(buffer); } QImage ViewFinder::getCurrentImage() diff --git a/src/qcam/viewfinder.h b/src/qcam/viewfinder.h index 54c0fa9dd7a0..b5153160f70e 100644 --- a/src/qcam/viewfinder.h +++ b/src/qcam/viewfinder.h @@ -52,6 +52,7 @@ private: libcamera::PixelFormat format_; QSize size_; + libcamera::FrameBuffer *buffer_; QImage image_; QMutex mutex_; /* Prevent concurrent access to image_ */ };