From patchwork Mon Jul 20 10:47:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8873 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 4E447C0109 for ; Mon, 20 Jul 2020 10:44:16 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1F029605B7; Mon, 20 Jul 2020 12:44:16 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D5F4460537 for ; Mon, 20 Jul 2020 12:44:13 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id A7C8060011; Mon, 20 Jul 2020 10:44:12 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:18 +0200 Message-Id: <20200720104736.19986-2-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 01/19] libcamera: ipu3: Rename mbusCodesToInfo 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 mbusCodesToInfo map actually maps media bus codes to PixelFormat instances. Rename the map according to its actual function and while at it drop the 'static' keyword as the map is already defined in an anonymous namespace. Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Reviewed-by: Kieran Bingham Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/cio2.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp index cb8c80a4a9ca..77f54da47e28 100644 --- a/src/libcamera/pipeline/ipu3/cio2.cpp +++ b/src/libcamera/pipeline/ipu3/cio2.cpp @@ -22,7 +22,7 @@ LOG_DECLARE_CATEGORY(IPU3) namespace { -static const std::map mbusCodesToInfo = { +const std::map mbusCodesToPixelFormat = { { MEDIA_BUS_FMT_SBGGR10_1X10, formats::SBGGR10_IPU3 }, { MEDIA_BUS_FMT_SGBRG10_1X10, formats::SGBRG10_IPU3 }, { MEDIA_BUS_FMT_SGRBG10_1X10, formats::SGRBG10_IPU3 }, @@ -94,7 +94,7 @@ int CIO2Device::init(const MediaDevice *media, unsigned int index) * utils::set_overlap requires the ranges to be sorted, keep the * cio2Codes vector sorted in ascending order. */ - std::vector cio2Codes = utils::map_keys(mbusCodesToInfo); + std::vector cio2Codes = utils::map_keys(mbusCodesToPixelFormat); const std::vector &sensorCodes = sensor_->mbusCodes(); if (!utils::set_overlap(sensorCodes.begin(), sensorCodes.end(), cio2Codes.begin(), cio2Codes.end())) { @@ -134,7 +134,7 @@ int CIO2Device::configure(const Size &size, V4L2DeviceFormat *outputFormat) * Apply the selected format to the sensor, the CSI-2 receiver and * the CIO2 output device. */ - std::vector mbusCodes = utils::map_keys(mbusCodesToInfo); + std::vector mbusCodes = utils::map_keys(mbusCodesToPixelFormat); sensorFormat = sensor_->getFormat(mbusCodes, size); ret = sensor_->setFormat(&sensorFormat); if (ret) @@ -144,8 +144,8 @@ int CIO2Device::configure(const Size &size, V4L2DeviceFormat *outputFormat) if (ret) return ret; - const auto &itInfo = mbusCodesToInfo.find(sensorFormat.mbus_code); - if (itInfo == mbusCodesToInfo.end()) + const auto &itInfo = mbusCodesToPixelFormat.find(sensorFormat.mbus_code); + if (itInfo == mbusCodesToPixelFormat.end()) return -EINVAL; const PixelFormatInfo &info = PixelFormatInfo::info(itInfo->second); @@ -173,7 +173,7 @@ CIO2Device::generateConfiguration(Size size) const size = sensor_->resolution(); /* Query the sensor static information for closest match. */ - std::vector mbusCodes = utils::map_keys(mbusCodesToInfo); + std::vector mbusCodes = utils::map_keys(mbusCodesToPixelFormat); V4L2SubdeviceFormat sensorFormat = sensor_->getFormat(mbusCodes, size); if (!sensorFormat.mbus_code) { LOG(IPU3, Error) << "Sensor does not support mbus code"; @@ -181,7 +181,7 @@ CIO2Device::generateConfiguration(Size size) const } cfg.size = sensorFormat.size; - cfg.pixelFormat = mbusCodesToInfo.at(sensorFormat.mbus_code); + cfg.pixelFormat = mbusCodesToPixelFormat.at(sensorFormat.mbus_code); cfg.bufferCount = CIO2_BUFFER_COUNT; return cfg; From patchwork Mon Jul 20 10:47:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8874 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 5ACC4C0109 for ; Mon, 20 Jul 2020 10:44:17 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7951160718; Mon, 20 Jul 2020 12:44:16 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8E23E60554 for ; Mon, 20 Jul 2020 12:44:14 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 0189D60002; Mon, 20 Jul 2020 10:44:13 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:19 +0200 Message-Id: <20200720104736.19986-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 02/19] libcamera: utils: Add alignUp and alignDown functions 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" Add to libcamera utils library two functions to round up or down a value to an alignment and add a test in test/utils.cpp for the two new functions. Reviewed-by: Laurent Pinchart Signed-off-by: Jacopo Mondi Reviewed-by: Niklas Söderlund Reviewed-by: Kieran Bingham --- include/libcamera/internal/utils.h | 10 ++++++++++ src/libcamera/utils.cpp | 16 ++++++++++++++++ test/utils.cpp | 11 +++++++++++ 3 files changed, 37 insertions(+) diff --git a/include/libcamera/internal/utils.h b/include/libcamera/internal/utils.h index 8d026cc6c0fe..45cd6f120c51 100644 --- a/include/libcamera/internal/utils.h +++ b/include/libcamera/internal/utils.h @@ -200,6 +200,16 @@ details::StringSplitter split(const std::string &str, const std::string &delim); std::string libcameraBuildPath(); std::string libcameraSourcePath(); +constexpr unsigned int alignDown(unsigned int value, unsigned int alignment) +{ + return value / alignment * alignment; +} + +constexpr unsigned int alignUp(unsigned int value, unsigned int alignment) +{ + return (value + alignment - 1) / alignment * alignment; +} + } /* namespace utils */ } /* namespace libcamera */ diff --git a/src/libcamera/utils.cpp b/src/libcamera/utils.cpp index 0567328fe31b..615df46ac142 100644 --- a/src/libcamera/utils.cpp +++ b/src/libcamera/utils.cpp @@ -444,6 +444,22 @@ std::string libcameraSourcePath() return path + "/"; } +/** + * \fn alignDown(unsigned int value, unsigned int alignment) + * \brief Align \a value down to \a alignment + * \param[in] value The value to align + * \param[in] alignment The alignment + * \return The value rounded down to the nearest multiple of \a alignment + */ + +/** + * \fn alignUp(unsigned int value, unsigned int alignment) + * \brief Align \a value up to \a alignment + * \param[in] value The value to align + * \param[in] alignment The alignment + * \return The value rounded up to the nearest multiple of \a alignment + */ + } /* namespace utils */ } /* namespace libcamera */ diff --git a/test/utils.cpp b/test/utils.cpp index f482e6a1d829..08f293898fd9 100644 --- a/test/utils.cpp +++ b/test/utils.cpp @@ -166,6 +166,17 @@ protected: return TestFail; } + /* utils::alignUp() and utils::alignDown() tests. */ + if (utils::alignDown(6, 3) != 6 || utils::alignDown(7, 3) != 6) { + cerr << "utils::alignDown test failed" << endl; + return TestFail; + } + + if (utils::alignUp(6, 3) != 6 || utils::alignUp(7, 3) != 9) { + cerr << "utils::alignUp test failed" << endl; + return TestFail; + } + return TestPass; } }; From patchwork Mon Jul 20 10:47:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8875 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 546AEC0109 for ; Mon, 20 Jul 2020 10:44:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 10B77605BB; Mon, 20 Jul 2020 12:44:19 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7BA1360537 for ; Mon, 20 Jul 2020 12:44:15 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id AE2BC60011; Mon, 20 Jul 2020 10:44:14 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:20 +0200 Message-Id: <20200720104736.19986-4-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 03/19] libcamera: geometry: Add isNull() function to Rectangle class 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" It's common for code to check if a rectangle is null. Add a helper function to do so and test the function in test/geometry.cpp Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- include/libcamera/geometry.h | 1 + src/libcamera/geometry.cpp | 6 ++++++ test/geometry.cpp | 14 ++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/include/libcamera/geometry.h b/include/libcamera/geometry.h index d858f85cf1f0..02fb63c08f60 100644 --- a/include/libcamera/geometry.h +++ b/include/libcamera/geometry.h @@ -181,6 +181,7 @@ public: unsigned int width; unsigned int height; + bool isNull() const { return !width && !height; } const std::string toString() const; }; diff --git a/src/libcamera/geometry.cpp b/src/libcamera/geometry.cpp index 23181bdec969..b12e1a62f939 100644 --- a/src/libcamera/geometry.cpp +++ b/src/libcamera/geometry.cpp @@ -385,6 +385,12 @@ bool operator==(const SizeRange &lhs, const SizeRange &rhs) * \brief The distance between the top and bottom sides */ +/** + * \fn bool Rectangle::isNull() const + * \brief Check if the rectangle is null + * \return True if both the width and height are 0, or false otherwise + */ + /** * \brief Assemble and return a string describing the rectangle * \return A string describing the Rectangle diff --git a/test/geometry.cpp b/test/geometry.cpp index 1a9fc1b8e3ed..08e268c9c312 100644 --- a/test/geometry.cpp +++ b/test/geometry.cpp @@ -182,6 +182,20 @@ protected: if (!compare(Size(200, 100), Size(100, 200), &operator>=, ">=", true)) return TestFail; + /* Test Rectangle::isNull(). */ + if (!Rectangle(0, 0, 0, 0).isNull() || + !Rectangle(1, 1, 0, 0).isNull()) { + cout << "Null rectangle incorrectly reported as not null" << endl; + return TestFail; + } + + if (Rectangle(0, 0, 0, 1).isNull() || + Rectangle(0, 0, 1, 0).isNull() || + Rectangle(0, 0, 1, 1).isNull()) { + cout << "Non-null rectangle incorrectly reported as null" << endl; + return TestFail; + } + return TestPass; } }; From patchwork Mon Jul 20 10:47:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8876 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 8A2FCC2E67 for ; Mon, 20 Jul 2020 10:44:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6382560724; Mon, 20 Jul 2020 12:44:19 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 64CE0605C6 for ; Mon, 20 Jul 2020 12:44:16 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 9B8396000B; Mon, 20 Jul 2020 10:44:15 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:21 +0200 Message-Id: <20200720104736.19986-5-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 04/19] libcamera: ipu3: Remove streams from generateConfiguration 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" Remove stream assignment from the IPU3 pipeline handler generateConfiguration() implementation. The function aims to provide a suitable default for the requested use cases. Defer stream assignment to validation and only initialize sizes and formats. Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/ipu3.cpp | 104 ++++++++------------------- 1 file changed, 30 insertions(+), 74 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index eb00eecfd10a..b1f804d60664 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -31,6 +31,15 @@ namespace libcamera { LOG_DEFINE_CATEGORY(IPU3) +static constexpr unsigned int IPU3_BUFFER_COUNT = 4; +static constexpr unsigned int IPU3_MAX_STREAMS = 3; +static const Size IMGU_OUTPUT_MIN_SIZE = { 2, 2 }; +static const Size IMGU_OUTPUT_MAX_SIZE = { 4480, 34004 }; +static constexpr unsigned int IMGU_OUTPUT_WIDTH_ALIGN = 64; +static constexpr unsigned int IMGU_OUTPUT_HEIGHT_ALIGN = 4; +static constexpr unsigned int IMGU_OUTPUT_WIDTH_MARGIN = 64; +static constexpr unsigned int IMGU_OUTPUT_HEIGHT_MARGIN = 32; + class IPU3CameraData : public CameraData { public: @@ -61,9 +70,6 @@ public: const std::vector &streams() { return streams_; } private: - static constexpr unsigned int IPU3_BUFFER_COUNT = 4; - static constexpr unsigned int IPU3_MAX_STREAMS = 3; - void assignStreams(); void adjustStream(StreamConfiguration &cfg, bool scale); @@ -299,94 +305,50 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, { IPU3CameraData *data = cameraData(camera); IPU3CameraConfiguration *config = new IPU3CameraConfiguration(camera, data); - std::set streams = { - &data->outStream_, - &data->vfStream_, - &data->rawStream_, - }; if (roles.empty()) return config; + Size sensorResolution = data->cio2_.sensor()->resolution(); for (const StreamRole role : roles) { StreamConfiguration cfg = {}; - Stream *stream = nullptr; - - cfg.pixelFormat = formats::NV12; switch (role) { case StreamRole::StillCapture: /* - * Pick the output stream by default as the Viewfinder - * and VideoRecording roles are not allowed on - * the output stream. - */ - if (streams.find(&data->outStream_) != streams.end()) { - stream = &data->outStream_; - } else if (streams.find(&data->vfStream_) != streams.end()) { - stream = &data->vfStream_; - } else { - LOG(IPU3, Error) - << "No stream available for requested role " - << role; - break; - } - - /* - * FIXME: Soraka: the maximum resolution reported by - * both sensors (2592x1944 for ov5670 and 4224x3136 for - * ov13858) are returned as default configurations but - * they're not correctly processed by the ImgU. - * Resolutions up tp 2560x1920 have been validated. - * - * \todo Clarify ImgU alignment requirements. + * Use as default full-frame configuration a value + * strictly smaller than the sensor resolution (limited + * to the ImgU maximum output size) and aligned down to + * the required frame margin. */ - cfg.size = { 2560, 1920 }; + cfg.size = sensorResolution.boundedTo(IMGU_OUTPUT_MAX_SIZE); + cfg.size.width = utils::alignDown(cfg.size.width - 1, + IMGU_OUTPUT_WIDTH_MARGIN); + cfg.size.height = utils::alignDown(cfg.size.height - 1, + IMGU_OUTPUT_HEIGHT_MARGIN); + cfg.pixelFormat = formats::NV12; + cfg.bufferCount = IPU3_BUFFER_COUNT; break; case StreamRole::StillCaptureRaw: { - if (streams.find(&data->rawStream_) == streams.end()) { - LOG(IPU3, Error) - << "Multiple raw streams are not supported"; - break; - } - - stream = &data->rawStream_; - - cfg.size = data->cio2_.sensor()->resolution(); + cfg = data->cio2_.generateConfiguration(sensorResolution); - cfg = data->cio2_.generateConfiguration(cfg.size); break; } case StreamRole::Viewfinder: case StreamRole::VideoRecording: { /* - * We can't use the 'output' stream for viewfinder or - * video capture roles. - * - * \todo This is an artificial limitation until we - * figure out the exact capabilities of the hardware. + * Default viewfinder and videorecording to 1280x720, + * capped to the maximum sensor resolution and aligned + * to the ImgU output constraints. */ - if (streams.find(&data->vfStream_) == streams.end()) { - LOG(IPU3, Error) - << "No stream available for requested role " - << role; - break; - } - - stream = &data->vfStream_; - - /* - * Align the default viewfinder size to the maximum - * available sensor resolution and to the IPU3 - * alignment constraints. - */ - const Size &res = data->cio2_.sensor()->resolution(); - unsigned int width = std::min(1280U, res.width); - unsigned int height = std::min(720U, res.height); - cfg.size = { width & ~7, height & ~3 }; + cfg.size = sensorResolution.boundedTo({ 1280, 720 }) + .alignedDownTo(IMGU_OUTPUT_WIDTH_ALIGN, + IMGU_OUTPUT_HEIGHT_ALIGN); + cfg.pixelFormat = formats::NV12; + cfg.bufferCount = IPU3_BUFFER_COUNT; break; } @@ -394,16 +356,10 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, default: LOG(IPU3, Error) << "Requested stream role not supported: " << role; - break; - } - - if (!stream) { delete config; return nullptr; } - streams.erase(stream); - config->addConfiguration(cfg); } From patchwork Mon Jul 20 10:47:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8877 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 2CD8AC0109 for ; Mon, 20 Jul 2020 10:44:20 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BBBBF6072E; Mon, 20 Jul 2020 12:44:19 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2FF4E60537 for ; Mon, 20 Jul 2020 12:44:17 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 7391360011; Mon, 20 Jul 2020 10:44:16 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:22 +0200 Message-Id: <20200720104736.19986-6-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 05/19] libcamera: ipu3: Make sure the config is valid 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" Inspect the return status of validate() in the IPU3 pipeline handler generateConfigurtion() implementation. If the generated configuration is not valid, return a an empty configuration to the application. Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/ipu3.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index b1f804d60664..f2d76551d369 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -363,7 +363,8 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, config->addConfiguration(cfg); } - config->validate(); + if (config->validate() == CameraConfiguration::Invalid) + return {}; return config; } From patchwork Mon Jul 20 10:47:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8878 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 6199FC0109 for ; Mon, 20 Jul 2020 10:44:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3A9CB605BF; Mon, 20 Jul 2020 12:44:22 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DFE9E60537 for ; Mon, 20 Jul 2020 12:44:17 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 52D6F6000B; Mon, 20 Jul 2020 10:44:17 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:23 +0200 Message-Id: <20200720104736.19986-7-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 06/19] libcamera: ipu3: cio2: Report format and sizes 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" Add two methods to the CIO2Device class to retrieve all the supported PixelFormats and sizes. Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi Acked-by: Laurent Pinchart --- src/libcamera/pipeline/ipu3/cio2.cpp | 40 ++++++++++++++++++++++++++++ src/libcamera/pipeline/ipu3/cio2.h | 5 ++++ 2 files changed, 45 insertions(+) diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp index 77f54da47e28..abe6d8a592d6 100644 --- a/src/libcamera/pipeline/ipu3/cio2.cpp +++ b/src/libcamera/pipeline/ipu3/cio2.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include "libcamera/internal/camera_sensor.h" @@ -43,6 +44,45 @@ CIO2Device::~CIO2Device() delete sensor_; } +/** + * \brief Retrieve the list of supported PixelFormats + * + * Retrieve the list of supported pixel formats by matching the sensor produced + * media bus codes with the formats supported by the CIO2 unit. + * + * \return The list of supported PixelFormat + */ +std::vector CIO2Device::formats() const +{ + if (!sensor_) + return {}; + + std::vector formats; + for (unsigned int code : sensor_->mbusCodes()) { + auto it = mbusCodesToPixelFormat.find(code); + if (it != mbusCodesToPixelFormat.end()) + formats.push_back(it->second); + } + + return formats; +} + +/** + * \brief Retrieve the list of supported size ranges + * \return The list of supported SizeRange + */ +std::vector CIO2Device::sizes() const +{ + if (!sensor_) + return {}; + + std::vector sizes; + for (const Size &size : sensor_->sizes()) + sizes.emplace_back(size, size); + + return sizes; +} + /** * \brief Initialize components of the CIO2 device with \a index * \param[in] media The CIO2 media device diff --git a/src/libcamera/pipeline/ipu3/cio2.h b/src/libcamera/pipeline/ipu3/cio2.h index 956355a0aa58..221cf817eee9 100644 --- a/src/libcamera/pipeline/ipu3/cio2.h +++ b/src/libcamera/pipeline/ipu3/cio2.h @@ -20,8 +20,10 @@ namespace libcamera { class CameraSensor; class FrameBuffer; class MediaDevice; +class PixelFormat; class Request; class Size; +class SizeRange; class V4L2Subdevice; struct StreamConfiguration; @@ -33,6 +35,9 @@ public: CIO2Device(); ~CIO2Device(); + std::vector formats() const; + std::vector sizes() const; + int init(const MediaDevice *media, unsigned int index); int configure(const Size &size, V4L2DeviceFormat *outputFormat); From patchwork Mon Jul 20 10:47:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8879 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 B9147C2E67 for ; Mon, 20 Jul 2020 10:44:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 783D060721; Mon, 20 Jul 2020 12:44:22 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BFEB060537 for ; Mon, 20 Jul 2020 12:44:18 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 0822860012; Mon, 20 Jul 2020 10:44:17 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:24 +0200 Message-Id: <20200720104736.19986-8-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 07/19] libcamera: ipu3: Do not overwrite StreamConfiguration 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 validate function overwrites the generated StreamConfiguration with the one reported by the CIO2 unit when inspecting the RAW stream configuration. As we prepare to add StreamFormats to the IPU3 StreamConfiguration, assigning to the CIO2 generated configuration would delete the StreamFormats. Fix this by updating relevant fields only in order to keep the assigned StreamFormats. Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/ipu3.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index f2d76551d369..b998c0722edc 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -270,7 +270,9 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate() const Stream *stream = streams_[i]; if (stream == &data_->rawStream_) { - cfg = cio2Configuration_; + cfg.size = cio2Configuration_.size; + cfg.pixelFormat = cio2Configuration_.pixelFormat; + cfg.bufferCount = cio2Configuration_.bufferCount; } else { bool scale = stream == &data_->vfStream_; adjustStream(config_[i], scale); From patchwork Mon Jul 20 10:47:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8880 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 33DDEC0109 for ; Mon, 20 Jul 2020 10:44:23 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 02A2E6073C; Mon, 20 Jul 2020 12:44:23 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A81766071C for ; Mon, 20 Jul 2020 12:44:19 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id E11E760013; Mon, 20 Jul 2020 10:44:18 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:25 +0200 Message-Id: <20200720104736.19986-9-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 08/19] libcamera: ipu3: Report StreamFormats 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" Report StreamFormats associated to each StreamConfiguration generated by the IPU3 pipeline handler. The StreamFormats are generated differently for RAW and processed streams, with the former using the sensor enumerated resolutions and the latter using a continuous range of sizes constructed by matching the sensor capabilities with the platform constraints. Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/ipu3.cpp | 45 +++++++++++++++++++--------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index b998c0722edc..27200a8cc811 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -313,7 +313,10 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, Size sensorResolution = data->cio2_.sensor()->resolution(); for (const StreamRole role : roles) { - StreamConfiguration cfg = {}; + std::map> streamFormats; + unsigned int bufferCount; + PixelFormat pixelFormat; + Size size; switch (role) { case StreamRole::StillCapture: @@ -323,18 +326,26 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, * to the ImgU maximum output size) and aligned down to * the required frame margin. */ - cfg.size = sensorResolution.boundedTo(IMGU_OUTPUT_MAX_SIZE); - cfg.size.width = utils::alignDown(cfg.size.width - 1, - IMGU_OUTPUT_WIDTH_MARGIN); - cfg.size.height = utils::alignDown(cfg.size.height - 1, - IMGU_OUTPUT_HEIGHT_MARGIN); - cfg.pixelFormat = formats::NV12; - cfg.bufferCount = IPU3_BUFFER_COUNT; + size = sensorResolution.boundedTo(IMGU_OUTPUT_MAX_SIZE); + size.width = utils::alignDown(size.width - 1, + IMGU_OUTPUT_WIDTH_MARGIN); + size.height = utils::alignDown(size.height - 1, + IMGU_OUTPUT_HEIGHT_MARGIN); + pixelFormat = formats::NV12; + bufferCount = IPU3_BUFFER_COUNT; + streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } }; break; case StreamRole::StillCaptureRaw: { - cfg = data->cio2_.generateConfiguration(sensorResolution); + StreamConfiguration cio2Config = + data->cio2_.generateConfiguration(sensorResolution); + pixelFormat = cio2Config.pixelFormat; + size = cio2Config.size; + bufferCount = cio2Config.bufferCount; + + for (const PixelFormat &format : data->cio2_.formats()) + streamFormats[format] = data->cio2_.sizes(); break; } @@ -346,11 +357,12 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, * capped to the maximum sensor resolution and aligned * to the ImgU output constraints. */ - cfg.size = sensorResolution.boundedTo({ 1280, 720 }) - .alignedDownTo(IMGU_OUTPUT_WIDTH_ALIGN, - IMGU_OUTPUT_HEIGHT_ALIGN); - cfg.pixelFormat = formats::NV12; - cfg.bufferCount = IPU3_BUFFER_COUNT; + size = sensorResolution.boundedTo({ 1280, 720 }) + .alignedDownTo(IMGU_OUTPUT_WIDTH_ALIGN, + IMGU_OUTPUT_HEIGHT_ALIGN); + pixelFormat = formats::NV12; + bufferCount = IPU3_BUFFER_COUNT; + streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } }; break; } @@ -362,6 +374,11 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, return nullptr; } + StreamFormats formats(streamFormats); + StreamConfiguration cfg(formats); + cfg.size = size; + cfg.pixelFormat = pixelFormat; + cfg.bufferCount = bufferCount; config->addConfiguration(cfg); } From patchwork Mon Jul 20 10:47:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8881 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 943BBC2E67 for ; Mon, 20 Jul 2020 10:44:23 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5700F605BB; Mon, 20 Jul 2020 12:44:23 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 99025605C3 for ; Mon, 20 Jul 2020 12:44:20 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id C78E360011; Mon, 20 Jul 2020 10:44:19 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:26 +0200 Message-Id: <20200720104736.19986-10-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 09/19] libcamera: ipu3: Remove initialization of Size 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 Size struct constructor defaults the width and height to 0. Remove the empty braced-list initialization as it is not required. Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/ipu3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 27200a8cc811..bf7e349c9107 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -246,7 +246,7 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate() * only. If no resolution is requested for any stream, or if no sensor * resolution is large enough, pick the largest one. */ - Size size = {}; + Size size; for (const StreamConfiguration &cfg : config_) { if (cfg.size.width > size.width) From patchwork Mon Jul 20 10:47:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8882 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 2AC86C0109 for ; Mon, 20 Jul 2020 10:44:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 01DBF60744; Mon, 20 Jul 2020 12:44:26 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7C8E7605BB for ; Mon, 20 Jul 2020 12:44:21 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id BFAEE6000B; Mon, 20 Jul 2020 10:44:20 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:27 +0200 Message-Id: <20200720104736.19986-11-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 10/19] libcamera: ipu3: Validate the stream combination 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 IPU3 pipeline handler supports 2 processed RGB/YUV streams and one RAW stream. Validate that the requested stream combination is supported in the pipeline handler validate() implementation and return an error in case it's not. Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/ipu3.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index bf7e349c9107..6eaba401d68e 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -241,20 +241,35 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate() } /* - * Select the sensor format by collecting the maximum width and height - * and picking the closest larger match, as the IPU3 can downscale - * only. If no resolution is requested for any stream, or if no sensor - * resolution is large enough, pick the largest one. + * Validate the requested stream configuration and select the sensor + * format by collecting the maximum width and height and picking the + * closest larger match, as the IPU3 can downscale only. If no + * resolution is requested for any stream, or if no sensor resolution is + * large enough, pick the largest one. */ + unsigned int rawCount = 0; + unsigned int yuvCount = 0; Size size; for (const StreamConfiguration &cfg : config_) { + const PixelFormatInfo &info = PixelFormatInfo::info(cfg.pixelFormat); + + if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) + rawCount++; + else + yuvCount++; + if (cfg.size.width > size.width) size.width = cfg.size.width; if (cfg.size.height > size.height) size.height = cfg.size.height; } + if (rawCount > 1 || yuvCount > 2) { + LOG(IPU3, Debug) << "Camera configuration not supported"; + return Invalid; + } + /* Generate raw configuration from CIO2. */ cio2Configuration_ = data_->cio2_.generateConfiguration(size); if (!cio2Configuration_.pixelFormat.isValid()) From patchwork Mon Jul 20 10:47:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8883 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 58D21C2E67 for ; Mon, 20 Jul 2020 10:44:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2E2B460746; Mon, 20 Jul 2020 12:44:26 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5D6B260716 for ; Mon, 20 Jul 2020 12:44:22 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 97B8E60013; Mon, 20 Jul 2020 10:44:21 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:28 +0200 Message-Id: <20200720104736.19986-12-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 11/19] libcamera: camera: Zero streams before validate() 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 current implementation of the Camera::configure() method zeroes the stream pointers assigned to the StreamConfiguration items before calling the pipeline handler configure() operation, just after the CameraConfiguration has been validated. This discards the stream assignment performed at pipeline hander validation time, requiring platforms that need to perform that early assignment to maintain the association in place with custom data structures. To allow pipeline handlers to use StreamConfiguration::setStream() at validate() time, zero the stream assignment before calling validate(). Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- src/libcamera/camera.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index 69a1b4428e3f..ca88c48b2830 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -753,6 +753,9 @@ int Camera::configure(CameraConfiguration *config) if (ret < 0) return ret; + for (auto it : *config) + it.setStream(nullptr); + if (config->validate() != CameraConfiguration::Valid) { LOG(Camera, Error) << "Can't configure camera with invalid configuration"; @@ -763,7 +766,6 @@ int Camera::configure(CameraConfiguration *config) for (unsigned int index = 0; index < config->size(); ++index) { StreamConfiguration &cfg = config->at(index); - cfg.setStream(nullptr); msg << " (" << index << ") " << cfg.toString(); } From patchwork Mon Jul 20 10:47:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8884 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 E9040C0109 for ; Mon, 20 Jul 2020 10:44:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9A75760729; Mon, 20 Jul 2020 12:44:26 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 21EF66073E for ; Mon, 20 Jul 2020 12:44:23 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 7FF8360012; Mon, 20 Jul 2020 10:44:22 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:29 +0200 Message-Id: <20200720104736.19986-13-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 12/19] libcamera: ipu3: cio2: Add a const sensor() method 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" Add a const version of the CIO2Device::sensor() method, that retrieves a const pointer to the sensor_ class member, to be called by users which only own a const reference to a CIO2Device class instance. Reviewed-by: Laurent Pinchart Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/cio2.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcamera/pipeline/ipu3/cio2.h b/src/libcamera/pipeline/ipu3/cio2.h index 221cf817eee9..fa813a989fd2 100644 --- a/src/libcamera/pipeline/ipu3/cio2.h +++ b/src/libcamera/pipeline/ipu3/cio2.h @@ -50,6 +50,7 @@ public: int stop(); CameraSensor *sensor() { return sensor_; } + const CameraSensor *sensor() const { return sensor_; } int queueBuffer(Request *request, FrameBuffer *rawBuffer); void tryReturnBuffer(FrameBuffer *buffer); From patchwork Mon Jul 20 10:47:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8885 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 78173C0109 for ; Mon, 20 Jul 2020 10:44:27 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 33E40605BD; Mon, 20 Jul 2020 12:44:27 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AF8EF6071C for ; Mon, 20 Jul 2020 12:44:23 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 43FAA60013; Mon, 20 Jul 2020 10:44:23 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:30 +0200 Message-Id: <20200720104736.19986-14-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 13/19] libcamera: ipu3: Adjust and assign streams in validate() 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" Remove the adjustStream() and assignStream() methods, and perform stream adjustment and assignment while iterating the StreamConfiguration items. The adjustStream() implementation had some arbitrary assumption, like the main output having to be as large as the sensor resolution, and did not take into account the different alignment requirements between the main output and the viewfinder output. The assignStream() implementation also assumes only full-size streams can be produced by the main output, and having it as a separate function prevents adjusting streams according to which output they are assigned. Blend the two implementation in a single loop and perform the required stream adjustment and assignment in one go. As streams are now assigned at validate() time, remove the same operation from the configure() function. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/libcamera/pipeline/ipu3/ipu3.cpp | 250 ++++++++++++--------------- 1 file changed, 111 insertions(+), 139 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 6eaba401d68e..24ad37eb1831 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -70,9 +70,6 @@ public: const std::vector &streams() { return streams_; } private: - void assignStreams(); - void adjustStream(StreamConfiguration &cfg, bool scale); - /* * The IPU3CameraData instance is guaranteed to be valid as long as the * corresponding Camera instance is valid. In order to borrow a @@ -137,96 +134,6 @@ IPU3CameraConfiguration::IPU3CameraConfiguration(Camera *camera, data_ = data; } -void IPU3CameraConfiguration::assignStreams() -{ - /* - * Verify and update all configuration entries, and assign a stream to - * each of them. The viewfinder stream can scale, while the output - * stream can crop only, so select the output stream when the requested - * resolution is equal to the sensor resolution, and the viewfinder - * stream otherwise. - */ - std::set availableStreams = { - &data_->outStream_, - &data_->vfStream_, - &data_->rawStream_, - }; - - /* - * The caller is responsible to limit the number of requested streams - * to a number supported by the pipeline before calling this function. - */ - ASSERT(availableStreams.size() >= config_.size()); - - streams_.clear(); - streams_.reserve(config_.size()); - - for (const StreamConfiguration &cfg : config_) { - const PixelFormatInfo &info = - PixelFormatInfo::info(cfg.pixelFormat); - const Stream *stream; - - if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) - stream = &data_->rawStream_; - else if (cfg.size == cio2Configuration_.size) - stream = &data_->outStream_; - else - stream = &data_->vfStream_; - - if (availableStreams.find(stream) == availableStreams.end()) - stream = *availableStreams.begin(); - - streams_.push_back(stream); - availableStreams.erase(stream); - } -} - -void IPU3CameraConfiguration::adjustStream(StreamConfiguration &cfg, bool scale) -{ - /* The only pixel format the driver supports is NV12. */ - cfg.pixelFormat = formats::NV12; - - if (scale) { - /* - * Provide a suitable default that matches the sensor aspect - * ratio. - */ - if (cfg.size.isNull()) { - cfg.size.width = 1280; - cfg.size.height = 1280 * cio2Configuration_.size.height - / cio2Configuration_.size.width; - } - - /* - * \todo: Clamp the size to the hardware bounds when we will - * figure them out. - * - * \todo: Handle the scaler (BDS) restrictions. The BDS can - * only scale with the same factor in both directions, and the - * scaling factor is limited to a multiple of 1/32. At the - * moment the ImgU driver hides these constraints by applying - * additional cropping, this should be fixed on the driver - * side, and cropping should be exposed to us. - */ - } else { - /* - * \todo: Properly support cropping when the ImgU driver - * interface will be cleaned up. - */ - cfg.size = cio2Configuration_.size; - } - - /* - * Clamp the size to match the ImgU alignment constraints. The width - * shall be a multiple of 8 pixels and the height a multiple of 4 - * pixels. - */ - if (cfg.size.width % 8 || cfg.size.height % 4) { - cfg.size.width &= ~7; - cfg.size.height &= ~3; - } -} - CameraConfiguration::Status IPU3CameraConfiguration::validate() { Status status = Valid; @@ -242,27 +149,27 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate() /* * Validate the requested stream configuration and select the sensor - * format by collecting the maximum width and height and picking the - * closest larger match, as the IPU3 can downscale only. If no - * resolution is requested for any stream, or if no sensor resolution is - * large enough, pick the largest one. + * format by collecting the maximum RAW stream width and height and + * picking the closest larger match, as the IPU3 can downscale only. If + * no resolution is requested for the RAW stream, use the one from the + * largest YUV stream, plus margins pixels for the IF and BDS to scale. + * If no resolution is requested for any stream, pick the largest one. */ unsigned int rawCount = 0; unsigned int yuvCount = 0; - Size size; + Size maxYuvSize; + Size maxRawSize; for (const StreamConfiguration &cfg : config_) { const PixelFormatInfo &info = PixelFormatInfo::info(cfg.pixelFormat); - if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) + if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) { rawCount++; - else + maxRawSize.expandTo(cfg.size); + } else { yuvCount++; - - if (cfg.size.width > size.width) - size.width = cfg.size.width; - if (cfg.size.height > size.height) - size.height = cfg.size.height; + maxYuvSize.expandTo(cfg.size); + } } if (rawCount > 1 || yuvCount > 2) { @@ -270,43 +177,113 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate() return Invalid; } - /* Generate raw configuration from CIO2. */ - cio2Configuration_ = data_->cio2_.generateConfiguration(size); + if (maxRawSize.isNull()) + maxRawSize = maxYuvSize.alignedUpTo(IMGU_OUTPUT_WIDTH_MARGIN, + IMGU_OUTPUT_HEIGHT_MARGIN) + .boundedTo(data_->cio2_.sensor()->resolution()); + + /* + * Generate raw configuration from CIO2. + * + * The output YUV streams will be limited in size to the maximum + * frame size requested for the RAW stream. + */ + cio2Configuration_ = data_->cio2_.generateConfiguration(maxRawSize); if (!cio2Configuration_.pixelFormat.isValid()) return Invalid; - /* Assign streams to each configuration entry. */ - assignStreams(); + LOG(IPU3, Debug) << "CIO2 configuration: " << cio2Configuration_.toString(); - /* Verify and adjust configuration if needed. */ + /* + * Adjust the configurations if needed and assign streams while + * iterating them. + */ + bool mainOutputAvailable = true; for (unsigned int i = 0; i < config_.size(); ++i) { - StreamConfiguration &cfg = config_[i]; - const StreamConfiguration oldCfg = cfg; - const Stream *stream = streams_[i]; - - if (stream == &data_->rawStream_) { - cfg.size = cio2Configuration_.size; - cfg.pixelFormat = cio2Configuration_.pixelFormat; - cfg.bufferCount = cio2Configuration_.bufferCount; + const PixelFormatInfo &info = PixelFormatInfo::info(config_[i].pixelFormat); + const StreamConfiguration originalCfg = config_[i]; + StreamConfiguration *cfg = &config_[i]; + + LOG(IPU3, Debug) << "Validating stream: " << config_[i].toString(); + + if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) { + /* Initialize the RAW stream with the CIO2 configuration. */ + cfg->size = cio2Configuration_.size; + cfg->pixelFormat = cio2Configuration_.pixelFormat; + cfg->bufferCount = cio2Configuration_.bufferCount; + cfg->stride = info.stride(cfg->size.width, 0, 64); + cfg->frameSize = info.frameSize(cfg->size, 64); + cfg->setStream(const_cast(&data_->rawStream_)); + + LOG(IPU3, Debug) << "Assigned " << cfg->toString() + << " to the raw stream"; } else { - bool scale = stream == &data_->vfStream_; - adjustStream(config_[i], scale); - cfg.bufferCount = IPU3_BUFFER_COUNT; + /* Assign and configure the main and viewfinder outputs. */ + + /* + * Clamp the size to match the ImgU size limits and the + * margins from the CIO2 output frame size. + * + * The ImgU outputs needs to be strictly smaller than + * the CIO2 output frame and rounded down to 64 + * pixels in width and 32 pixels in height. This comes + * from inspecting the pipe configuration script results + * and the available suggested configurations in the + * ChromeOS BSP .xml camera tuning files. + * + * \todo Clarify what are the hardware constraints + * that require this alignements, if any. It might + * depend on the BDS scaling factor of 1/32, as the main + * output has no YUV scaler as the viewfinder output has. + */ + unsigned int limit; + limit = utils::alignDown(cio2Configuration_.size.width - 1, + IMGU_OUTPUT_WIDTH_MARGIN); + cfg->size.width = utils::clamp(cfg->size.width, + IMGU_OUTPUT_MIN_SIZE.width, + limit); + + limit = utils::alignDown(cio2Configuration_.size.height - 1, + IMGU_OUTPUT_HEIGHT_MARGIN); + cfg->size.height = utils::clamp(cfg->size.height, + IMGU_OUTPUT_MIN_SIZE.height, + limit); + + cfg->size.alignDownTo(IMGU_OUTPUT_WIDTH_ALIGN, + IMGU_OUTPUT_HEIGHT_ALIGN); + + cfg->pixelFormat = formats::NV12; + cfg->bufferCount = IPU3_BUFFER_COUNT; + cfg->stride = info.stride(cfg->size.width, 0, 1); + cfg->frameSize = info.frameSize(cfg->size, 1); + + /* + * Use the main output stream in case only one stream is + * requested or if the current configuration is the one + * with the maximum YUV output size. + */ + if (mainOutputAvailable && + (originalCfg.size == maxYuvSize || yuvCount == 1)) { + cfg->setStream(const_cast(&data_->outStream_)); + mainOutputAvailable = false; + + LOG(IPU3, Debug) << "Assigned " << cfg->toString() + << " to the main output"; + } else { + cfg->setStream(const_cast(&data_->vfStream_)); + + LOG(IPU3, Debug) << "Assigned " << cfg->toString() + << " to the viewfinder output"; + } } - if (cfg.pixelFormat != oldCfg.pixelFormat || - cfg.size != oldCfg.size) { + if (cfg->pixelFormat != originalCfg.pixelFormat || + cfg->size != originalCfg.size) { LOG(IPU3, Debug) << "Stream " << i << " configuration adjusted to " - << cfg.toString(); + << cfg->toString(); status = Adjusted; } - - const PixelFormatInfo &info = PixelFormatInfo::info(cfg.pixelFormat); - bool packedRaw = info.colourEncoding == PixelFormatInfo::ColourEncodingRAW; - - cfg.stride = info.stride(cfg.size.width, 0, packedRaw ? 64 : 1); - cfg.frameSize = info.frameSize(cfg.size, packedRaw ? 64 : 1); } return status; @@ -340,6 +317,9 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, * strictly smaller than the sensor resolution (limited * to the ImgU maximum output size) and aligned down to * the required frame margin. + * + * The alignment constraints should be clarified + * as per the todo item in validate(). */ size = sensorResolution.boundedTo(IMGU_OUTPUT_MAX_SIZE); size.width = utils::alignDown(size.width - 1, @@ -476,16 +456,8 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) bool vfActive = false; for (unsigned int i = 0; i < config->size(); ++i) { - /* - * Use a const_cast<> here instead of storing a mutable stream - * pointer in the configuration to let the compiler catch - * unwanted modifications of camera data in the configuration - * validate() implementation. - */ - Stream *stream = const_cast(config->streams()[i]); StreamConfiguration &cfg = (*config)[i]; - - cfg.setStream(stream); + Stream *stream = cfg.stream(); if (stream == outStream) { ret = imgu->configureOutput(cfg, &outputFormat); From patchwork Mon Jul 20 10:47:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8886 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 0A033C0109 for ; Mon, 20 Jul 2020 10:44:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B7B8C60744; Mon, 20 Jul 2020 12:44:27 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 89914605B7 for ; Mon, 20 Jul 2020 12:44:24 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id C9CD460011; Mon, 20 Jul 2020 10:44:23 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:31 +0200 Message-Id: <20200720104736.19986-15-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 14/19] libcamera: ipu3: Remove streams from IPU3CameraConfiguration 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 IPU3CameraConfiguration::streams_ field was used to keep an association between the StreamConfiguration and the assigned streams before CameraConfiguration::setStream() was called at configure() time. The stream assignment was based on the order in which elements were inserted in the vector, implementing a fragile association between streams and their intended configurations. As it is now possible to assign streams at validation time, there is no need to keep that association in place, and the streams_ vector is now unused. Remove it and the associated accessor method from the IPU3CameraConfiguration class. Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/ipu3.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 24ad37eb1831..08e3fcb5af15 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -67,7 +67,6 @@ public: Status validate() override; const StreamConfiguration &cio2Format() const { return cio2Configuration_; }; - const std::vector &streams() { return streams_; } private: /* @@ -79,7 +78,6 @@ private: const IPU3CameraData *data_; StreamConfiguration cio2Configuration_; - std::vector streams_; }; class PipelineHandlerIPU3 : public PipelineHandler From patchwork Mon Jul 20 10:47:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8887 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 6491DC0109 for ; Mon, 20 Jul 2020 10:44:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3FF616073E; Mon, 20 Jul 2020 12:44:30 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6B35060554 for ; Mon, 20 Jul 2020 12:44:25 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id A981D60012; Mon, 20 Jul 2020 10:44:24 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:32 +0200 Message-Id: <20200720104736.19986-16-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 15/19] libcamera: ipu3: Remove camera_ from IPU3CameraConfiguration 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 IPU3CameraConfiguration::camera_ shared pointer is not used. Remove it. Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/ipu3.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 08e3fcb5af15..0379fb7b92a7 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -62,7 +62,7 @@ public: class IPU3CameraConfiguration : public CameraConfiguration { public: - IPU3CameraConfiguration(Camera *camera, IPU3CameraData *data); + IPU3CameraConfiguration(IPU3CameraData *data); Status validate() override; @@ -74,7 +74,6 @@ private: * corresponding Camera instance is valid. In order to borrow a * reference to the camera data, store a new reference to the camera. */ - std::shared_ptr camera_; const IPU3CameraData *data_; StreamConfiguration cio2Configuration_; @@ -124,11 +123,9 @@ private: MediaDevice *imguMediaDev_; }; -IPU3CameraConfiguration::IPU3CameraConfiguration(Camera *camera, - IPU3CameraData *data) +IPU3CameraConfiguration::IPU3CameraConfiguration(IPU3CameraData *data) : CameraConfiguration() { - camera_ = camera->shared_from_this(); data_ = data; } @@ -296,7 +293,7 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, const StreamRoles &roles) { IPU3CameraData *data = cameraData(camera); - IPU3CameraConfiguration *config = new IPU3CameraConfiguration(camera, data); + IPU3CameraConfiguration *config = new IPU3CameraConfiguration(data); if (roles.empty()) return config; From patchwork Mon Jul 20 10:47:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8888 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 88D95C2E67 for ; Mon, 20 Jul 2020 10:44:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 60017607DE; Mon, 20 Jul 2020 12:44:30 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3C87C607BD for ; Mon, 20 Jul 2020 12:44:26 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 89E5B60002; Mon, 20 Jul 2020 10:44:25 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:33 +0200 Message-Id: <20200720104736.19986-17-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 16/19] libcamera: ipu3: imgu: Calculate ImgU pipe configuration 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" Instrument the ImgU component to dynamically calculate the image manipulation pipeline intermediate sizes. To correctly configure the ImgU it is necessary to program the IF, BDS and GDC sizes, which are currently fixed to the input frame size. The procedure used to calculate the intermediate sizes has been ported from the pipe_config.py python script, available at: https://github.com/intel/intel-ipu3-pipecfg at revision: 61e83f2f7606 ("Add more information into README") Define two structures (ImgUDevice::Pipe and ImgUDevice::PipeConfig) to allow the pipeline handler to supply and retrieve configuration parameters from the ImgU. Finally, add a new operation to the ImgUDevice that calculates the pipe configuration parameters based on the requested input and output sizes. Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi Acked-by: Laurent Pinchart --- src/libcamera/pipeline/ipu3/imgu.cpp | 349 +++++++++++++++++++++++++++ src/libcamera/pipeline/ipu3/imgu.h | 20 ++ 2 files changed, 369 insertions(+) diff --git a/src/libcamera/pipeline/ipu3/imgu.cpp b/src/libcamera/pipeline/ipu3/imgu.cpp index 4bec4b2f1a76..17b749435ee2 100644 --- a/src/libcamera/pipeline/ipu3/imgu.cpp +++ b/src/libcamera/pipeline/ipu3/imgu.cpp @@ -7,6 +7,9 @@ #include "imgu.h" +#include +#include + #include #include @@ -14,11 +17,300 @@ #include "libcamera/internal/log.h" #include "libcamera/internal/media_device.h" +#include "libcamera/internal/utils.h" namespace libcamera { LOG_DECLARE_CATEGORY(IPU3) +namespace { + +static constexpr unsigned int FILTER_H = 4; + +static constexpr unsigned int IF_ALIGN_W = 2; +static constexpr unsigned int IF_ALIGN_H = 4; + +static constexpr unsigned int BDS_ALIGN_W = 2; +static constexpr unsigned int BDS_ALIGN_H = 4; + +static constexpr unsigned int IF_CROP_MAX_W = 40; +static constexpr unsigned int IF_CROP_MAX_H = 540; + +static constexpr float BDS_SF_MAX = 2.5; +static constexpr float BDS_SF_MIN = 1.0; +static constexpr float BDS_SF_STEP = 0.03125; + +/* BSD scaling factors: min=1, max=2.5, step=1/32 */ +const std::vector bdsScalingFactors = { + 1, 1.03125, 1.0625, 1.09375, 1.125, 1.15625, 1.1875, 1.21875, 1.25, + 1.28125, 1.3125, 1.34375, 1.375, 1.40625, 1.4375, 1.46875, 1.5, 1.53125, + 1.5625, 1.59375, 1.625, 1.65625, 1.6875, 1.71875, 1.75, 1.78125, 1.8125, + 1.84375, 1.875, 1.90625, 1.9375, 1.96875, 2, 2.03125, 2.0625, 2.09375, + 2.125, 2.15625, 2.1875, 2.21875, 2.25, 2.28125, 2.3125, 2.34375, 2.375, + 2.40625, 2.4375, 2.46875, 2.5 +}; + +/* GDC scaling factors: min=1, max=16, step=1/4 */ +const std::vector gdcScalingFactors = { + 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.25, 3.5, 3.75, 4, 4.25, + 4.5, 4.75, 5, 5.25, 5.5, 5.75, 6, 6.25, 6.5, 6.75, 7, 7.25, 7.5, 7.75, + 8, 8.25, 8.5, 8.75, 9, 9.25, 9.5, 9.75, 10, 10.25, 10.5, 10.75, 11, + 11.25, 11.5, 11.75, 12, 12.25, 12.5, 12.75, 13, 13.25, 13.5, 13.75, 14, + 14.25, 14.5, 14.75, 15, 15.25, 15.5, 15.75, 16, +}; + +std::vector pipeConfigs; + +struct FOV { + float w; + float h; + + bool isLarger(const FOV &other) + { + if (w > other.w) + return true; + if (w == other.w && h > other.h) + return true; + return false; + } +}; + +/* Approximate a scaling factor sf to the closest one available in a range. */ +float findScaleFactor(float sf, const std::vector &range, + bool roundDown = false) +{ + if (sf <= range[0]) + return range[0]; + if (sf >= range[range.size() - 1]) + return range[range.size() - 1]; + + + float bestDiff = std::numeric_limits::max(); + unsigned int index = 0; + for (unsigned int i = 0; i < range.size(); ++i) { + float diff = std::abs(sf - range[i]); + if (diff < bestDiff) { + bestDiff = diff; + index = i; + } + } + + if (roundDown && index > 0 && sf < range[index]) + index--; + + return range[index]; +} + +bool isSameRatio(const Size &in, const Size &out) +{ + float inRatio = static_cast(in.width) / + static_cast(in.height); + float outRatio = static_cast(out.width) / + static_cast(out.height); + + if (std::abs(inRatio - outRatio) > 0.1) + return false; + + return true; +} + +void calculateBDSHeight(ImgUDevice::Pipe *pipe, const Size &iif, const Size &gdc, + unsigned int bdsWidth, float bdsSF) +{ + unsigned int minIFHeight = iif.height - IF_CROP_MAX_H; + unsigned int minBDSHeight = gdc.height + FILTER_H * 2; + unsigned int ifHeight; + float bdsHeight; + + if (!isSameRatio(pipe->input, gdc)) { + bool found = false; + float estIFHeight = static_cast(iif.width * gdc.height) / + static_cast(gdc.width); + estIFHeight = utils::clamp(estIFHeight, minIFHeight, iif.height); + ifHeight = utils::alignUp(estIFHeight, IF_ALIGN_H); + while (ifHeight >= minIFHeight && + static_cast(ifHeight) / bdsSF >= minBDSHeight) { + bdsHeight = static_cast(ifHeight) / bdsSF; + if (std::fmod(bdsHeight, 1.0) == 0) { + unsigned int bdsIntHeight = static_cast(bdsHeight); + if (!(bdsIntHeight % BDS_ALIGN_H)) { + found = true; + break; + } + } + + ifHeight -= IF_ALIGN_H; + } + + ifHeight = utils::alignUp(estIFHeight, IF_ALIGN_H); + while (ifHeight <= iif.height && + static_cast(ifHeight) / bdsSF >= minBDSHeight) { + bdsHeight = static_cast(ifHeight) / bdsSF; + if (std::fmod(bdsHeight, 1.0) == 0) { + unsigned int bdsIntHeight = static_cast(bdsHeight); + if (!(bdsIntHeight % BDS_ALIGN_H)) { + found = true; + break; + } + } + + ifHeight += IF_ALIGN_H; + } + + if (found) { + unsigned int bdsIntHeight = static_cast(bdsHeight); + pipeConfigs.push_back({ bdsSF, { iif.width, ifHeight }, + { bdsWidth, bdsIntHeight }, gdc }); + return; + } + } else { + ifHeight = utils::alignUp(iif.height, IF_ALIGN_H); + while (ifHeight > minIFHeight && + static_cast(ifHeight) / bdsSF >= minBDSHeight) { + bdsHeight = ifHeight / bdsSF; + if (std::fmod(ifHeight, 1.0) == 0 && std::fmod(bdsHeight, 1.0) == 0) { + unsigned int bdsIntHeight = static_cast(bdsHeight); + + if (!(ifHeight % IF_ALIGN_H) && + !(bdsIntHeight % BDS_ALIGN_H)) { + pipeConfigs.push_back({ bdsSF, { iif.width, ifHeight }, + { bdsWidth, bdsIntHeight }, gdc }); + } + } + + ifHeight -= IF_ALIGN_H; + } + } +} + +void calculateBDS(ImgUDevice::Pipe *pipe, const Size &iif, const Size &gdc, + float bdsSF) +{ + unsigned int minBDSWidth = gdc.width + FILTER_H * 2; + + float sf = bdsSF; + while (sf <= BDS_SF_MAX && sf >= BDS_SF_MIN) { + float bdsWidth = static_cast(iif.width) / sf; + + if (std::fmod(bdsWidth, 1.0) == 0) { + unsigned int bdsIntWidth = static_cast(bdsWidth); + if (!(bdsIntWidth % BDS_ALIGN_W) && bdsWidth >= minBDSWidth) + calculateBDSHeight(pipe, iif, gdc, bdsIntWidth, sf); + } + + sf += BDS_SF_STEP; + } + + sf = bdsSF; + while (sf <= BDS_SF_MAX && sf >= BDS_SF_MIN) { + float bdsWidth = static_cast(iif.width) / sf; + + if (std::fmod(bdsWidth, 1.0) == 0) { + unsigned int bdsIntWidth = static_cast(bdsWidth); + if (!(bdsIntWidth % BDS_ALIGN_W) && bdsWidth >= minBDSWidth) + calculateBDSHeight(pipe, iif, gdc, bdsIntWidth, sf); + } + + sf -= BDS_SF_STEP; + } +} + +Size calculateGDC(ImgUDevice::Pipe *pipe) +{ + const Size &in = pipe->input; + const Size &main = pipe->output; + const Size &vf = pipe->viewfinder; + Size gdc; + + if (!vf.isNull()) { + gdc.width = main.width; + + float ratio = static_cast(main.width * vf.height) / + static_cast(vf.width); + gdc.height = std::max(static_cast(main.height), ratio); + + return gdc; + } + + if (!isSameRatio(in, main)) { + gdc = main; + return gdc; + } + + float totalSF = static_cast(in.width) / + static_cast(main.width); + float bdsSF = totalSF > 2 ? 2 : 1; + float yuvSF = totalSF / bdsSF; + float sf = findScaleFactor(yuvSF, gdcScalingFactors); + + gdc.width = static_cast(main.width) * sf; + gdc.height = static_cast(main.height) * sf; + + return gdc; +} + +FOV calcFOV(const Size &in, const ImgUDevice::PipeConfig &pipe) +{ + FOV fov{}; + + float inW = static_cast(in.width); + float inH = static_cast(in.height); + float ifCropW = static_cast(in.width - pipe.iif.width); + float ifCropH = static_cast(in.height - pipe.iif.height); + float gdcCropW = static_cast(pipe.bds.width - pipe.gdc.width) * pipe.bds_sf; + float gdcCropH = static_cast(pipe.bds.height - pipe.gdc.height) * pipe.bds_sf; + fov.w = (inW - (ifCropW + gdcCropW)) / inW; + fov.h = (inH - (ifCropH + gdcCropH)) / inH; + + return fov; +} + +} /* namespace */ + +/** + * \struct PipeConfig + * \brief The ImgU pipe configuration parameters + * + * The ImgU image pipeline is composed of several hardware blocks that crop + * and scale the input image to obtain the desired output sizes. The + * scaling/cropping operations of those components is configured though the + * V4L2 selection API and the V4L2 subdev API applied to the ImgU media entity. + * + * The configurable components in the pipeline are: + * - IF: image feeder + * - BDS: bayer downscaler + * - GDC: geometric distorsion correction + * + * The IF crop rectangle is controlled by the V4L2_SEL_TGT_CROP selection target + * applied to the ImgU media entity sink pad number 0. The BDS scaler is + * controlled by the V4L2_SEL_TGT_COMPOSE target on the same pad, while the GDC + * output size is configured with the VIDIOC_SUBDEV_S_FMT IOCTL, again on pad + * number 0. + * + * The PipeConfig structure collects the sizes of each of those components + * plus the BDS scaling factor used to calculate the field of view + * of the final images. + */ + +/** + * \struct Pipe + * \brief Describe the ImgU requested configuration + * + * The ImgU unit processes images through several components, which have + * to be properly configured inspecting the input image size and the desired + * output sizes. This structure collects the ImgU input configuration and the + * requested main output and viewfinder configurations. + * + * \var Pipe::input + * \brief The input image size + * + * \var Pipe::output + * \brief The requested main output size + * + * \var Pipe::viewfinder + * \brief The requested viewfinder size + */ + /** * \brief Initialize components of the ImgU instance * \param[in] mediaDevice The ImgU instance media device @@ -74,6 +366,63 @@ int ImgUDevice::init(MediaDevice *media, unsigned int index) return 0; } +/** + * \brief Calculate the ImgU pipe configuration parameters + * \param[in] pipe The requested ImgU configuration + * \return An ImgUDevice::PipeConfig instance on success, an empty configuration + * otherwise + */ +ImgUDevice::PipeConfig ImgUDevice::calculatePipeConfig(Pipe *pipe) +{ + pipeConfigs.clear(); + + LOG(IPU3, Debug) << "Calculating pipe configuration for: "; + LOG(IPU3, Debug) << "input: " << pipe->input.toString(); + LOG(IPU3, Debug) << "main: " << pipe->output.toString(); + LOG(IPU3, Debug) << "vf: " << pipe->viewfinder.toString(); + + const Size &in = pipe->input; + Size gdc = calculateGDC(pipe); + + unsigned int ifWidth = utils::alignUp(in.width, IF_ALIGN_W); + unsigned int ifHeight = in.height; + unsigned int minIfWidth = in.width - IF_CROP_MAX_W; + float bdsSF = static_cast(in.width) / + static_cast(gdc.width); + float sf = findScaleFactor(bdsSF, bdsScalingFactors, true); + while (ifWidth >= minIfWidth) { + Size iif{ ifWidth, ifHeight }; + calculateBDS(pipe, iif, gdc, sf); + + ifWidth -= IF_ALIGN_W; + } + + if (pipeConfigs.size() == 0) { + LOG(IPU3, Error) << "Failed to calculate pipe configuration"; + return {}; + } + + FOV bestFov = calcFOV(pipe->input, pipeConfigs[0]); + unsigned int bestIndex = 0; + unsigned int p = 0; + for (auto pipeConfig : pipeConfigs) { + FOV fov = calcFOV(pipe->input, pipeConfig); + if (fov.isLarger(bestFov)) { + bestFov = fov; + bestIndex = p; + } + + ++p; + } + + LOG(IPU3, Debug) << "Computed pipe configuration: "; + LOG(IPU3, Debug) << "IF: " << pipeConfigs[bestIndex].iif.toString(); + LOG(IPU3, Debug) << "BDS: " << pipeConfigs[bestIndex].bds.toString(); + LOG(IPU3, Debug) << "GDC: " << pipeConfigs[bestIndex].gdc.toString(); + + return pipeConfigs[bestIndex]; +} + /** * \brief Configure the ImgU unit input * \param[in] size The ImgU input frame size diff --git a/src/libcamera/pipeline/ipu3/imgu.h b/src/libcamera/pipeline/ipu3/imgu.h index 23ec1ca1c6ae..0b2dd1f965c1 100644 --- a/src/libcamera/pipeline/ipu3/imgu.h +++ b/src/libcamera/pipeline/ipu3/imgu.h @@ -23,8 +23,28 @@ struct StreamConfiguration; class ImgUDevice { public: + struct PipeConfig { + float bds_sf; + Size iif; + Size bds; + Size gdc; + + bool isNull() const + { + return iif.isNull() || bds.isNull() || gdc.isNull(); + } + }; + + struct Pipe { + Size input; + Size output; + Size viewfinder; + }; + int init(MediaDevice *media, unsigned int index); + PipeConfig calculatePipeConfig(Pipe *pipe); + int configureInput(const Size &size, V4L2DeviceFormat *inputFormat); int configureOutput(const StreamConfiguration &cfg, From patchwork Mon Jul 20 10:47:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8889 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 AD21DC2E68 for ; Mon, 20 Jul 2020 10:44:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 807386081A; Mon, 20 Jul 2020 12:44:30 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1E9876039F for ; Mon, 20 Jul 2020 12:44:27 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 5CC1E60010; Mon, 20 Jul 2020 10:44:26 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:34 +0200 Message-Id: <20200720104736.19986-18-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 17/19] libcamera: ipu3: Validate the pipe configuration 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" Collect the desired ImgU pipe configuration while assigning streams in the pipeline handler validate() function and ask the ImgUDevice class to calculate the pipe configuration parameters. If the requested pipe configuration results in a non-valid configuration, return an error from the validate() function. Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/ipu3.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 0379fb7b92a7..5237c3b306df 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -77,6 +77,7 @@ private: const IPU3CameraData *data_; StreamConfiguration cio2Configuration_; + ImgUDevice::PipeConfig pipeConfig_; }; class PipelineHandlerIPU3 : public PipelineHandler @@ -189,6 +190,9 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate() LOG(IPU3, Debug) << "CIO2 configuration: " << cio2Configuration_.toString(); + ImgUDevice::Pipe pipe{}; + pipe.input = cio2Configuration_.size; + /* * Adjust the configurations if needed and assign streams while * iterating them. @@ -262,10 +266,15 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate() cfg->setStream(const_cast(&data_->outStream_)); mainOutputAvailable = false; + pipe.output = cfg->size; + if (yuvCount == 1) + pipe.viewfinder = pipe.output; + LOG(IPU3, Debug) << "Assigned " << cfg->toString() << " to the main output"; } else { cfg->setStream(const_cast(&data_->vfStream_)); + pipe.viewfinder = cfg->size; LOG(IPU3, Debug) << "Assigned " << cfg->toString() << " to the viewfinder output"; @@ -281,6 +290,16 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate() } } + /* Only compute the ImgU configuration if a YUV stream has been requested. */ + if (yuvCount) { + pipeConfig_ = data_->imgu_->calculatePipeConfig(&pipe); + if (pipeConfig_.isNull()) { + LOG(IPU3, Error) << "Failed to calculate pipe configuration: " + << "unsupported resolutions."; + return Invalid; + } + } + return status; } From patchwork Mon Jul 20 10:47:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8890 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 C0EC0C2E7A for ; Mon, 20 Jul 2020 10:44:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 97E8E60832; Mon, 20 Jul 2020 12:44:30 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 284C560717 for ; Mon, 20 Jul 2020 12:44:28 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 447A66000A; Mon, 20 Jul 2020 10:44:27 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:35 +0200 Message-Id: <20200720104736.19986-19-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 18/19] libcamera: ipu3: Configure ImgU with the computed parameters 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" Instrument the ImgUDevice::configureInput() function to use the provided pipe configuration parameters to configure the IF, BDS and GDC rectangles. Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/imgu. | 0 src/libcamera/pipeline/ipu3/imgu.cpp | 26 +++++++++++++------------- src/libcamera/pipeline/ipu3/imgu.h | 2 +- src/libcamera/pipeline/ipu3/ipu3.cpp | 16 +++++++++++++++- 4 files changed, 29 insertions(+), 15 deletions(-) create mode 100644 src/libcamera/pipeline/ipu3/imgu. diff --git a/src/libcamera/pipeline/ipu3/imgu. b/src/libcamera/pipeline/ipu3/imgu. new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/libcamera/pipeline/ipu3/imgu.cpp b/src/libcamera/pipeline/ipu3/imgu.cpp index 17b749435ee2..ad51a64a84e4 100644 --- a/src/libcamera/pipeline/ipu3/imgu.cpp +++ b/src/libcamera/pipeline/ipu3/imgu.cpp @@ -425,11 +425,11 @@ ImgUDevice::PipeConfig ImgUDevice::calculatePipeConfig(Pipe *pipe) /** * \brief Configure the ImgU unit input - * \param[in] size The ImgU input frame size + * \param[in] config The ImgU pipe configuration parameters * \param[in] inputFormat The format to be applied to ImgU input * \return 0 on success or a negative error code otherwise */ -int ImgUDevice::configureInput(const Size &size, +int ImgUDevice::configureInput(const PipeConfig &pipeConfig, V4L2DeviceFormat *inputFormat) { /* Configure the ImgU input video device with the requested sizes. */ @@ -449,27 +449,27 @@ int ImgUDevice::configureInput(const Size &size, * to configure the crop/compose rectangles, contradicting the * V4L2 specification. */ - Rectangle rect{ 0, 0, inputFormat->size }; - ret = imgu_->setSelection(PAD_INPUT, V4L2_SEL_TGT_CROP, &rect); + Rectangle iif{ 0, 0, pipeConfig.iif }; + ret = imgu_->setSelection(PAD_INPUT, V4L2_SEL_TGT_CROP, &iif); if (ret) return ret; + LOG(IPU3, Debug) << "ImgU IF rectangle = " << iif.toString(); - ret = imgu_->setSelection(PAD_INPUT, V4L2_SEL_TGT_COMPOSE, &rect); + Rectangle bds{ 0, 0, pipeConfig.bds }; + ret = imgu_->setSelection(PAD_INPUT, V4L2_SEL_TGT_COMPOSE, &bds); if (ret) return ret; + LOG(IPU3, Debug) << "ImgU BDS rectangle = " << bds.toString(); - LOG(IPU3, Debug) << "ImgU input feeder and BDS rectangle = " - << rect.toString(); + V4L2SubdeviceFormat gdcFormat = {}; + gdcFormat.mbus_code = MEDIA_BUS_FMT_FIXED; + gdcFormat.size = pipeConfig.gdc; - V4L2SubdeviceFormat imguFormat = {}; - imguFormat.mbus_code = MEDIA_BUS_FMT_FIXED; - imguFormat.size = size; - - ret = imgu_->setFormat(PAD_INPUT, &imguFormat); + ret = imgu_->setFormat(PAD_INPUT, &gdcFormat); if (ret) return ret; - LOG(IPU3, Debug) << "ImgU GDC format = " << imguFormat.toString(); + LOG(IPU3, Debug) << "ImgU GDC format = " << gdcFormat.toString(); return 0; } diff --git a/src/libcamera/pipeline/ipu3/imgu.h b/src/libcamera/pipeline/ipu3/imgu.h index 0b2dd1f965c1..91715c78fa83 100644 --- a/src/libcamera/pipeline/ipu3/imgu.h +++ b/src/libcamera/pipeline/ipu3/imgu.h @@ -45,7 +45,7 @@ public: PipeConfig calculatePipeConfig(Pipe *pipe); - int configureInput(const Size &size, V4L2DeviceFormat *inputFormat); + int configureInput(const PipeConfig &pipeConfig, V4L2DeviceFormat *inputFormat); int configureOutput(const StreamConfiguration &cfg, V4L2DeviceFormat *outputFormat) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 5237c3b306df..d7c0076a57e3 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -67,6 +67,7 @@ public: Status validate() override; const StreamConfiguration &cio2Format() const { return cio2Configuration_; }; + const ImgUDevice::PipeConfig imguConfig() const { return pipeConfig_; } private: /* @@ -461,7 +462,20 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) if (ret) return ret; - ret = imgu->configureInput(sensorSize, &cio2Format); + /* + * If the ImgU gets configured with proper IF, BDS and GDC sizes, it + * is then expected that frames are dequeued from its main output + * otherwise the system stalls. + * + * If no ImgU configuration has been computed, it means only a RAW + * stream has been requested: return here to skip the ImgU configuration + * part. + */ + ImgUDevice::PipeConfig imguConfig = config->imguConfig(); + if (imguConfig.isNull()) + return 0; + + ret = imgu->configureInput(imguConfig, &cio2Format); if (ret) return ret; From patchwork Mon Jul 20 10:47:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 8891 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 02C36C2E7B for ; Mon, 20 Jul 2020 10:44:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D036560868; Mon, 20 Jul 2020 12:44:30 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0A1BE6039F for ; Mon, 20 Jul 2020 12:44:29 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 45BD06000F; Mon, 20 Jul 2020 10:44:28 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Jul 2020 12:47:36 +0200 Message-Id: <20200720104736.19986-20-jacopo@jmondi.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200720104736.19986-1-jacopo@jmondi.org> References: <20200720104736.19986-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 19/19] libcamera: ipu3: imgu: Rename configureInput() 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 ImgUDevice::configureInput() function does not only configure the input format but applies rectangles to the IF, BDS and GDC components. Rename it to ImgUDevice::configure(). Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/imgu.cpp | 5 ++--- src/libcamera/pipeline/ipu3/imgu.h | 2 +- src/libcamera/pipeline/ipu3/ipu3.cpp | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/imgu.cpp b/src/libcamera/pipeline/ipu3/imgu.cpp index ad51a64a84e4..a3ea3eabe318 100644 --- a/src/libcamera/pipeline/ipu3/imgu.cpp +++ b/src/libcamera/pipeline/ipu3/imgu.cpp @@ -424,13 +424,12 @@ ImgUDevice::PipeConfig ImgUDevice::calculatePipeConfig(Pipe *pipe) } /** - * \brief Configure the ImgU unit input + * \brief Configure the ImgU pipeline * \param[in] config The ImgU pipe configuration parameters * \param[in] inputFormat The format to be applied to ImgU input * \return 0 on success or a negative error code otherwise */ -int ImgUDevice::configureInput(const PipeConfig &pipeConfig, - V4L2DeviceFormat *inputFormat) +int ImgUDevice::configure(const PipeConfig &pipeConfig, V4L2DeviceFormat *inputFormat) { /* Configure the ImgU input video device with the requested sizes. */ int ret = input_->setFormat(inputFormat); diff --git a/src/libcamera/pipeline/ipu3/imgu.h b/src/libcamera/pipeline/ipu3/imgu.h index 91715c78fa83..ff8dab7d645c 100644 --- a/src/libcamera/pipeline/ipu3/imgu.h +++ b/src/libcamera/pipeline/ipu3/imgu.h @@ -45,7 +45,7 @@ public: PipeConfig calculatePipeConfig(Pipe *pipe); - int configureInput(const PipeConfig &pipeConfig, V4L2DeviceFormat *inputFormat); + int configure(const PipeConfig &pipeConfig, V4L2DeviceFormat *inputFormat); int configureOutput(const StreamConfiguration &cfg, V4L2DeviceFormat *outputFormat) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index d7c0076a57e3..06afc7d79dac 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -475,7 +475,7 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) if (imguConfig.isNull()) return 0; - ret = imgu->configureInput(imguConfig, &cio2Format); + ret = imgu->configure(imguConfig, &cio2Format); if (ret) return ret;