Patch Detail
Show a patch.
GET /api/patches/20711/?format=api
{ "id": 20711, "url": "https://patchwork.libcamera.org/api/patches/20711/?format=api", "web_url": "https://patchwork.libcamera.org/patch/20711/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20240726114715.226468-3-umang.jain@ideasonboard.com>", "date": "2024-07-26T11:47:12", "name": "[v6,2/5] libcamera: converter: Add interface to support cropping capability", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "4cd4c13a635bf6595141dbf102deed6efc556d77", "submitter": { "id": 86, "url": "https://patchwork.libcamera.org/api/people/86/?format=api", "name": "Umang Jain", "email": "umang.jain@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/20711/mbox/", "series": [ { "id": 4462, "url": "https://patchwork.libcamera.org/api/series/4462/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4462", "date": "2024-07-26T11:47:10", "name": "libcamera: rkisp1: Plumb the ConverterDW100 converter", "version": 6, "mbox": "https://patchwork.libcamera.org/series/4462/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/20711/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/20711/checks/", "tags": {}, "headers": { "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>", "X-Original-To": "parsemail@patchwork.libcamera.org", "Delivered-To": "parsemail@patchwork.libcamera.org", "Received": [ "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id AEB9CBDC71\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 26 Jul 2024 11:47:34 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4E0A963378;\n\tFri, 26 Jul 2024 13:47:34 +0200 (CEST)", "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 8E8466336B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 26 Jul 2024 13:47:29 +0200 (CEST)", "from localhost.localdomain (unknown\n\t[IPv6:2405:201:2015:f873:55f8:639e:8e9f:12ec])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 5D5378CC;\n\tFri, 26 Jul 2024 13:46:44 +0200 (CEST)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"jyTvf4/T\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1721994405;\n\tbh=l+JMY3xVM7qlcAJq3/PvQ9triNKZiGSv4dbVblgMnQ0=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=jyTvf4/TIWIRRFndX3LgFENhhwhcyL5qqa48vLmQMuZGdykob0GOFGHB0HT5W6IuH\n\tebVS9Rg1xPhxRnmbWktOnVaADCt0FPYiMmf1Z5FN1UQtSzuIghI2yE7om6UCjWSoNH\n\tbQZHNHYLAptYUUu62p9+h6hdGtPOn2gD6+2pi1AE=", "From": "Umang Jain <umang.jain@ideasonboard.com>", "To": "libcamera-devel@lists.libcamera.org", "Cc": "Umang Jain <umang.jain@ideasonboard.com>,\n\tPaul Elder <paul.elder@ideasonboard.com>", "Subject": "[PATCH v6 2/5] libcamera: converter: Add interface to support\n\tcropping capability", "Date": "Fri, 26 Jul 2024 17:17:12 +0530", "Message-ID": "<20240726114715.226468-3-umang.jain@ideasonboard.com>", "X-Mailer": "git-send-email 2.45.0", "In-Reply-To": "<20240726114715.226468-1-umang.jain@ideasonboard.com>", "References": "<20240726114715.226468-1-umang.jain@ideasonboard.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-BeenThere": "libcamera-devel@lists.libcamera.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "<libcamera-devel.lists.libcamera.org>", "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>", "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>", "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>", "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>", "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "If the converter has cropping capability, the interface should support it\nby providing appropriate virtual functions. Provide Feature::Crop in\nFeature enumeration for the same.\n\nProvide virtual setCrop() and getCropBounds() interfaces so that\nthe converter can implement their own cropping functionality.\n\nThe V4L2M2MConverter implements these interfaces of the Converter\ninterface. Not all V4L2M2M converters will have cropping capability,\nhence Feature::Crop should be set while construction for all those\nconverters.\n\nSigned-off-by: Umang Jain <umang.jain@ideasonboard.com>\nReviewed-by: Paul Elder <paul.elder@ideasonboard.com>\n---\n include/libcamera/internal/converter.h | 5 +\n .../internal/converter/converter_v4l2_m2m.h | 6 ++\n src/libcamera/converter.cpp | 52 +++++++++++\n .../converter/converter_v4l2_m2m.cpp | 92 +++++++++++++++++++\n 4 files changed, 155 insertions(+)", "diff": "diff --git a/include/libcamera/internal/converter.h b/include/libcamera/internal/converter.h\nindex 652ff519..853888f4 100644\n--- a/include/libcamera/internal/converter.h\n+++ b/include/libcamera/internal/converter.h\n@@ -14,6 +14,7 @@\n #include <memory>\n #include <string>\n #include <tuple>\n+#include <utility>\n #include <vector>\n \n #include <libcamera/base/class.h>\n@@ -35,6 +36,7 @@ class Converter\n public:\n \tenum class Feature {\n \t\tNone = 0,\n+\t\tInputCrop = (1 << 0),\n \t};\n \n \tusing Features = Flags<Feature>;\n@@ -63,6 +65,9 @@ public:\n \tvirtual int queueBuffers(FrameBuffer *input,\n \t\t\t\t const std::map<const Stream *, FrameBuffer *> &outputs) = 0;\n \n+\tvirtual int setInputCrop(const Stream *stream, Rectangle *rect);\n+\tvirtual std::pair<Rectangle, Rectangle> inputCropBounds(const Stream *stream);\n+\n \tSignal<FrameBuffer *> inputBufferReady;\n \tSignal<FrameBuffer *> outputBufferReady;\n \ndiff --git a/include/libcamera/internal/converter/converter_v4l2_m2m.h b/include/libcamera/internal/converter/converter_v4l2_m2m.h\nindex 91701dbe..5b69b14e 100644\n--- a/include/libcamera/internal/converter/converter_v4l2_m2m.h\n+++ b/include/libcamera/internal/converter/converter_v4l2_m2m.h\n@@ -30,6 +30,7 @@ class Size;\n class SizeRange;\n class Stream;\n struct StreamConfiguration;\n+class Rectangle;\n class V4L2M2MDevice;\n \n class V4L2M2MConverter : public Converter\n@@ -57,6 +58,9 @@ public:\n \tint queueBuffers(FrameBuffer *input,\n \t\t\t const std::map<const Stream *, FrameBuffer *> &outputs);\n \n+\tint setInputCrop(const Stream *stream, Rectangle *rect);\n+\tstd::pair<Rectangle, Rectangle> inputCropBounds(const Stream *stream);\n+\n private:\n \tclass V4L2M2MStream : protected Loggable\n \t{\n@@ -75,6 +79,8 @@ private:\n \n \t\tint queueBuffers(FrameBuffer *input, FrameBuffer *output);\n \n+\t\tint setSelection(unsigned int target, Rectangle *rect);\n+\n \tprotected:\n \t\tstd::string logPrefix() const override;\n \ndiff --git a/src/libcamera/converter.cpp b/src/libcamera/converter.cpp\nindex e2dbf5e0..7ab56b4c 100644\n--- a/src/libcamera/converter.cpp\n+++ b/src/libcamera/converter.cpp\n@@ -11,6 +11,8 @@\n \n #include <libcamera/base/log.h>\n \n+#include <libcamera/stream.h>\n+\n #include \"libcamera/internal/media_device.h\"\n \n /**\n@@ -39,6 +41,8 @@ LOG_DEFINE_CATEGORY(Converter)\n * \\brief Specify the features supported by the converter\n * \\var Converter::Feature::None\n * \\brief No extra features supported by the converter\n+ * \\var Converter::Feature::InputCrop\n+ * \\brief Cropping capability at input is supported by the converter\n */\n \n /**\n@@ -161,6 +165,54 @@ Converter::~Converter()\n * \\return 0 on success or a negative error code otherwise\n */\n \n+/**\n+ * \\brief Set the crop rectangle \\a rect for \\a stream\n+ * \\param[in] stream Pointer to output stream\n+ * \\param[inout] rect The crop rectangle to be applied\n+ *\n+ * Set the crop rectangle \\a rect for \\a stream provided the converter supports\n+ * cropping. The converter should have the Feature::InputCrop flag in this\n+ * case.\n+ *\n+ * \\return 0 on success or a negative error code otherwise\n+ */\n+int Converter::setInputCrop([[maybe_unused]] const Stream *stream, [[maybe_unused]] Rectangle *rect)\n+{\n+\tif (!(features() & Feature::InputCrop)) {\n+\t\tLOG(Converter, Error) << \"Converter doesn't support cropping capabilities\";\n+\t\treturn -ENOTSUP;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * \\brief Get the crop bounds \\a stream\n+ * \\param[in] stream Pointer to output stream\n+ *\n+ * Get the minimum and maximum crop bounds for \\a stream. The converter\n+ * should supporting cropping (Feature::InputCrop).\n+ *\n+ * \\return A std::pair<Rectangle, Rectangle> containining minimum and maximum\n+ * crop bound respectively.\n+ */\n+std::pair<Rectangle, Rectangle> Converter::inputCropBounds([[maybe_unused]] const Stream *stream)\n+{\n+\tconst StreamConfiguration &config = stream->configuration();\n+\tRectangle rect;\n+\n+\tif (!(features() & Feature::InputCrop))\n+\t\tLOG(Converter, Error) << \"Converter doesn't support cropping capabilities\";\n+\n+\t/*\n+\t * This is base implementation for the Converter class, so just return\n+\t * the stream configured size as minimum and maximum crop bounds.\n+\t */\n+\trect.size() = config.size;\n+\n+\treturn { rect, rect };\n+}\n+\n /**\n * \\var Converter::inputBufferReady\n * \\brief A signal emitted when the input frame buffer completes\ndiff --git a/src/libcamera/converter/converter_v4l2_m2m.cpp b/src/libcamera/converter/converter_v4l2_m2m.cpp\nindex 4aeb7dd9..3295b988 100644\n--- a/src/libcamera/converter/converter_v4l2_m2m.cpp\n+++ b/src/libcamera/converter/converter_v4l2_m2m.cpp\n@@ -155,6 +155,15 @@ int V4L2M2MConverter::V4L2M2MStream::queueBuffers(FrameBuffer *input, FrameBuffe\n \treturn 0;\n }\n \n+int V4L2M2MConverter::V4L2M2MStream::setSelection(unsigned int target, Rectangle *rect)\n+{\n+\tint ret = m2m_->output()->setSelection(target, rect);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\treturn 0;\n+}\n+\n std::string V4L2M2MConverter::V4L2M2MStream::logPrefix() const\n {\n \treturn stream_->configuration().toString();\n@@ -375,6 +384,85 @@ int V4L2M2MConverter::exportBuffers(const Stream *stream, unsigned int count,\n \treturn iter->second->exportBuffers(count, buffers);\n }\n \n+/**\n+ * \\copydoc libcamera::Converter::setInputCrop\n+ */\n+int V4L2M2MConverter::setInputCrop(const Stream *stream, Rectangle *rect)\n+{\n+\tif (!(features() & Feature::InputCrop))\n+\t\treturn -ENOTSUP;\n+\n+\tauto iter = streams_.find(stream);\n+\tif (iter == streams_.end())\n+\t\treturn -EINVAL;\n+\n+\treturn iter->second->setSelection(V4L2_SEL_TGT_CROP, rect);\n+}\n+\n+/**\n+ * \\copydoc libcamera::Converter::inputCropBounds\n+ */\n+std::pair<Rectangle, Rectangle>\n+V4L2M2MConverter::inputCropBounds(const Stream *stream)\n+{\n+\tRectangle minCrop;\n+\tRectangle maxCrop;\n+\tint ret;\n+\n+\tif (!(features() & Feature::InputCrop)) {\n+\t\tLOG(Converter, Error) << \"Input Crop functionality is not supported\";\n+\t\treturn {};\n+\t}\n+\n+\tminCrop.width = 1;\n+\tminCrop.height = 1;\n+\tmaxCrop.width = UINT_MAX;\n+\tmaxCrop.height = UINT_MAX;\n+\n+\tauto iter = streams_.find(stream);\n+\tif (iter == streams_.end()) {\n+\t\t/*\n+\t\t * No streams configured, return minimum and maximum crop\n+\t\t * bounds at initialization.\n+\t\t */\n+\t\tret = m2m_->output()->setSelection(V4L2_SEL_TGT_CROP, &minCrop);\n+\t\tif (ret) {\n+\t\t\tLOG(Converter, Error) << \"Failed to query minimum crop bound\"\n+\t\t\t\t\t << strerror(-ret);\n+\t\t\treturn {};\n+\t\t}\n+\n+\t\tret = m2m_->output()->setSelection(V4L2_SEL_TGT_CROP, &maxCrop);\n+\t\tif (ret) {\n+\t\t\tLOG(Converter, Error) << \"Failed to query maximum crop bound\"\n+\t\t\t\t\t << strerror(-ret);\n+\t\t\treturn {};\n+\t\t}\n+\n+\t\treturn { minCrop, maxCrop };\n+\t}\n+\n+\t/*\n+\t * If the streams are configured, return bounds from according to\n+\t * stream configuration.\n+\t */\n+\tret = setInputCrop(stream, &minCrop);\n+\tif (ret) {\n+\t\tLOG(Converter, Error) << \"Failed to query minimum crop bound\"\n+\t\t\t\t << strerror(-ret);\n+\t\treturn {};\n+\t}\n+\n+\tret = setInputCrop(stream, &maxCrop);\n+\tif (ret) {\n+\t\tLOG(Converter, Error) << \"Failed to query maximum crop bound\"\n+\t\t\t\t << strerror(-ret);\n+\t\treturn {};\n+\t}\n+\n+\treturn { minCrop, maxCrop };\n+}\n+\n /**\n * \\copydoc libcamera::Converter::start\n */\n@@ -448,6 +536,10 @@ int V4L2M2MConverter::queueBuffers(FrameBuffer *input,\n \treturn 0;\n }\n \n+/*\n+ * \\todo: This should be extended to include Feature::Flag to denote\n+ * what each converter supports feature-wise.\n+ */\n static std::initializer_list<std::string> compatibles = {\n \t\"mtk-mdp\",\n \t\"pxp\",\n", "prefixes": [ "v6", "2/5" ] }