From patchwork Mon Sep 6 02:00:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13618 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id B96E8BDC71 for ; Mon, 6 Sep 2021 02:01:24 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E9E3460254; Mon, 6 Sep 2021 04:01:22 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="rN0/Kt+n"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 99B4E60254 for ; Mon, 6 Sep 2021 04:01:21 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 285258D7; Mon, 6 Sep 2021 04:01:21 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1630893681; bh=vBG0qyEef7amrs34aZAtJq889C71FrR0QxyyK4EGp8k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rN0/Kt+nohQCqIHoJ60o7UJ7GBjS+iduewajHcAk80aisj/E3oBn6Su+d9F4hrM+y Zb7G4RpCopTwnFyiTkj1R74dP67b7pc0v4FOqhDUo//Yp0xTqvdXDdwWLXi7cS1Fse gMl4Bw5aWiwVXnkcVmEuJ11AuAin3M/G6Te+UbIw= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 6 Sep 2021 05:00:34 +0300 Message-Id: <20210906020100.14430-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> References: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 01/27] libcamera: base: utils: Use size_t for index in utils::enumerate() 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The index generated by utils::enumerate() is an iteration counter, which should thus be positive. Use std::size_t instead of the different_type of the container. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Jean-Michel Hautbois Reviewed-by: Paul Elder Reviewed-by: Hirokazu Honda --- include/libcamera/base/utils.h | 4 ++-- test/utils.cpp | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h index 52301254c2eb..2b761436a99f 100644 --- a/include/libcamera/base/utils.h +++ b/include/libcamera/base/utils.h @@ -246,7 +246,7 @@ private: public: using difference_type = typename std::iterator_traits::difference_type; - using value_type = std::pair; + using value_type = std::pair; using pointer = value_type *; using reference = value_type &; using iterator_category = std::input_iterator_tag; @@ -275,7 +275,7 @@ public: private: Base current_; - difference_type pos_; + std::size_t pos_; }; template diff --git a/test/utils.cpp b/test/utils.cpp index d7f810e95e7a..d65467b5102c 100644 --- a/test/utils.cpp +++ b/test/utils.cpp @@ -77,8 +77,8 @@ protected: int testEnumerate() { - std::vector integers{ 1, 2, 3, 4, 5 }; - int i = 0; + std::vector integers{ 1, 2, 3, 4, 5 }; + unsigned int i = 0; for (auto [index, value] : utils::enumerate(integers)) { if (index != i || value != i + 1) { @@ -93,12 +93,12 @@ protected: ++i; } - if (integers != std::vector{ 0, 1, 2, 3, 4 }) { + if (integers != std::vector{ 0, 1, 2, 3, 4 }) { cerr << "Failed to modify container in enumerated range loop" << endl; return TestFail; } - Span span{ integers }; + Span span{ integers }; i = 0; for (auto [index, value] : utils::enumerate(span)) { @@ -112,7 +112,7 @@ protected: ++i; } - const int array[] = { 0, 2, 4, 6, 8 }; + const unsigned int array[] = { 0, 2, 4, 6, 8 }; i = 0; for (auto [index, value] : utils::enumerate(array)) { From patchwork Mon Sep 6 02:00:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13619 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 8678DC3242 for ; Mon, 6 Sep 2021 02:01:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4686669170; Mon, 6 Sep 2021 04:01:24 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ecAM9h2W"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4E2DD69168 for ; Mon, 6 Sep 2021 04:01:22 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id DFE9A317; Mon, 6 Sep 2021 04:01:21 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1630893682; bh=haQutqc6PwSxhveNNoMpj+9cb863eutSY7ibo5UM+Ck=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ecAM9h2W0PFpMicM38tH5i2hRq48tKAY63cypSv7m8T27HFoi+3eV+oXR7JCHARc0 8xG28A8udULxxBUi2XCz2rq29eDoFu2yOtyUWJ1XHxc4Zkpwswqz3TCUwTMTYZ3BPp CQ8MdJet6BcrEH3aHM+tMXqQZYlfIN1TnV9y7wd8= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 6 Sep 2021 05:00:36 +0300 Message-Id: <20210906020100.14430-4-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> References: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 03/27] libcamera: v4l2_videodevice: Drop toV4L2PixelFormat() 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The V4L2VideoDevice::toV4L2PixelFormat() function is incorrectly implemented, as it will pick a multi-planar format if the device supports the multi-planar API, even if only single-planar formats are supported. This currently works because the implementation calls V4L2PixelFormat::fromPixelFormat(), which ignores the multiplanar argument and always returns a single-planar format. Fixing this isn't trivial. As we don't need to support multi-planar V4L2 formats at this point, drop the function instead of pretending everything is fine, and call V4L2PixelFormat::fromPixelFormat() directly from pipeline handlers. As the single-planar case is the most common, set the multiplanar argument to false by default to avoid long lines. Signed-off-by: Laurent Pinchart Reviewed-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham Reviewed-by: Hirokazu Honda --- include/libcamera/internal/v4l2_pixelformat.h | 2 +- include/libcamera/internal/v4l2_videodevice.h | 2 -- src/libcamera/pipeline/ipu3/imgu.cpp | 2 +- .../pipeline/raspberrypi/raspberrypi.cpp | 8 ++++---- src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 6 +++--- src/libcamera/pipeline/simple/converter.cpp | 8 ++++---- src/libcamera/pipeline/simple/simple.cpp | 4 ++-- src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 6 +++--- src/libcamera/pipeline/vimc/vimc.cpp | 8 ++++---- src/libcamera/v4l2_videodevice.cpp | 17 ----------------- test/libtest/buffer_source.cpp | 3 +-- 11 files changed, 23 insertions(+), 43 deletions(-) diff --git a/include/libcamera/internal/v4l2_pixelformat.h b/include/libcamera/internal/v4l2_pixelformat.h index 9bfd81ad6651..560c5c53c0c3 100644 --- a/include/libcamera/internal/v4l2_pixelformat.h +++ b/include/libcamera/internal/v4l2_pixelformat.h @@ -38,7 +38,7 @@ public: PixelFormat toPixelFormat() const; static V4L2PixelFormat fromPixelFormat(const PixelFormat &pixelFormat, - bool multiplanar); + bool multiplanar = false); private: uint32_t fourcc_; diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h index 7a145f608a5b..087ad067e37e 100644 --- a/include/libcamera/internal/v4l2_videodevice.h +++ b/include/libcamera/internal/v4l2_videodevice.h @@ -212,8 +212,6 @@ public: static std::unique_ptr fromEntityName(const MediaDevice *media, const std::string &entity); - V4L2PixelFormat toV4L2PixelFormat(const PixelFormat &pixelFormat); - protected: std::string logPrefix() const override; diff --git a/src/libcamera/pipeline/ipu3/imgu.cpp b/src/libcamera/pipeline/ipu3/imgu.cpp index 317e482a1498..3e1ef645ec93 100644 --- a/src/libcamera/pipeline/ipu3/imgu.cpp +++ b/src/libcamera/pipeline/ipu3/imgu.cpp @@ -575,7 +575,7 @@ int ImgUDevice::configureVideoDevice(V4L2VideoDevice *dev, unsigned int pad, return 0; *outputFormat = {}; - outputFormat->fourcc = dev->toV4L2PixelFormat(formats::NV12); + outputFormat->fourcc = V4L2PixelFormat::fromPixelFormat(formats::NV12); outputFormat->size = cfg.size; outputFormat->planesCount = 2; diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index b2674ac02109..0bdfa7273ce0 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -440,14 +440,14 @@ CameraConfiguration::Status RPiCameraConfiguration::validate() V4L2VideoDevice::Formats fmts = dev->formats(); - if (fmts.find(V4L2PixelFormat::fromPixelFormat(cfgPixFmt, false)) == fmts.end()) { + if (fmts.find(V4L2PixelFormat::fromPixelFormat(cfgPixFmt)) == fmts.end()) { /* If we cannot find a native format, use a default one. */ cfgPixFmt = formats::NV12; status = Adjusted; } V4L2DeviceFormat format; - format.fourcc = dev->toV4L2PixelFormat(cfg.pixelFormat); + format.fourcc = V4L2PixelFormat::fromPixelFormat(cfg.pixelFormat); format.size = cfg.size; int ret = dev->tryFormat(&format); @@ -647,7 +647,7 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config) RPi::Stream *stream = i == maxIndex ? &data->isp_[Isp::Output0] : &data->isp_[Isp::Output1]; - V4L2PixelFormat fourcc = stream->dev()->toV4L2PixelFormat(cfg.pixelFormat); + V4L2PixelFormat fourcc = V4L2PixelFormat::fromPixelFormat(cfg.pixelFormat); format.size = cfg.size; format.fourcc = fourcc; @@ -688,7 +688,7 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config) maxSize = Size(320, 240); format = {}; format.size = maxSize; - format.fourcc = V4L2PixelFormat::fromPixelFormat(formats::YUV420, false); + format.fourcc = V4L2PixelFormat::fromPixelFormat(formats::YUV420); ret = data->isp_[Isp::Output0].dev()->setFormat(&format); if (ret) { LOG(RPI, Error) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp index 25f482eb8d8e..f8d471204d2e 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp @@ -80,7 +80,7 @@ CameraConfiguration::Status RkISP1Path::validate(StreamConfiguration *cfg) cfg->bufferCount = RKISP1_BUFFER_COUNT; V4L2DeviceFormat format; - format.fourcc = video_->toV4L2PixelFormat(cfg->pixelFormat); + format.fourcc = V4L2PixelFormat::fromPixelFormat(cfg->pixelFormat); format.size = cfg->size; int ret = video_->tryFormat(&format); @@ -146,7 +146,7 @@ int RkISP1Path::configure(const StreamConfiguration &config, const PixelFormatInfo &info = PixelFormatInfo::info(config.pixelFormat); V4L2DeviceFormat outputFormat; - outputFormat.fourcc = video_->toV4L2PixelFormat(config.pixelFormat); + outputFormat.fourcc = V4L2PixelFormat::fromPixelFormat(config.pixelFormat); outputFormat.size = config.size; outputFormat.planesCount = info.numPlanes(); @@ -155,7 +155,7 @@ int RkISP1Path::configure(const StreamConfiguration &config, return ret; if (outputFormat.size != config.size || - outputFormat.fourcc != video_->toV4L2PixelFormat(config.pixelFormat)) { + outputFormat.fourcc != V4L2PixelFormat::fromPixelFormat(config.pixelFormat)) { LOG(RkISP1, Error) << "Unable to configure capture in " << config.toString(); return -EINVAL; diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp index b5e34c4cd0c5..9cbc6ee30ce4 100644 --- a/src/libcamera/pipeline/simple/converter.cpp +++ b/src/libcamera/pipeline/simple/converter.cpp @@ -46,7 +46,7 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg, const StreamConfiguration &outputCfg) { V4L2PixelFormat videoFormat = - m2m_->output()->toV4L2PixelFormat(inputCfg.pixelFormat); + V4L2PixelFormat::fromPixelFormat(inputCfg.pixelFormat); V4L2DeviceFormat format; format.fourcc = videoFormat; @@ -71,7 +71,7 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg, } /* Set the pixel format and size on the output. */ - videoFormat = m2m_->capture()->toV4L2PixelFormat(outputCfg.pixelFormat); + videoFormat = V4L2PixelFormat::fromPixelFormat(outputCfg.pixelFormat); format = {}; format.fourcc = videoFormat; format.size = outputCfg.size; @@ -210,7 +210,7 @@ std::vector SimpleConverter::formats(PixelFormat input) * enumerate the conversion capabilities on its output (V4L2 capture). */ V4L2DeviceFormat v4l2Format; - v4l2Format.fourcc = m2m_->output()->toV4L2PixelFormat(input); + v4l2Format.fourcc = V4L2PixelFormat::fromPixelFormat(input); v4l2Format.size = { 1, 1 }; int ret = m2m_->output()->setFormat(&v4l2Format); @@ -281,7 +281,7 @@ SimpleConverter::strideAndFrameSize(const PixelFormat &pixelFormat, const Size &size) { V4L2DeviceFormat format; - format.fourcc = m2m_->capture()->toV4L2PixelFormat(pixelFormat); + format.fourcc = V4L2PixelFormat::fromPixelFormat(pixelFormat); format.size = size; int ret = m2m_->capture()->tryFormat(&format); diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index cadaf5d030ab..701fb4be0b71 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -826,7 +826,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() return Invalid; } else { V4L2DeviceFormat format; - format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat); + format.fourcc = V4L2PixelFormat::fromPixelFormat(cfg.pixelFormat); format.size = cfg.size; int ret = data_->video_->tryFormat(&format); @@ -915,7 +915,7 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) return ret; /* Configure the video node. */ - V4L2PixelFormat videoFormat = video->toV4L2PixelFormat(pipeConfig->captureFormat); + V4L2PixelFormat videoFormat = V4L2PixelFormat::fromPixelFormat(pipeConfig->captureFormat); V4L2DeviceFormat captureFormat; captureFormat.fourcc = videoFormat; diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index 973ecd5b835e..264f5370cf32 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -151,7 +151,7 @@ CameraConfiguration::Status UVCCameraConfiguration::validate() cfg.bufferCount = 4; V4L2DeviceFormat format; - format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat); + format.fourcc = V4L2PixelFormat::fromPixelFormat(cfg.pixelFormat); format.size = cfg.size; int ret = data_->video_->tryFormat(&format); @@ -207,7 +207,7 @@ int PipelineHandlerUVC::configure(Camera *camera, CameraConfiguration *config) int ret; V4L2DeviceFormat format; - format.fourcc = data->video_->toV4L2PixelFormat(cfg.pixelFormat); + format.fourcc = V4L2PixelFormat::fromPixelFormat(cfg.pixelFormat); format.size = cfg.size; ret = data->video_->setFormat(&format); @@ -215,7 +215,7 @@ int PipelineHandlerUVC::configure(Camera *camera, CameraConfiguration *config) return ret; if (format.size != cfg.size || - format.fourcc != data->video_->toV4L2PixelFormat(cfg.pixelFormat)) + format.fourcc != V4L2PixelFormat::fromPixelFormat(cfg.pixelFormat)) return -EINVAL; cfg.setStream(&data->stream_); diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp index baeb6a7e6fa6..e453091da4b2 100644 --- a/src/libcamera/pipeline/vimc/vimc.cpp +++ b/src/libcamera/pipeline/vimc/vimc.cpp @@ -170,7 +170,7 @@ CameraConfiguration::Status VimcCameraConfiguration::validate() cfg.bufferCount = 4; V4L2DeviceFormat format; - format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat); + format.fourcc = V4L2PixelFormat::fromPixelFormat(cfg.pixelFormat); format.size = cfg.size; int ret = data_->video_->tryFormat(&format); @@ -274,7 +274,7 @@ int PipelineHandlerVimc::configure(Camera *camera, CameraConfiguration *config) return ret; V4L2DeviceFormat format; - format.fourcc = data->video_->toV4L2PixelFormat(cfg.pixelFormat); + format.fourcc = V4L2PixelFormat::fromPixelFormat(cfg.pixelFormat); format.size = cfg.size; ret = data->video_->setFormat(&format); @@ -282,7 +282,7 @@ int PipelineHandlerVimc::configure(Camera *camera, CameraConfiguration *config) return ret; if (format.size != cfg.size || - format.fourcc != data->video_->toV4L2PixelFormat(cfg.pixelFormat)) + format.fourcc != V4L2PixelFormat::fromPixelFormat(cfg.pixelFormat)) return -EINVAL; /* @@ -597,7 +597,7 @@ int VimcCameraData::allocateMockIPABuffers() constexpr unsigned int kBufCount = 2; V4L2DeviceFormat format; - format.fourcc = video_->toV4L2PixelFormat(formats::BGR888); + format.fourcc = V4L2PixelFormat::fromPixelFormat(formats::BGR888); format.size = Size (160, 120); int ret = video_->setFormat(&format); diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index 4e1c2b7cef5e..84ccb97495f5 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -1687,23 +1687,6 @@ V4L2VideoDevice::fromEntityName(const MediaDevice *media, return std::make_unique(mediaEntity); } -/** - * \brief Convert \a PixelFormat to its corresponding V4L2 FourCC - * \param[in] pixelFormat The PixelFormat to convert - * - * For multiplanar formats, the V4L2 format variant (contiguous or - * non-contiguous planes) is selected automatically based on the capabilities - * of the video device. If the video device supports the V4L2 multiplanar API, - * non-contiguous formats are preferred. - * - * \return The V4L2_PIX_FMT_* pixel format code corresponding to \a pixelFormat - */ -V4L2PixelFormat V4L2VideoDevice::toV4L2PixelFormat(const PixelFormat &pixelFormat) -{ - return V4L2PixelFormat::fromPixelFormat(pixelFormat, - caps_.isMultiplanar()); -} - /** * \class V4L2M2MDevice * \brief Memory-to-Memory video device diff --git a/test/libtest/buffer_source.cpp b/test/libtest/buffer_source.cpp index 73563f2fc39d..64e7376ad575 100644 --- a/test/libtest/buffer_source.cpp +++ b/test/libtest/buffer_source.cpp @@ -70,8 +70,7 @@ int BufferSource::allocate(const StreamConfiguration &config) } format.size = config.size; - format.fourcc = V4L2PixelFormat::fromPixelFormat(config.pixelFormat, - false); + format.fourcc = V4L2PixelFormat::fromPixelFormat(config.pixelFormat); if (video->setFormat(&format)) { std::cout << "Failed to set format on output device" << std::endl; return TestFail; From patchwork Mon Sep 6 02:00:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13620 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id D1988C3244 for ; Mon, 6 Sep 2021 02:01:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 632856916A; Mon, 6 Sep 2021 04:01:28 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="DFo54giT"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1210E69177 for ; Mon, 6 Sep 2021 04:01:23 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A3DAE317; Mon, 6 Sep 2021 04:01:22 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1630893682; bh=09YKS3OCbJfM3iXPIX6mfmLL4N+doNvEjmNP+VkdoW8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DFo54giTBKzvkGS13Gg/oeR2tR9+vsu93VgQYDJZZtrNmtFXLVpd43kN/kL0X8rCh d7TdMYRe5pQgyb1X3TS2qOkwQW2OWNBUtq9oG3nlfqk7Mxt2PMynM0xVXN/74/jyWk JQiDJFW4Whjd6ogvpA7YiT0ajBJ7E2qzMzm14Mn0= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 6 Sep 2021 05:00:38 +0300 Message-Id: <20210906020100.14430-6-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> References: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 05/27] libcamera: formats: Move plane info structure to PixelFormatInfo 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Move the PixelFormatPlaneInfo structure within the PixelFormatInfo class definition and rename it to Plane, to align the naming scheme with other parts of libcamera, such as FrameBuffer::Plane or FrameMetadata::Plane. Signed-off-by: Laurent Pinchart Reviewed-by: Jean-Michel Hautbois Reviewed-by: Hirokazu Honda Reviewed-by: Paul Elder --- include/libcamera/internal/formats.h | 13 ++++++------- src/libcamera/formats.cpp | 12 ++++++------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h index 51a8a6b8b0ae..a07de6bc6020 100644 --- a/include/libcamera/internal/formats.h +++ b/include/libcamera/internal/formats.h @@ -19,12 +19,6 @@ namespace libcamera { -struct PixelFormatPlaneInfo -{ - unsigned int bytesPerGroup; - unsigned int verticalSubSampling; -}; - class PixelFormatInfo { public: @@ -34,6 +28,11 @@ public: ColourEncodingRAW, }; + struct Plane { + unsigned int bytesPerGroup; + unsigned int verticalSubSampling; + }; + bool isValid() const { return format.isValid(); } static const PixelFormatInfo &info(const PixelFormat &format); @@ -58,7 +57,7 @@ public: unsigned int pixelsPerGroup; - std::array planes; + std::array planes; }; } /* namespace libcamera */ diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp index 603d88619fe0..c993960eb982 100644 --- a/src/libcamera/formats.cpp +++ b/src/libcamera/formats.cpp @@ -24,15 +24,15 @@ namespace libcamera { LOG_DEFINE_CATEGORY(Formats) /** - * \class PixelFormatPlaneInfo + * \class PixelFormatInfo::Plane * \brief Information about a single plane of a pixel format * - * \var PixelFormatPlaneInfo::bytesPerGroup + * \var PixelFormatInfo::Plane::bytesPerGroup * \brief The number of bytes that a pixel group consumes * * \sa PixelFormatInfo::pixelsPerGroup * - * \var PixelFormatPlaneInfo::verticalSubSampling + * \var PixelFormatInfo::Plane::verticalSubSampling * \brief Vertical subsampling multiplier * * This value is the ratio between the number of rows of pixels in the frame @@ -87,7 +87,7 @@ LOG_DEFINE_CATEGORY(Formats) * * A pixel group is defined as the minimum number of pixels (including padding) * necessary in a row when the image has only one column of effective pixels. - * pixelsPerGroup refers to this value. PixelFormatPlaneInfo::bytesPerGroup, + * pixelsPerGroup refers to this value. PixelFormatInfo::Plane::bytesPerGroup, * then, refers to the number of bytes that a pixel group consumes. This * definition of a pixel group allows simple calculation of stride, as * ceil(width / pixelsPerGroup) * bytesPerGroup. These values are determined @@ -122,7 +122,7 @@ LOG_DEFINE_CATEGORY(Formats) * \var PixelFormatInfo::planes * \brief Information about pixels for each plane * - * \sa PixelFormatPlaneInfo + * \sa PixelFormatInfo::Plane */ /** @@ -869,7 +869,7 @@ unsigned int PixelFormatInfo::numPlanes() const { unsigned int count = 0; - for (const PixelFormatPlaneInfo &p : planes) { + for (const Plane &p : planes) { if (p.bytesPerGroup == 0) break; From patchwork Mon Sep 6 02:00:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13621 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 4D7B3C3246 for ; Mon, 6 Sep 2021 02:01:39 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2EE976916B; Mon, 6 Sep 2021 04:01:37 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Gpfw50+q"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D27226916F for ; Mon, 6 Sep 2021 04:01:23 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 66CB0317; Mon, 6 Sep 2021 04:01:23 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1630893683; bh=Sef7lmnQEDxTden/vXJyaa0xRkS8gcy3nJ8cA32vHZ4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Gpfw50+qN5oubGZaIEw9F5zjfvdj3oKSyjKS4K6vjL4bjyeaK4ZJufgAuVe4zNItH vmditywnComL9WfUgsor6r96lO5cte2uFJ2F6upLh9teyCO52zY2PVH3IvsL5M8eq7 lhltGsrFUaHDr0cRcO7Rge/VaBHEi3OLiRO5re0k= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 6 Sep 2021 05:00:40 +0300 Message-Id: <20210906020100.14430-8-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> References: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 07/27] libcamera: formats: Support V4L2 non-contiguous formats 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" V4L2 describes multi-planar formats with different 4CCs depending on whether or not the planes are stored contiguously in memory. Support this when translating between PixelFormat and V4L2PixelFormat. Signed-off-by: Laurent Pinchart Reviewed-by: Hirokazu Honda Reviewed-by: Jean-Michel Hautbois --- Changes since v1: - Replace the v4l2Format array with a structure --- include/libcamera/internal/formats.h | 5 +- src/libcamera/formats.cpp | 284 +++++++++++++++++++++------ src/libcamera/v4l2_pixelformat.cpp | 11 +- 3 files changed, 240 insertions(+), 60 deletions(-) diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h index b2869c93e960..5ebc68f91cda 100644 --- a/include/libcamera/internal/formats.h +++ b/include/libcamera/internal/formats.h @@ -54,7 +54,10 @@ public: /* \todo Add support for non-contiguous memory planes */ const char *name; PixelFormat format; - V4L2PixelFormat v4l2Format; + struct { + V4L2PixelFormat single; + V4L2PixelFormat multi; + } v4l2Formats; unsigned int bitsPerPixel; enum ColourEncoding colourEncoding; bool packed; diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp index ce0081a8a3d1..5bbb12347ac8 100644 --- a/src/libcamera/formats.cpp +++ b/src/libcamera/formats.cpp @@ -55,8 +55,15 @@ LOG_DEFINE_CATEGORY(Formats) * \var PixelFormatInfo::format * \brief The PixelFormat described by this instance * - * \var PixelFormatInfo::v4l2Format - * \brief The V4L2 pixel format corresponding to the PixelFormat + * \var PixelFormatInfo::v4l2Formats + * \brief The V4L2 pixel formats corresponding to the PixelFormat + * + * Multiple V4L2 formats may exist for one PixelFormat when the format uses + * multiple planes, as V4L2 defines separate 4CCs for contiguous and separate + * planes formats. The two entries in the array store the contiguous and + * non-contiguous V4L2 formats respectively. If the PixelFormat isn't a + * multiplanar format, or if no corresponding non-contiguous V4L2 format + * exists, the second entry is invalid. * * \var PixelFormatInfo::bitsPerPixel * \brief The average number of bits per pixel @@ -149,7 +156,10 @@ const std::map pixelFormatInfo{ { formats::RGB565, { .name = "RGB565", .format = formats::RGB565, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_RGB565), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_RGB565), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, @@ -159,7 +169,10 @@ const std::map pixelFormatInfo{ { formats::RGB565_BE, { .name = "RGB565_BE", .format = formats::RGB565_BE, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_RGB565X), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_RGB565X), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, @@ -169,7 +182,10 @@ const std::map pixelFormatInfo{ { formats::BGR888, { .name = "BGR888", .format = formats::BGR888, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_RGB24), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_RGB24), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, @@ -179,7 +195,10 @@ const std::map pixelFormatInfo{ { formats::RGB888, { .name = "RGB888", .format = formats::RGB888, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_BGR24), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_BGR24), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, @@ -189,7 +208,10 @@ const std::map pixelFormatInfo{ { formats::XRGB8888, { .name = "XRGB8888", .format = formats::XRGB8888, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_XBGR32), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_XBGR32), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, @@ -199,7 +221,10 @@ const std::map pixelFormatInfo{ { formats::XBGR8888, { .name = "XBGR8888", .format = formats::XBGR8888, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_RGBX32), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_RGBX32), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, @@ -209,7 +234,10 @@ const std::map pixelFormatInfo{ { formats::BGRX8888, { .name = "BGRX8888", .format = formats::BGRX8888, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_XRGB32), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_XRGB32), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, @@ -219,7 +247,10 @@ const std::map pixelFormatInfo{ { formats::ABGR8888, { .name = "ABGR8888", .format = formats::ABGR8888, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_RGBA32), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_RGBA32), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, @@ -229,7 +260,10 @@ const std::map pixelFormatInfo{ { formats::ARGB8888, { .name = "ARGB8888", .format = formats::ARGB8888, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_ABGR32), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_ABGR32), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, @@ -239,7 +273,10 @@ const std::map pixelFormatInfo{ { formats::BGRA8888, { .name = "BGRA8888", .format = formats::BGRA8888, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_ARGB32), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_ARGB32), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, @@ -249,7 +286,10 @@ const std::map pixelFormatInfo{ { formats::RGBA8888, { .name = "RGBA8888", .format = formats::RGBA8888, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_BGRA32), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_BGRA32), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, @@ -261,7 +301,10 @@ const std::map pixelFormatInfo{ { formats::YUYV, { .name = "YUYV", .format = formats::YUYV, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_YUYV), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_YUYV), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, @@ -271,7 +314,10 @@ const std::map pixelFormatInfo{ { formats::YVYU, { .name = "YVYU", .format = formats::YVYU, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_YVYU), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_YVYU), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, @@ -281,7 +327,10 @@ const std::map pixelFormatInfo{ { formats::UYVY, { .name = "UYVY", .format = formats::UYVY, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_UYVY), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_UYVY), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, @@ -291,7 +340,10 @@ const std::map pixelFormatInfo{ { formats::VYUY, { .name = "VYUY", .format = formats::VYUY, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_VYUY), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_VYUY), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, @@ -303,7 +355,10 @@ const std::map pixelFormatInfo{ { formats::NV12, { .name = "NV12", .format = formats::NV12, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV12), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_NV12), + .multi = V4L2PixelFormat(V4L2_PIX_FMT_NV12M), + }, .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, @@ -313,7 +368,10 @@ const std::map pixelFormatInfo{ { formats::NV21, { .name = "NV21", .format = formats::NV21, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV21), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_NV21), + .multi = V4L2PixelFormat(V4L2_PIX_FMT_NV21M), + }, .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, @@ -323,7 +381,10 @@ const std::map pixelFormatInfo{ { formats::NV16, { .name = "NV16", .format = formats::NV16, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV16), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_NV16), + .multi = V4L2PixelFormat(V4L2_PIX_FMT_NV16M), + }, .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, @@ -333,7 +394,10 @@ const std::map pixelFormatInfo{ { formats::NV61, { .name = "NV61", .format = formats::NV61, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV61), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_NV61), + .multi = V4L2PixelFormat(V4L2_PIX_FMT_NV61M), + }, .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, @@ -343,7 +407,10 @@ const std::map pixelFormatInfo{ { formats::NV24, { .name = "NV24", .format = formats::NV24, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV24), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_NV24), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, @@ -353,7 +420,10 @@ const std::map pixelFormatInfo{ { formats::NV42, { .name = "NV42", .format = formats::NV42, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV42), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_NV42), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, @@ -363,7 +433,10 @@ const std::map pixelFormatInfo{ { formats::YUV420, { .name = "YUV420", .format = formats::YUV420, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_YUV420), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_YUV420), + .multi = V4L2PixelFormat(V4L2_PIX_FMT_YUV420M), + }, .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, @@ -373,7 +446,10 @@ const std::map pixelFormatInfo{ { formats::YVU420, { .name = "YVU420", .format = formats::YVU420, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_YVU420), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_YVU420), + .multi = V4L2PixelFormat(V4L2_PIX_FMT_YVU420M), + }, .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, @@ -383,7 +459,10 @@ const std::map pixelFormatInfo{ { formats::YUV422, { .name = "YUV422", .format = formats::YUV422, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_YUV422P), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_YUV422P), + .multi = V4L2PixelFormat(V4L2_PIX_FMT_YUV422M), + }, .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, @@ -395,7 +474,10 @@ const std::map pixelFormatInfo{ { formats::R8, { .name = "R8", .format = formats::R8, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_GREY), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_GREY), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, @@ -407,7 +489,10 @@ const std::map pixelFormatInfo{ { formats::SBGGR8, { .name = "SBGGR8", .format = formats::SBGGR8, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR8), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR8), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, @@ -417,7 +502,10 @@ const std::map pixelFormatInfo{ { formats::SGBRG8, { .name = "SGBRG8", .format = formats::SGBRG8, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG8), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG8), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, @@ -427,7 +515,10 @@ const std::map pixelFormatInfo{ { formats::SGRBG8, { .name = "SGRBG8", .format = formats::SGRBG8, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG8), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG8), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, @@ -437,7 +528,10 @@ const std::map pixelFormatInfo{ { formats::SRGGB8, { .name = "SRGGB8", .format = formats::SRGGB8, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB8), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB8), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, @@ -447,7 +541,10 @@ const std::map pixelFormatInfo{ { formats::SBGGR10, { .name = "SBGGR10", .format = formats::SBGGR10, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, @@ -457,7 +554,10 @@ const std::map pixelFormatInfo{ { formats::SGBRG10, { .name = "SGBRG10", .format = formats::SGBRG10, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG10), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG10), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, @@ -467,7 +567,10 @@ const std::map pixelFormatInfo{ { formats::SGRBG10, { .name = "SGRBG10", .format = formats::SGRBG10, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, @@ -477,7 +580,10 @@ const std::map pixelFormatInfo{ { formats::SRGGB10, { .name = "SRGGB10", .format = formats::SRGGB10, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, @@ -487,7 +593,10 @@ const std::map pixelFormatInfo{ { formats::SBGGR10_CSI2P, { .name = "SBGGR10_CSI2P", .format = formats::SBGGR10_CSI2P, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10P), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10P), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, @@ -497,7 +606,10 @@ const std::map pixelFormatInfo{ { formats::SGBRG10_CSI2P, { .name = "SGBRG10_CSI2P", .format = formats::SGBRG10_CSI2P, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG10P), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG10P), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, @@ -507,7 +619,10 @@ const std::map pixelFormatInfo{ { formats::SGRBG10_CSI2P, { .name = "SGRBG10_CSI2P", .format = formats::SGRBG10_CSI2P, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10P), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10P), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, @@ -517,7 +632,10 @@ const std::map pixelFormatInfo{ { formats::SRGGB10_CSI2P, { .name = "SRGGB10_CSI2P", .format = formats::SRGGB10_CSI2P, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10P), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10P), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, @@ -527,7 +645,10 @@ const std::map pixelFormatInfo{ { formats::SBGGR12, { .name = "SBGGR12", .format = formats::SBGGR12, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR12), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR12), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, @@ -537,7 +658,10 @@ const std::map pixelFormatInfo{ { formats::SGBRG12, { .name = "SGBRG12", .format = formats::SGBRG12, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG12), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG12), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, @@ -547,7 +671,10 @@ const std::map pixelFormatInfo{ { formats::SGRBG12, { .name = "SGRBG12", .format = formats::SGRBG12, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG12), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG12), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, @@ -557,7 +684,10 @@ const std::map pixelFormatInfo{ { formats::SRGGB12, { .name = "SRGGB12", .format = formats::SRGGB12, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB12), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB12), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, @@ -567,7 +697,10 @@ const std::map pixelFormatInfo{ { formats::SBGGR12_CSI2P, { .name = "SBGGR12_CSI2P", .format = formats::SBGGR12_CSI2P, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR12P), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR12P), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, @@ -577,7 +710,10 @@ const std::map pixelFormatInfo{ { formats::SGBRG12_CSI2P, { .name = "SGBRG12_CSI2P", .format = formats::SGBRG12_CSI2P, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG12P), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG12P), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, @@ -587,7 +723,10 @@ const std::map pixelFormatInfo{ { formats::SGRBG12_CSI2P, { .name = "SGRBG12_CSI2P", .format = formats::SGRBG12_CSI2P, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG12P), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG12P), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, @@ -597,7 +736,10 @@ const std::map pixelFormatInfo{ { formats::SRGGB12_CSI2P, { .name = "SRGGB12_CSI2P", .format = formats::SRGGB12_CSI2P, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB12P), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB12P), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, @@ -607,7 +749,10 @@ const std::map pixelFormatInfo{ { formats::SBGGR16, { .name = "SBGGR16", .format = formats::SBGGR16, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR16), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR16), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, @@ -617,7 +762,10 @@ const std::map pixelFormatInfo{ { formats::SGBRG16, { .name = "SGBRG16", .format = formats::SGBRG16, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG16), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG16), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, @@ -627,7 +775,10 @@ const std::map pixelFormatInfo{ { formats::SGRBG16, { .name = "SGRBG16", .format = formats::SGRBG16, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG16), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG16), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, @@ -637,7 +788,10 @@ const std::map pixelFormatInfo{ { formats::SRGGB16, { .name = "SRGGB16", .format = formats::SRGGB16, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB16), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB16), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, @@ -647,7 +801,10 @@ const std::map pixelFormatInfo{ { formats::SBGGR10_IPU3, { .name = "SBGGR10_IPU3", .format = formats::SBGGR10_IPU3, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SBGGR10), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SBGGR10), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, @@ -658,7 +815,10 @@ const std::map pixelFormatInfo{ { formats::SGBRG10_IPU3, { .name = "SGBRG10_IPU3", .format = formats::SGBRG10_IPU3, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SGBRG10), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SGBRG10), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, @@ -668,7 +828,10 @@ const std::map pixelFormatInfo{ { formats::SGRBG10_IPU3, { .name = "SGRBG10_IPU3", .format = formats::SGRBG10_IPU3, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SGRBG10), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SGRBG10), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, @@ -678,7 +841,10 @@ const std::map pixelFormatInfo{ { formats::SRGGB10_IPU3, { .name = "SRGGB10_IPU3", .format = formats::SRGGB10_IPU3, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SRGGB10), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SRGGB10), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, @@ -690,7 +856,10 @@ const std::map pixelFormatInfo{ { formats::MJPEG, { .name = "MJPEG", .format = formats::MJPEG, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_MJPEG), + .v4l2Formats = { + .single = V4L2PixelFormat(V4L2_PIX_FMT_MJPEG), + .multi = V4L2PixelFormat(), + }, .bitsPerPixel = 0, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, @@ -736,7 +905,8 @@ const PixelFormatInfo &PixelFormatInfo::info(const V4L2PixelFormat &format) { const auto &info = std::find_if(pixelFormatInfo.begin(), pixelFormatInfo.end(), [format](auto pair) { - return pair.second.v4l2Format == format; + return pair.second.v4l2Formats.single == format || + pair.second.v4l2Formats.multi == format; }); if (info == pixelFormatInfo.end()) return pixelFormatInfoInvalid; diff --git a/src/libcamera/v4l2_pixelformat.cpp b/src/libcamera/v4l2_pixelformat.cpp index 93fc4446cc64..d1f3a42f3de2 100644 --- a/src/libcamera/v4l2_pixelformat.cpp +++ b/src/libcamera/v4l2_pixelformat.cpp @@ -67,12 +67,19 @@ const std::map vpf2pf{ /* YUV planar formats. */ { V4L2PixelFormat(V4L2_PIX_FMT_NV16), formats::NV16 }, + { V4L2PixelFormat(V4L2_PIX_FMT_NV16M), formats::NV16 }, { V4L2PixelFormat(V4L2_PIX_FMT_NV61), formats::NV61 }, + { V4L2PixelFormat(V4L2_PIX_FMT_NV61M), formats::NV61 }, { V4L2PixelFormat(V4L2_PIX_FMT_NV12), formats::NV12 }, + { V4L2PixelFormat(V4L2_PIX_FMT_NV12M), formats::NV12 }, { V4L2PixelFormat(V4L2_PIX_FMT_NV21), formats::NV21 }, + { V4L2PixelFormat(V4L2_PIX_FMT_NV21M), formats::NV21 }, { V4L2PixelFormat(V4L2_PIX_FMT_YUV420), formats::YUV420 }, + { V4L2PixelFormat(V4L2_PIX_FMT_YUV420M), formats::YUV420 }, { V4L2PixelFormat(V4L2_PIX_FMT_YVU420), formats::YVU420 }, + { V4L2PixelFormat(V4L2_PIX_FMT_YVU420M), formats::YVU420 }, { V4L2PixelFormat(V4L2_PIX_FMT_YUV422P), formats::YUV422 }, + { V4L2PixelFormat(V4L2_PIX_FMT_YUV422M), formats::YUV422 }, /* Greyscale formats. */ { V4L2PixelFormat(V4L2_PIX_FMT_GREY), formats::R8 }, @@ -202,13 +209,13 @@ PixelFormat V4L2PixelFormat::toPixelFormat() const * \return The V4L2PixelFormat corresponding to \a pixelFormat */ V4L2PixelFormat V4L2PixelFormat::fromPixelFormat(const PixelFormat &pixelFormat, - [[maybe_unused]] bool multiplanar) + bool multiplanar) { const PixelFormatInfo &info = PixelFormatInfo::info(pixelFormat); if (!info.isValid()) return V4L2PixelFormat(); - return info.v4l2Format; + return multiplanar ? info.v4l2Formats.multi : info.v4l2Formats.single; } } /* namespace libcamera */ From patchwork Mon Sep 6 02:00:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13622 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 654F6C324A for ; Mon, 6 Sep 2021 02:01:44 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E521E6917F; Mon, 6 Sep 2021 04:01:38 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="VrGhWzjH"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5F77069179 for ; Mon, 6 Sep 2021 04:01:25 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id ED952317; Mon, 6 Sep 2021 04:01:24 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1630893685; bh=01N1ZgIx+X2DwgcJlzMy1w63JnMIRFmJhfzVca4M7jU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VrGhWzjHepnMnBLrpGtDT1hJ1udRpvBobZW0XHuIpvXQcpxyPPJL7avXukj9C2rUT P24iwVGzvPdqpAAhJbqW7m88MdsiSQNWaPUXwRFgcrWJnG1bswPPSbxnJfCkYk9I00 gQBPq5nfJh9vFGCqYQpCnApubJyOH15CARHwIbt4= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 6 Sep 2021 05:00:44 +0300 Message-Id: <20210906020100.14430-12-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> References: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 11/27] libcamera: v4l2_videodevice: Document plane handling in createBuffer() 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The V4L2VideoDevice::createBuffer() calculates offsets manually when using a multi-planar pixel format and a single-planar V4L2 format. The process isn't trivial, document it. Signed-off-by: Laurent Pinchart Reviewed-by: Jean-Michel Hautbois Reviewed-by: Hirokazu Honda --- src/libcamera/v4l2_videodevice.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index 1483181a0856..88535f5a07c7 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -1334,10 +1334,19 @@ std::unique_ptr V4L2VideoDevice::createBuffer(unsigned int index) } /* + * If we have a multi-planar format with a V4L2 single-planar buffer, + * split the single V4L2 plane into multiple FrameBuffer planes by + * computing the offsets manually. + * * The format info is not guaranteed to be valid, as there are no * PixelFormatInfo for metadata formats, so check it first. */ if (formatInfo_->isValid() && formatInfo_->numPlanes() != numPlanes) { + /* + * There's no valid situation where the number of colour planes + * differs from the number of V4L2 planes and the V4L2 buffer + * has more than one plane. + */ ASSERT(numPlanes == 1u); planes.resize(formatInfo_->numPlanes()); From patchwork Mon Sep 6 02:00:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13623 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 7CCDAC324B for ; Mon, 6 Sep 2021 02:01:46 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E59F26917B; Mon, 6 Sep 2021 04:01:39 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="p3ccUtT2"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8E0F469174 for ; Mon, 6 Sep 2021 04:01:26 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1E7838D7; Mon, 6 Sep 2021 04:01:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1630893686; bh=ADgP6wyAOxxkbNZHhYHjOLTRGZIwB18N9UIOasiuSEc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=p3ccUtT2jzcZCA6ZY+fgZN2mGhRHjW+MGR8Dz6SY66zmApfTNon8eNT80msnRy6sq py9G98XFSzLV8nB75LpRvmCsmEHqGRtjFoCf2HEL1WangD55kCFt3F+bnfe47ao7Jd NT9u4Bk7jtATFYjk1WGDpmRYBGXSbCM8hwc3vx04= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 6 Sep 2021 05:00:47 +0300 Message-Id: <20210906020100.14430-15-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> References: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 14/27] libcamera: v4l2_videodevice: Split planes when dequeuing buffer 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" When dequeueing a buffer from a V4L2VideoDevice, the number of planes in the FrameBuffer may not match the number of V4L2 buffer planes if the PixelFormat is multi-planar (has multiple colour planes) and the V4L2 format is single-planar (has a single buffer plane). In this case, we need to split the single V4L2 buffer plane into FrameBuffer planes. Do so, and add checks to reject invalid V4L2 buffers in case of a driver issue. Signed-off-by: Laurent Pinchart Reviewed-by: Hirokazu Honda --- Changes since v1: - Reduce indentation --- src/libcamera/v4l2_videodevice.cpp | 53 +++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index 625d5da40337..0a7fbdb7e011 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -7,6 +7,7 @@ #include "libcamera/internal/v4l2_videodevice.h" +#include #include #include #include @@ -1664,12 +1665,54 @@ FrameBuffer *V4L2VideoDevice::dequeueBuffer() buffer->metadata_.timestamp = buf.timestamp.tv_sec * 1000000000ULL + buf.timestamp.tv_usec * 1000ULL; - buffer->metadata_.planes.clear(); - if (multiPlanar) { - for (unsigned int nplane = 0; nplane < buf.length; nplane++) - buffer->metadata_.planes.push_back({ planes[nplane].bytesused }); + if (V4L2_TYPE_IS_OUTPUT(buf.type)) + return buffer; + + unsigned int numV4l2Planes = multiPlanar ? buf.length : 1; + FrameMetadata &metadata = buffer->metadata_; + metadata.planes.clear(); + + if (numV4l2Planes != buffer->planes().size()) { + /* + * If we have a multi-planar buffer with a V4L2 + * single-planar format, split the V4L2 buffer across + * the buffer planes. Only the last plane may have less + * bytes used than its length. + */ + if (numV4l2Planes != 1) { + LOG(V4L2, Error) + << "Invalid number of planes (" << numV4l2Planes + << " != " << buffer->planes().size() << ")"; + + metadata.status = FrameMetadata::FrameError; + return buffer; + } + + unsigned int bytesused = multiPlanar ? planes[0].bytesused + : buf.bytesused; + + for (auto [i, plane] : utils::enumerate(buffer->planes())) { + if (!bytesused) { + LOG(V4L2, Error) + << "Dequeued buffer is too small"; + + metadata.status = FrameMetadata::FrameError; + return buffer; + } + + metadata.planes.push_back({ std::min(plane.length, bytesused) }); + bytesused -= metadata.planes.back().bytesused; + } + } else if (multiPlanar) { + /* + * If we use the multi-planar API, fill in the planes. + * The number of planes in the frame buffer and in the + * V4L2 buffer is guaranteed to be equal at this point. + */ + for (unsigned int i = 0; i < numV4l2Planes; ++i) + metadata.planes.push_back({ planes[i].bytesused }); } else { - buffer->metadata_.planes.push_back({ buf.bytesused }); + metadata.planes.push_back({ buf.bytesused }); } return buffer; From patchwork Mon Sep 6 02:00:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13627 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id BF437BD87D for ; Mon, 6 Sep 2021 02:09:11 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EE2DF69188; Mon, 6 Sep 2021 04:01:40 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="MrGny06/"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EDC8069173 for ; Mon, 6 Sep 2021 04:01:26 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7A54F317; Mon, 6 Sep 2021 04:01:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1630893686; bh=LjAFG557AsMFuQqRp6gQiNAC/v5bRxRLiV3zQyayPoQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MrGny06/Blaq8MNMsMVTHv6WiZeqInaWFlvENlfiUvXgB0zK0dxcH+XL7Nxlq9pk3 4eYq258hvJEYcw3c2nZA+X+zu/mI9o6sBGQZT9y9dhHzpVN1o9apZ0SkivkPjgHcqj z7KHyYrO55uYeQcMMgB8UW3kaI1eVGEJNGhpkZ9s= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 6 Sep 2021 05:00:48 +0300 Message-Id: <20210906020100.14430-16-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> References: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 15/27] libcamera: v4l2_videodevice: Use utils::enumerate() 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Replace a manual counter with the utils::enumerate() utility function. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Hirokazu Honda --- src/libcamera/v4l2_videodevice.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index 0a7fbdb7e011..59aa53c7c27e 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -1356,7 +1356,7 @@ std::unique_ptr V4L2VideoDevice::createBuffer(unsigned int index) const FileDescriptor &fd = planes[0].fd; size_t offset = 0; - for (size_t i = 0; i < planes.size(); ++i) { + for (auto [i, plane] : utils::enumerate(planes)) { /* * The stride is reported by V4L2 for the first plane * only. Compute the stride of the other planes by @@ -1368,11 +1368,11 @@ std::unique_ptr V4L2VideoDevice::createBuffer(unsigned int index) * formatInfo_->planes[i].bytesPerGroup / formatInfo_->planes[0].bytesPerGroup; - planes[i].fd = fd; - planes[i].offset = offset; - planes[i].length = formatInfo_->planeSize(format_.size.height, - i, stride); - offset += planes[i].length; + plane.fd = fd; + plane.offset = offset; + plane.length = formatInfo_->planeSize(format_.size.height, + i, stride); + offset += plane.length; } } From patchwork Mon Sep 6 02:00:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13624 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id A6B89C324C for ; Mon, 6 Sep 2021 02:01:50 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 04C976916C; Mon, 6 Sep 2021 04:01:42 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="aENYqNOE"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B24056916F for ; Mon, 6 Sep 2021 04:01:27 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 403458D7; Mon, 6 Sep 2021 04:01:27 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1630893687; bh=3qDqvTFoKWq0JsFPCuhidIF49wrJmvmJs7RUtDS73gU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aENYqNOEJl2n2H+Mwn4vHCnQQkjZjmrWSGnHX+M8NNRrRuJK+s16o/dSDePLrGJWV YZ+7cO90RIDvRMCrbyRkQGg4eTxQ76lnQqIUhYTFHyPv8AtwY6FdYNbrkbrdAmudDo /bDvvmfS+wiNzw3tB6mapz0NPj4FPY6S6jiq27FM= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 6 Sep 2021 05:00:50 +0300 Message-Id: <20210906020100.14430-18-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> References: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 17/27] libcamera: framebuffer: Prevent modifying the number of metadata planes 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The number of metadata planes should always match the number of frame buffer planes. Enforce this by making the vector private and providing accessor functions. As this changes the public API, update all in-tree users accordingly. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Jean-Michel Hautbois Reviewed-by: Hirokazu Honda --- include/libcamera/framebuffer.h | 10 +++++++++- src/cam/camera_session.cpp | 4 ++-- src/cam/file_sink.cpp | 2 +- src/libcamera/framebuffer.cpp | 12 +++++++++--- src/libcamera/v4l2_videodevice.cpp | 14 +++++++------- src/qcam/main_window.cpp | 2 +- src/qcam/viewfinder_gl.cpp | 2 +- src/qcam/viewfinder_qt.cpp | 2 +- src/v4l2/v4l2_camera_proxy.cpp | 2 +- 9 files changed, 32 insertions(+), 18 deletions(-) diff --git a/include/libcamera/framebuffer.h b/include/libcamera/framebuffer.h index fd68ed0a139d..7f2f176af691 100644 --- a/include/libcamera/framebuffer.h +++ b/include/libcamera/framebuffer.h @@ -13,6 +13,7 @@ #include #include +#include #include @@ -34,7 +35,14 @@ struct FrameMetadata { Status status; unsigned int sequence; uint64_t timestamp; - std::vector planes; + + Span planes() { return planes_; } + Span planes() const { return planes_; } + +private: + friend class FrameBuffer; + + std::vector planes_; }; class FrameBuffer final : public Extensible diff --git a/src/cam/camera_session.cpp b/src/cam/camera_session.cpp index 60d640f2b15c..32a373a99b72 100644 --- a/src/cam/camera_session.cpp +++ b/src/cam/camera_session.cpp @@ -374,9 +374,9 @@ void CameraSession::processRequest(Request *request) << " bytesused: "; unsigned int nplane = 0; - for (const FrameMetadata::Plane &plane : metadata.planes) { + for (const FrameMetadata::Plane &plane : metadata.planes()) { info << plane.bytesused; - if (++nplane < metadata.planes.size()) + if (++nplane < metadata.planes().size()) info << "/"; } } diff --git a/src/cam/file_sink.cpp b/src/cam/file_sink.cpp index 0b529e3eb767..0fc7d621f50b 100644 --- a/src/cam/file_sink.cpp +++ b/src/cam/file_sink.cpp @@ -110,7 +110,7 @@ void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer) for (unsigned int i = 0; i < buffer->planes().size(); ++i) { const FrameBuffer::Plane &plane = buffer->planes()[i]; - const FrameMetadata::Plane &meta = buffer->metadata().planes[i]; + const FrameMetadata::Plane &meta = buffer->metadata().planes()[i]; uint8_t *data = planeData_[&plane]; unsigned int length = std::min(meta.bytesused, plane.length); diff --git a/src/libcamera/framebuffer.cpp b/src/libcamera/framebuffer.cpp index e4f8419a9063..d44a98babd05 100644 --- a/src/libcamera/framebuffer.cpp +++ b/src/libcamera/framebuffer.cpp @@ -91,8 +91,14 @@ LOG_DEFINE_CATEGORY(Buffer) */ /** - * \var FrameMetadata::planes - * \brief Array of per-plane metadata + * \fn FrameMetadata::planes() + * \copydoc FrameMetadata::planes() const + */ + +/** + * \fn FrameMetadata::planes() const + * \brief Retrieve the array of per-plane metadata + * \return The array of per-plane metadata */ /** @@ -210,7 +216,7 @@ FrameBuffer::FrameBuffer(const std::vector &planes, unsigned int cookie) : Extensible(std::make_unique()), planes_(planes), cookie_(cookie) { - metadata_.planes.resize(planes_.size()); + metadata_.planes_.resize(planes_.size()); unsigned int offset = 0; bool isContiguous = true; diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index e729e608448c..296304fbd979 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -1538,7 +1538,7 @@ int V4L2VideoDevice::queueBuffer(FrameBuffer *buffer) unsigned int length = 0; for (auto [i, plane] : utils::enumerate(planes)) { - bytesused += metadata.planes[i].bytesused; + bytesused += metadata.planes()[i].bytesused; length += plane.length; if (i != planes.size() - 1 && bytesused != length) { @@ -1562,7 +1562,7 @@ int V4L2VideoDevice::queueBuffer(FrameBuffer *buffer) * V4L2 buffer is guaranteed to be equal at this point. */ for (auto [i, plane] : utils::enumerate(planes)) { - v4l2Planes[i].bytesused = metadata.planes[i].bytesused; + v4l2Planes[i].bytesused = metadata.planes()[i].bytesused; v4l2Planes[i].length = plane.length; } } else { @@ -1570,7 +1570,7 @@ int V4L2VideoDevice::queueBuffer(FrameBuffer *buffer) * Single-planar API with a single plane in the buffer * is trivial to handle. */ - buf.bytesused = metadata.planes[0].bytesused; + buf.bytesused = metadata.planes()[0].bytesused; buf.length = planes[0].length; } @@ -1699,9 +1699,9 @@ FrameBuffer *V4L2VideoDevice::dequeueBuffer() return buffer; } - metadata.planes[i].bytesused = + metadata.planes()[i].bytesused = std::min(plane.length, bytesused); - bytesused -= metadata.planes[i].bytesused; + bytesused -= metadata.planes()[i].bytesused; } } else if (multiPlanar) { /* @@ -1710,9 +1710,9 @@ FrameBuffer *V4L2VideoDevice::dequeueBuffer() * V4L2 buffer is guaranteed to be equal at this point. */ for (unsigned int i = 0; i < numV4l2Planes; ++i) - metadata.planes[i].bytesused = planes[i].bytesused; + metadata.planes()[i].bytesused = planes[i].bytesused; } else { - metadata.planes[0].bytesused = buf.bytesused; + metadata.planes()[0].bytesused = buf.bytesused; } return buffer; diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index 1536b2b5bd66..ac853e360aea 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -756,7 +756,7 @@ void MainWindow::processViewfinder(FrameBuffer *buffer) qDebug().noquote() << QString("seq: %1").arg(metadata.sequence, 6, 10, QLatin1Char('0')) - << "bytesused:" << metadata.planes[0].bytesused + << "bytesused:" << metadata.planes()[0].bytesused << "timestamp:" << metadata.timestamp << "fps:" << Qt::fixed << qSetRealNumberPrecision(2) << fps; diff --git a/src/qcam/viewfinder_gl.cpp b/src/qcam/viewfinder_gl.cpp index 40226601f9fd..d2ef036974f4 100644 --- a/src/qcam/viewfinder_gl.cpp +++ b/src/qcam/viewfinder_gl.cpp @@ -125,7 +125,7 @@ void ViewFinderGL::render(libcamera::FrameBuffer *buffer, /* * \todo Get the stride from the buffer instead of computing it naively */ - stride_ = buffer->metadata().planes[0].bytesused / size_.height(); + stride_ = buffer->metadata().planes()[0].bytesused / size_.height(); update(); buffer_ = buffer; } diff --git a/src/qcam/viewfinder_qt.cpp b/src/qcam/viewfinder_qt.cpp index efa1d412584b..a0bf99b0b522 100644 --- a/src/qcam/viewfinder_qt.cpp +++ b/src/qcam/viewfinder_qt.cpp @@ -87,7 +87,7 @@ void ViewFinderQt::render(libcamera::FrameBuffer *buffer, } unsigned char *memory = mem.data(); - size_t size = buffer->metadata().planes[0].bytesused; + size_t size = buffer->metadata().planes()[0].bytesused; { QMutexLocker locker(&mutex_); diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index d926a7b77083..07d2250bb846 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -211,7 +211,7 @@ void V4L2CameraProxy::updateBuffers() switch (fmd.status) { case FrameMetadata::FrameSuccess: - buf.bytesused = fmd.planes[0].bytesused; + buf.bytesused = fmd.planes()[0].bytesused; buf.field = V4L2_FIELD_NONE; buf.timestamp.tv_sec = fmd.timestamp / 1000000000; buf.timestamp.tv_usec = fmd.timestamp % 1000000; From patchwork Mon Sep 6 02:00:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13625 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id A22A9C3252 for ; Mon, 6 Sep 2021 02:01:51 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4702F69195; Mon, 6 Sep 2021 04:01:45 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="XjFxP4J/"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 622446917D for ; Mon, 6 Sep 2021 04:01:30 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id EF0AA317; Mon, 6 Sep 2021 04:01:29 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1630893690; bh=EXDpKBAwzDoi0Leyasjz9PsQE6wcJa7A0xsiCgMtj0k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XjFxP4J/HfnY0LAfbeG9iWb0OwE9ZphTc2VY8L9Zc7iFjXKwimB85t4z6mJz6zO50 g2BAhdy3hNw0QYx2Fy8qKKnpqgh6qTakPt7qkPPnKwlG0xENW9EVqaCUjc2hI3eOjB 2ikDYd/0egybU0vOOsopxbJRzbJdv5IY1YT+edKE= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 6 Sep 2021 05:00:57 +0300 Message-Id: <20210906020100.14430-25-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> References: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 24/27] qcam: Print bytesused for all planes 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Fix the debug message that prints frame metadata to print the number of bytes used for each plane, not just the first one. Signed-off-by: Laurent Pinchart Reviewed-by: Jean-Michel Hautbois --- src/qcam/main_window.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index ac853e360aea..0a00b1001570 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -754,9 +755,13 @@ void MainWindow::processViewfinder(FrameBuffer *buffer) fps = lastBufferTime_ && fps ? 1000000000.0 / fps : 0.0; lastBufferTime_ = metadata.timestamp; + QStringList bytesused; + for (const FrameMetadata::Plane &plane : metadata.planes()) + bytesused << QString::number(plane.bytesused); + qDebug().noquote() << QString("seq: %1").arg(metadata.sequence, 6, 10, QLatin1Char('0')) - << "bytesused:" << metadata.planes()[0].bytesused + << "bytesused:" << bytesused.join("/") << "timestamp:" << metadata.timestamp << "fps:" << Qt::fixed << qSetRealNumberPrecision(2) << fps; From patchwork Mon Sep 6 02:01:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13626 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id DE120C3255 for ; Mon, 6 Sep 2021 02:01:51 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 65D9F6919A; Mon, 6 Sep 2021 04:01:46 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="OXd8D5y0"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 81AEB69168 for ; Mon, 6 Sep 2021 04:01:31 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1B1EB8D7; Mon, 6 Sep 2021 04:01:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1630893691; bh=nU44O2CRh0Z7L7TY3mzq8q94t1OYxvVKQ6Xr8p9WQGM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OXd8D5y0tb/+SBQ0npZRv4wq3yG5ohcj9xjOduIxj7UxtVkd9whSVKHJmDQ7Me1F3 2g/IbqhzFnZEq6MAwa38bG86FZOm4V/otcKu2Wo/jx70RX7pRYuoXMum1zOwbYXwbj tTicQOnKh6vm+aIw6Lp5basE4pNj2VqD66UUFdmc= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 6 Sep 2021 05:01:00 +0300 Message-Id: <20210906020100.14430-28-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> References: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 27/27] qcam: viewfinder_qt: Support multi-planar buffers 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Now that the ViewFinderQt receives an Image, move the Converter API to take an Image as well, and enable multi-planar buffer support. Signed-off-by: Laurent Pinchart Reviewed-by: Jean-Michel Hautbois --- src/qcam/format_converter.cpp | 18 +++++++++++------- src/qcam/format_converter.h | 9 +++++---- src/qcam/viewfinder_qt.cpp | 14 +++++--------- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/qcam/format_converter.cpp b/src/qcam/format_converter.cpp index 973966f6afc1..673ad33e141d 100644 --- a/src/qcam/format_converter.cpp +++ b/src/qcam/format_converter.cpp @@ -13,6 +13,8 @@ #include +#include "../cam/image.h" + #define RGBSHIFT 8 #ifndef MAX #define MAX(a,b) ((a)>(b)?(a):(b)) @@ -154,12 +156,11 @@ int FormatConverter::configure(const libcamera::PixelFormat &format, return 0; } -void FormatConverter::convert(const unsigned char *src, size_t size, - QImage *dst) +void FormatConverter::convert(const Image *src, size_t size, QImage *dst) { switch (formatFamily_) { case MJPEG: - dst->loadFromData(src, size, "JPEG"); + dst->loadFromData(src->data(0).data(), size, "JPEG"); break; case YUV: convertYUV(src, dst->bits()); @@ -183,13 +184,14 @@ static void yuv_to_rgb(int y, int u, int v, int *r, int *g, int *b) *b = CLIP(( 298 * c + 516 * d + 128) >> RGBSHIFT); } -void FormatConverter::convertNV(const unsigned char *src, unsigned char *dst) +void FormatConverter::convertNV(const Image *srcImage, unsigned char *dst) { unsigned int c_stride = width_ * (2 / horzSubSample_); unsigned int c_inc = horzSubSample_ == 1 ? 2 : 0; unsigned int cb_pos = nvSwap_ ? 1 : 0; unsigned int cr_pos = nvSwap_ ? 0 : 1; - const unsigned char *src_c = src + width_ * height_; + const unsigned char *src = srcImage->data(0).data(); + const unsigned char *src_c = srcImage->data(1).data(); int r, g, b; for (unsigned int y = 0; y < height_; y++) { @@ -223,8 +225,9 @@ void FormatConverter::convertNV(const unsigned char *src, unsigned char *dst) } } -void FormatConverter::convertRGB(const unsigned char *src, unsigned char *dst) +void FormatConverter::convertRGB(const Image *srcImage, unsigned char *dst) { + const unsigned char *src = srcImage->data(0).data(); unsigned int x, y; int r, g, b; @@ -245,8 +248,9 @@ void FormatConverter::convertRGB(const unsigned char *src, unsigned char *dst) } } -void FormatConverter::convertYUV(const unsigned char *src, unsigned char *dst) +void FormatConverter::convertYUV(const Image *srcImage, unsigned char *dst) { + const unsigned char *src = srcImage->data(0).data(); unsigned int src_x, src_y, dst_x, dst_y; unsigned int src_stride; unsigned int dst_stride; diff --git a/src/qcam/format_converter.h b/src/qcam/format_converter.h index e389b24a69f7..2220a62b5f11 100644 --- a/src/qcam/format_converter.h +++ b/src/qcam/format_converter.h @@ -13,6 +13,7 @@ #include +class Image; class QImage; class FormatConverter @@ -20,7 +21,7 @@ class FormatConverter public: int configure(const libcamera::PixelFormat &format, const QSize &size); - void convert(const unsigned char *src, size_t size, QImage *dst); + void convert(const Image *src, size_t size, QImage *dst); private: enum FormatFamily { @@ -30,9 +31,9 @@ private: YUV, }; - void convertNV(const unsigned char *src, unsigned char *dst); - void convertRGB(const unsigned char *src, unsigned char *dst); - void convertYUV(const unsigned char *src, unsigned char *dst); + void convertNV(const Image *src, unsigned char *dst); + void convertRGB(const Image *src, unsigned char *dst); + void convertYUV(const Image *src, unsigned char *dst); libcamera::PixelFormat format_; unsigned int width_; diff --git a/src/qcam/viewfinder_qt.cpp b/src/qcam/viewfinder_qt.cpp index fef6d53eef5e..0d357d860014 100644 --- a/src/qcam/viewfinder_qt.cpp +++ b/src/qcam/viewfinder_qt.cpp @@ -7,6 +7,7 @@ #include "viewfinder_qt.h" +#include #include #include @@ -81,12 +82,6 @@ int ViewFinderQt::setFormat(const libcamera::PixelFormat &format, void ViewFinderQt::render(libcamera::FrameBuffer *buffer, Image *image) { - if (buffer->planes().size() != 1) { - qWarning() << "Multi-planar buffers are not supported"; - return; - } - - unsigned char *memory = image->data(0).data(); size_t size = buffer->metadata().planes()[0].bytesused; { @@ -103,8 +98,9 @@ void ViewFinderQt::render(libcamera::FrameBuffer *buffer, Image *image) * \todo Get the stride from the buffer instead of * computing it naively */ - image_ = QImage(memory, size_.width(), size_.height(), - size / size_.height(), + assert(buffer->planes().size() == 1); + image_ = QImage(image->data(0).data(), size_.width(), + size_.height(), size / size_.height(), ::nativeFormats[format_]); std::swap(buffer, buffer_); } else { @@ -112,7 +108,7 @@ void ViewFinderQt::render(libcamera::FrameBuffer *buffer, Image *image) * Otherwise, convert the format and release the frame * buffer immediately. */ - converter_.convert(memory, size, &image_); + converter_.convert(image, size, &image_); } } From patchwork Mon Sep 6 13:40:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13629 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 8C91BBDC71 for ; Mon, 6 Sep 2021 13:40:29 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4FA4C69167; Mon, 6 Sep 2021 15:40:29 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="oVSaAeDW"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 95BCE60137 for ; Mon, 6 Sep 2021 15:40:27 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 279538AD; Mon, 6 Sep 2021 15:40:27 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1630935627; bh=TBQvXpQIJzuTDycAD7Y3oLbrRvEgYn7z0BfVUGGdfFE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oVSaAeDWBYuRQdUq7mMQAlQKC/FKO+hI9gmAj5HIborwetw/d6q/UigCIExFKsLex KdLEGYeSjnKkApTo3KDgovE7AsBmRBpHJDMIFtzQOqUTf38hhhQeXIDpnZnegBtT70 G/OX53+LKLhmI3bU9n58u1UpnAaDJOCMmS1VE2fY= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 6 Sep 2021 16:40:04 +0300 Message-Id: <20210906134004.23485-1-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> References: <20210906020100.14430-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 28/27] android: jpeg: Support multi-planar buffers 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The JPEG post-processor uses MappedFrameBuffer to access pixel data, but only uses data from the first plane. Pass the vector of planes to the encode() function to correctly handle multi-planar formats (currently limited to NV12). Signed-off-by: Laurent Pinchart Acked-by: Umang Jain Tested-by: Umang Jain Reviewed-by: Hirokazu Honda --- src/android/jpeg/encoder_libjpeg.cpp | 18 +++++++++--------- src/android/jpeg/encoder_libjpeg.h | 8 +++++--- src/android/jpeg/post_processor_jpeg.cpp | 2 +- src/android/jpeg/thumbnailer.cpp | 4 ++-- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/android/jpeg/encoder_libjpeg.cpp b/src/android/jpeg/encoder_libjpeg.cpp index b8b01e20a001..7f63f36e793e 100644 --- a/src/android/jpeg/encoder_libjpeg.cpp +++ b/src/android/jpeg/encoder_libjpeg.cpp @@ -103,9 +103,9 @@ int EncoderLibJpeg::configure(const StreamConfiguration &cfg) return 0; } -void EncoderLibJpeg::compressRGB(Span frame) +void EncoderLibJpeg::compressRGB(const std::vector> &planes) { - unsigned char *src = const_cast(frame.data()); + unsigned char *src = const_cast(planes[0].data()); /* \todo Stride information should come from buffer configuration. */ unsigned int stride = pixelFormatInfo_->stride(compress_.image_width, 0); @@ -121,7 +121,7 @@ void EncoderLibJpeg::compressRGB(Span frame) * Compress the incoming buffer from a supported NV format. * This naively unpacks the semi-planar NV12 to a YUV888 format for libjpeg. */ -void EncoderLibJpeg::compressNV(Span frame) +void EncoderLibJpeg::compressNV(const std::vector> &planes) { uint8_t tmprowbuf[compress_.image_width * 3]; @@ -133,7 +133,6 @@ void EncoderLibJpeg::compressNV(Span frame) * Possible hints at: * https://sourceforge.net/p/libjpeg/mailman/message/30815123/ */ - unsigned int y_stride = pixelFormatInfo_->stride(compress_.image_width, 0); unsigned int c_stride = pixelFormatInfo_->stride(compress_.image_width, 1); unsigned int horzSubSample = 2 * compress_.image_width / c_stride; @@ -143,8 +142,8 @@ void EncoderLibJpeg::compressNV(Span frame) unsigned int cb_pos = nvSwap_ ? 1 : 0; unsigned int cr_pos = nvSwap_ ? 0 : 1; - const unsigned char *src = frame.data(); - const unsigned char *src_c = src + y_stride * compress_.image_height; + const unsigned char *src = planes[0].data(); + const unsigned char *src_c = planes[1].data(); JSAMPROW row_pointer[1]; row_pointer[0] = &tmprowbuf[0]; @@ -188,11 +187,12 @@ int EncoderLibJpeg::encode(const FrameBuffer &source, Span dest, return frame.error(); } - return encode(frame.planes()[0], dest, exifData, quality); + return encode(frame.planes(), dest, exifData, quality); } -int EncoderLibJpeg::encode(Span src, Span dest, - Span exifData, unsigned int quality) +int EncoderLibJpeg::encode(const std::vector> &src, + Span dest, Span exifData, + unsigned int quality) { unsigned char *destination = dest.data(); unsigned long size = dest.size(); diff --git a/src/android/jpeg/encoder_libjpeg.h b/src/android/jpeg/encoder_libjpeg.h index 61fbd1a69278..45ffbd7fae5d 100644 --- a/src/android/jpeg/encoder_libjpeg.h +++ b/src/android/jpeg/encoder_libjpeg.h @@ -9,6 +9,8 @@ #include "encoder.h" +#include + #include "libcamera/internal/formats.h" #include @@ -24,14 +26,14 @@ public: libcamera::Span destination, libcamera::Span exifData, unsigned int quality) override; - int encode(libcamera::Span source, + int encode(const std::vector> &planes, libcamera::Span destination, libcamera::Span exifData, unsigned int quality); private: - void compressRGB(libcamera::Span frame); - void compressNV(libcamera::Span frame); + void compressRGB(const std::vector> &planes); + void compressNV(const std::vector> &planes); struct jpeg_compress_struct compress_; struct jpeg_error_mgr jerr_; diff --git a/src/android/jpeg/post_processor_jpeg.cpp b/src/android/jpeg/post_processor_jpeg.cpp index 3160a784419c..68d74842925d 100644 --- a/src/android/jpeg/post_processor_jpeg.cpp +++ b/src/android/jpeg/post_processor_jpeg.cpp @@ -72,7 +72,7 @@ void PostProcessorJpeg::generateThumbnail(const FrameBuffer &source, */ thumbnail->resize(rawThumbnail.size()); - int jpeg_size = thumbnailEncoder_.encode(rawThumbnail, + int jpeg_size = thumbnailEncoder_.encode({ rawThumbnail }, *thumbnail, {}, quality); thumbnail->resize(jpeg_size); diff --git a/src/android/jpeg/thumbnailer.cpp b/src/android/jpeg/thumbnailer.cpp index 043c7b33f06a..2c341535de9e 100644 --- a/src/android/jpeg/thumbnailer.cpp +++ b/src/android/jpeg/thumbnailer.cpp @@ -62,8 +62,8 @@ void Thumbnailer::createThumbnail(const FrameBuffer &source, ASSERT(tw % 2 == 0 && th % 2 == 0); /* Image scaling block implementing nearest-neighbour algorithm. */ - unsigned char *src = static_cast(frame.planes()[0].data()); - unsigned char *srcC = src + sh * sw; + unsigned char *src = frame.planes()[0].data(); + unsigned char *srcC = frame.planes()[1].data(); unsigned char *srcCb, *srcCr; unsigned char *dstY, *srcY;