{"id":593,"url":"https://patchwork.libcamera.org/api/1.1/patches/593/?format=json","web_url":"https://patchwork.libcamera.org/patch/593/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/1.1/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20190220131757.14004-6-jacopo@jmondi.org>","date":"2019-02-20T13:17:57","name":"[libcamera-devel,5/5] libcamera: ipu3: Add IMGUDevice class","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"330f7e8b0b148994b503c0fa78cddd2bfdde23d9","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/1.1/people/3/?format=json","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/593/mbox/","series":[{"id":186,"url":"https://patchwork.libcamera.org/api/1.1/series/186/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=186","date":"2019-02-20T13:17:52","name":"libcamera: IPU3: create CIO2 and IMGU devices","version":1,"mbox":"https://patchwork.libcamera.org/series/186/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/593/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/593/checks/","tags":{},"headers":{"Return-Path":"<jacopo@jmondi.org>","Received":["from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net\n\t[217.70.183.194])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 3C7F160100\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 20 Feb 2019 14:17:43 +0100 (CET)","from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101])\n\t(Authenticated sender: jacopo@jmondi.org)\n\tby relay2-d.mail.gandi.net (Postfix) with ESMTPSA id A704C40016;\n\tWed, 20 Feb 2019 13:17:42 +0000 (UTC)"],"X-Originating-IP":"2.224.242.101","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"libcamera-devel@lists.libcamera.org","Date":"Wed, 20 Feb 2019 14:17:57 +0100","Message-Id":"<20190220131757.14004-6-jacopo@jmondi.org>","X-Mailer":"git-send-email 2.20.1","In-Reply-To":"<20190220131757.14004-1-jacopo@jmondi.org>","References":"<20190220131757.14004-1-jacopo@jmondi.org>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","Subject":"[libcamera-devel] [PATCH 5/5] libcamera: ipu3: Add IMGUDevice class","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Wed, 20 Feb 2019 13:17:43 -0000"},"content":"Add an IMGUDevice class that represents all devices associated with the\nIPU3 imgu unit.\n\nImgu units will be freely assigned to cameras, depending on the number of\nstreams that are required. Add two imgu instances to the ipu3 pipeline,\nand provide methods to configure the format on the imgu internal\ncomponents.\n\nSigned-off-by: Jacopo Mondi <jacopo@jmondi.org>\n---\n src/libcamera/pipeline/ipu3/imgu.cpp    | 338 ++++++++++++++++++++++++\n src/libcamera/pipeline/ipu3/ipu3.cpp    |  71 +++++\n src/libcamera/pipeline/ipu3/ipu3.h      |  34 +++\n src/libcamera/pipeline/ipu3/meson.build |   1 +\n 4 files changed, 444 insertions(+)\n create mode 100644 src/libcamera/pipeline/ipu3/imgu.cpp","diff":"diff --git a/src/libcamera/pipeline/ipu3/imgu.cpp b/src/libcamera/pipeline/ipu3/imgu.cpp\nnew file mode 100644\nindex 000000000000..7945764eb989\n--- /dev/null\n+++ b/src/libcamera/pipeline/ipu3/imgu.cpp\n@@ -0,0 +1,338 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2019, Google Inc.\n+ *\n+ * imgu.cpp - IPU3 IMGU unit\n+ */\n+\n+#include <string>\n+#include <vector>\n+\n+#include <linux/media-bus-format.h>\n+\n+#include \"geometry.h\"\n+#include \"ipu3.h\"\n+#include \"media_device.h\"\n+#include \"v4l2_device.h\"\n+#include \"v4l2_subdevice.h\"\n+\n+/*\n+ * IMGUDevice represents one of the two 'IMGU' units the Intel IPU3 ISP\n+ * provides.\n+ *\n+ * IMGU units are fed with image data captured from a CIO2 instance and with\n+ * configuration parameters for 3A tuning.\n+ *\n+ * Each IMGU handles 2 video pipes at the time, and each pipe provide 2 image\n+ * outputs ('output' and 'viewfinder') and one statistics metadata output.\n+ *\n+ * TODO: support concurrent pipes\n+ * TODO: support multiple video capture streams (output + viewfinder)\n+ */\n+\n+namespace libcamera {\n+\n+LOG_DECLARE_CATEGORY(IPU3)\n+\n+IMGUDevice::IMGUDevice()\n+\t: owner_(nullptr), imgu_(nullptr), input_(nullptr),\n+\t  output_(nullptr), viewfinder_(nullptr), stat_(nullptr)\n+{\n+}\n+\n+IMGUDevice::~IMGUDevice()\n+{\n+\tdelete imgu_;\n+\tdelete input_;\n+\tdelete output_;\n+\tdelete viewfinder_;\n+\tdelete stat_;\n+}\n+\n+int IMGUDevice::open(unsigned int index, MediaDevice *imguMediaDev)\n+{\n+\tint ret;\n+\n+\tstd::string imguName = \"ipu3-imgu \" + std::to_string(index);\n+\tMediaEntity *entity = imguMediaDev->getEntityByName(imguName);\n+\tif (!entity) {\n+\t\tLOG(IPU3, Error) << \"Failed to get entity '\" << imguName << \"'\";\n+\t\treturn -ENODEV;\n+\t}\n+\n+\timgu_ = new V4L2Subdevice(entity);\n+\tret = imgu_->open();\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tstd::string inputName = imguName + \" input\";\n+\tentity = imguMediaDev->getEntityByName(inputName);\n+\tif (!entity) {\n+\t\tLOG(IPU3, Error) << \"Failed to get entity '\" << inputName << \"'\";\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tinput_ = new V4L2Device(entity);\n+\tret = input_->open();\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tstd::string outputName = imguName + \" output\";\n+\tentity = imguMediaDev->getEntityByName(outputName);\n+\tif (!entity) {\n+\t\tLOG(IPU3, Error) << \"Failed to get entity '\" << outputName << \"'\";\n+\t\treturn -ENODEV;\n+\t}\n+\n+\toutput_ = new V4L2Device(entity);\n+\tret = output_->open();\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tstd::string viewfinderName = imguName + \" viewfinder\";\n+\tentity = imguMediaDev->getEntityByName(viewfinderName);\n+\tif (!entity) {\n+\t\tLOG(IPU3, Error) << \"Failed to get entity '\"\n+\t\t\t\t << viewfinderName << \"'\";\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tviewfinder_ = new V4L2Device(entity);\n+\tret = viewfinder_->open();\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tstd::string statName = imguName + \" 3a stat\";\n+\tentity = imguMediaDev->getEntityByName(statName);\n+\tif (!entity) {\n+\t\tLOG(IPU3, Error) << \"Failed to get entity '\"\n+\t\t\t\t << statName << \"'\";\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tstat_ = new V4L2Device(entity);\n+\tret = stat_->open();\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Link entities to configure the IMGU unit for capture. */\n+\tMediaLink *link = imguMediaDev->link(inputName, 0, imguName, 0);\n+\tif (!link) {\n+\t\tLOG(IPU3, Error)\n+\t\t\t<< \"Failed to get link '\" << inputName << \"':0 -> '\"\n+\t\t\t<< imguName << \"':0\";\n+\t\treturn -EINVAL;\n+\t}\n+\tlink->setEnabled(true);\n+\n+\tlink = imguMediaDev->link(imguName, 2, outputName, 0);\n+\tif (!link) {\n+\t\tLOG(IPU3, Error)\n+\t\t\t<< \"Failed to get link '\" << imguName << \"':2 -> '\"\n+\t\t\t<< outputName << \"':0\";\n+\t\treturn -EINVAL;\n+\t}\n+\tlink->setEnabled(true);\n+\n+\tlink = imguMediaDev->link(imguName, 3, viewfinderName, 0);\n+\tif (!link) {\n+\t\tLOG(IPU3, Error)\n+\t\t\t<< \"Failed to get link '\" << imguName << \"':3 -> '\"\n+\t\t\t<< viewfinderName << \"':0\";\n+\t\treturn -EINVAL;\n+\t}\n+\tlink->setEnabled(true);\n+\n+\tlink = imguMediaDev->link(imguName, 4, statName, 0);\n+\tif (!link) {\n+\t\tLOG(IPU3, Error)\n+\t\t\t<< \"Failed to get link '\" << imguName << \"':4 -> '\"\n+\t\t\t<< statName << \"':0\";\n+\t\treturn -EINVAL;\n+\t}\n+\tlink->setEnabled(true);\n+\n+\treturn 0;\n+}\n+\n+int IMGUDevice::configure(const IPU3DeviceFormat &inputFormat,\n+\t\t\t  const IPU3DeviceFormat &outputFormat)\n+{\n+\tint ret;\n+\n+\tRectangle selectionRectangle = {};\n+\tselectionRectangle.x = 0;\n+\tselectionRectangle.y = 0;\n+\tselectionRectangle.w = inputFormat.width;\n+\tselectionRectangle.h = inputFormat.height;\n+\n+\tret = imgu_->setCrop(IMGU_PAD_INPUT, selectionRectangle);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tLOG(IPU3, Debug)\n+\t\t<< \"'\" << imgu_->deviceName() << \"':\" << IMGU_PAD_INPUT << \" = \"\n+\t\t<< \"crop: (0,0)/\" << selectionRectangle.w << \"x\"\n+\t\t<< selectionRectangle.h;\n+\n+\tret = imgu_->setCompose(IMGU_PAD_INPUT, selectionRectangle);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tLOG(IPU3, Debug)\n+\t\t<< \"'\" << imgu_->deviceName() << \"':\" << IMGU_PAD_INPUT << \" = \"\n+\t\t<< \"compose: (0,0)/\" << selectionRectangle.w << \"x\"\n+\t\t<< selectionRectangle.h;\n+\n+\tV4L2SubdeviceFormat subdevFormat = {};\n+\tret = imgu_->getFormat(IMGU_PAD_INPUT, &subdevFormat);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tLOG(IPU3, Debug)\n+\t\t<< \"'\" << imgu_->deviceName() << \"':\" << IMGU_PAD_INPUT << \" = \"\n+\t\t<< subdevFormat.width << \"x\" << subdevFormat.height << \" - \"\n+\t\t<< std::hex << subdevFormat.mbus_code;\n+\n+\t/*\n+\t * Apply image format to the 'imgu' unit subdevices.\n+\t *\n+\t * FIXME: the IPU3 driver implementation shall be changed to use the\n+\t * actual input sizes as 'imgu input' subdevice sizes, and use the\n+\t * desired output sizes to configure the crop/compose rectangles.  The\n+\t * current implementation uses output sizes as 'imgu input' sizes, and\n+\t * uses the input dimension to configure the crop/compose rectangles,\n+\t * which contradicts the V4L2 specifications.\n+\t */\n+\tsubdevFormat = {};\n+\tsubdevFormat.width = outputFormat.width;\n+\tsubdevFormat.height = outputFormat.height;\n+\tsubdevFormat.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10;\n+\n+\tret = imgu_->setFormat(IMGU_PAD_INPUT, &subdevFormat);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tLOG(IPU3, Debug)\n+\t\t<< \"'\" << imgu_->deviceName() << \"':\" << IMGU_PAD_INPUT << \" = \"\n+\t\t<< subdevFormat.width << \"x\" << subdevFormat.height << \" - \"\n+\t\t<< std::hex << subdevFormat.mbus_code;\n+\n+\t/*\n+\t * Configure the 'imgu output' and 'imgu 3a stat' pads with the\n+\t * desired output image sizes.\n+\t */\n+\tsubdevFormat = {};\n+\tsubdevFormat.width = outputFormat.width;;\n+\tsubdevFormat.height = outputFormat.height;\n+\tsubdevFormat.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10;\n+\n+\tret = imgu_->setFormat(IMGU_PAD_OUTPUT, &subdevFormat);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tLOG(IPU3, Debug)\n+\t\t<< \"'\" << imgu_->deviceName() << \"':\" << IMGU_PAD_OUTPUT << \" = \"\n+\t\t<< subdevFormat.width << \"x\" << subdevFormat.height << \" - \"\n+\t\t<< std::hex << subdevFormat.mbus_code;\n+\n+\tsubdevFormat = {};\n+\tsubdevFormat.width = outputFormat.width;;\n+\tsubdevFormat.height = outputFormat.height;\n+\tsubdevFormat.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10;\n+\n+\tret = imgu_->setFormat(IMGU_PAD_STAT, &subdevFormat);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tLOG(IPU3, Debug)\n+\t\t<< \"'\" << imgu_->deviceName() << \"':\" << IMGU_PAD_STAT << \" = \"\n+\t\t<< subdevFormat.width << \"x\" << subdevFormat.height << \" - \"\n+\t\t<< std::hex << subdevFormat.mbus_code;\n+\n+\t/*\n+\t * FIXME: Set the 'imgu viewfinder' to hardcoded size\n+\t * It shall be configured as secondary stream when support for\n+\t * multiple streams is added.\n+\t */\n+\tsubdevFormat = {};\n+\tsubdevFormat.width = outputFormat.width / 2;\n+\tsubdevFormat.height = outputFormat.height / 2;\n+\tsubdevFormat.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10;\n+\n+\tret = imgu_->setFormat(IMGU_PAD_VF, &subdevFormat);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tLOG(IPU3, Debug)\n+\t\t<< \"'\" << imgu_->deviceName() << \"':\" << IMGU_PAD_VF << \" = \"\n+\t\t<< subdevFormat.width << \"x\" << subdevFormat.height << \" - \"\n+\t\t<< std::hex << subdevFormat.mbus_code;\n+\n+\t/*\n+\t * Apply the CIO2 provided 'inputFormat' to the 'imgu input' video\n+\t * device, and the requested 'outputFormat' to the to the 'imgu output'\n+\t * 'imgu viewfinder' and 'imgu 3a stat' nodes.\n+\t *\n+\t * FIXME: Keep the viewfinder size reduced.\n+\t */\n+\tV4L2DeviceFormat devFormat = {};\n+\tdevFormat.width = inputFormat.width;\n+\tdevFormat.height = inputFormat.height;\n+\tdevFormat.fourcc = inputFormat.fourcc;\n+\n+\tret = input_->setFormat(&devFormat);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tLOG(IPU3, Debug)\n+\t\t<< \"'\" << input_->driverName() << \"': \"\n+\t\t<< devFormat.width << \"x\" << devFormat.height\n+\t\t<< \"- 0x\" << std::hex << devFormat.fourcc << \" planes: \"\n+\t\t<< devFormat.planesCount;\n+\n+\tdevFormat = {};\n+\tdevFormat.width = outputFormat.width;\n+\tdevFormat.height = outputFormat.height;\n+\tdevFormat.fourcc = outputFormat.fourcc;\n+\tV4L2DeviceFormat tmpFormat = devFormat;\n+\n+\tret = output_->setFormat(&tmpFormat);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tLOG(IPU3, Debug)\n+\t\t<< \"'\" << output_->driverName() << \"': \"\n+\t\t<< tmpFormat.width << \"x\" << tmpFormat.height\n+\t\t<< \"- 0x\" << std::hex << tmpFormat.fourcc << \" planes: \"\n+\t\t<< tmpFormat.planesCount;\n+\n+\ttmpFormat = devFormat;\n+\tret = stat_->setFormat(&tmpFormat);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tLOG(IPU3, Debug)\n+\t\t<< \"'\" << stat_->driverName() << \"': \"\n+\t\t<< tmpFormat.width << \"x\" << tmpFormat.height\n+\t\t<< \"- 0x\" << std::hex << tmpFormat.fourcc << \" planes: \"\n+\t\t<< tmpFormat.planesCount;\n+\n+\ttmpFormat = devFormat;\n+\ttmpFormat.width = devFormat.width / 2;\n+\ttmpFormat.height = devFormat.height / 2;\n+\n+\tret = viewfinder_->setFormat(&tmpFormat);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tLOG(IPU3, Debug)\n+\t\t<< \"'\" << viewfinder_->driverName() << \"': \"\n+\t\t<< tmpFormat.width << \"x\" << tmpFormat.height\n+\t\t<< \"- 0x\" << std::hex << tmpFormat.fourcc << \" planes: \"\n+\t\t<< tmpFormat.planesCount;\n+\n+\treturn 0;\n+}\n+\n+} /* namespace libcamera */\ndiff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\nindex 5fcdd6335db6..8b4c88048f6c 100644\n--- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n@@ -64,6 +64,7 @@ int PipelineHandlerIPU3::configureStreams(Camera *camera,\n \tStream *stream = &cameraData(camera)->stream_;\n \tStreamConfiguration *cfg = &config[stream];\n \tIPU3DeviceFormat outputFormat = {};\n+\tIMGUDevice *imgu;\n \tint ret;\n \n \t/* Validate the requested image format and resolution. */\n@@ -75,10 +76,46 @@ int PipelineHandlerIPU3::configureStreams(Camera *camera,\n \toutputFormat.height = cfg->height;\n \toutputFormat.fourcc = cfg->pixelFormat;\n \n+\t/*\n+\t * FIXME: as of now, a single stream is supported, so we can claim\n+\t * the first available imgu unit, if any. When multiple streams per\n+\t * camera will be supported, a single camera could use both the imgu\n+\t * units and prevent other cameras to be used.\n+\t */\n+\tif (imgu0_.available())\n+\t\timgu = &imgu0_;\n+\telse if (imgu1_.available())\n+\t\timgu = &imgu1_;\n+\telse\n+\t\treturn -EBUSY;\n+\n+\t/*\n+\t * FIXME: the imgu unit shall be released when streams gets released.\n+\t * How to deal with cross-camera dependencies ?\n+\t */\n+\timgu->acquire(camera);\n+\n+\t/*\n+\t * Configure the CIO2 unit to provide images in a resolution that\n+\t * satisfies the desired output format.\n+\t */\n \tret = cio2->configure(outputFormat);\n \tif (ret)\n \t\treturn ret;\n \n+\t/*\n+\t * Get the CIO2 output format and apply it to the IMGU input and\n+\t * apply the output format to the IMGU output.\n+\t *\n+\t * Hardcode the fourcc code output from CIO2 to IMGU.\n+\t */\n+\tIPU3DeviceFormat inputFormat = cio2->format();\n+\tinputFormat.fourcc = V4L2_PIX_FMT_IPU3_SGRBG10;\n+\n+\tret = imgu->configure(inputFormat, outputFormat);\n+\tif (ret)\n+\t\treturn ret;\n+\n \treturn 0;\n }\n \n@@ -205,12 +242,22 @@ bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)\n \tif (cio2_->disableLinks())\n \t\tgoto error_close_cio2;\n \n+\tif (imgu_->open())\n+\t\tgoto error_close_cio2;\n+\n \tregisterCameras();\n \n+\tif (registerImgus())\n+\t\tgoto error_close_imgu;\n+\n \tcio2_->close();\n+\timgu_->close();\n \n \treturn true;\n \n+error_close_imgu:\n+\timgu_->close();\n+\n error_close_cio2:\n \tcio2_->close();\n \n@@ -221,6 +268,30 @@ error_release_mdev:\n \treturn false;\n }\n \n+/*\n+ * IPU3 has two 'imgu' units which can be freely assigned to cameras;\n+ *\n+ * Create instances for both the units, creating video devices and subdevices\n+ * associated with an instance.\n+ */\n+\n+int PipelineHandlerIPU3::registerImgus()\n+{\n+\tint ret = imgu0_.open(0, imgu_.get());\n+\tif (ret) {\n+\t\tLOG(IPU3, Error) << \"Failed to open 'imgu0' unit\";\n+\t\treturn ret;\n+\t}\n+\n+\tret = imgu1_.open(1, imgu_.get());\n+\tif (ret) {\n+\t\tLOG(IPU3, Error) << \"Failed to open 'imgu1' unit\";\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n /*\n  * Cameras are created associating an image sensor (represented by a\n  * media entity with function MEDIA_ENT_F_CAM_SENSOR) to one of the four\ndiff --git a/src/libcamera/pipeline/ipu3/ipu3.h b/src/libcamera/pipeline/ipu3/ipu3.h\nindex 2a8b6f13b1c7..83d6e7cf27db 100644\n--- a/src/libcamera/pipeline/ipu3/ipu3.h\n+++ b/src/libcamera/pipeline/ipu3/ipu3.h\n@@ -57,6 +57,36 @@ public:\n \tIPU3DeviceFormat cio2Format_;\n };\n \n+class IMGUDevice\n+{\n+public:\n+\tstatic constexpr unsigned int IMGU_PAD_INPUT = 0;\n+\tstatic constexpr unsigned int IMGU_PAD_OUTPUT = 2;\n+\tstatic constexpr unsigned int IMGU_PAD_VF = 3;\n+\tstatic constexpr unsigned int IMGU_PAD_STAT = 4;\n+\n+\tIMGUDevice();\n+\tIMGUDevice(const IMGUDevice &) = delete;\n+\t~IMGUDevice();\n+\n+\tCamera *owner_;\n+\tbool available() const { return owner_ == nullptr; }\n+\tvoid acquire(Camera *camera) { owner_ = camera; }\n+\tvoid release() { owner_ = nullptr; }\n+\n+\tint open(unsigned int index, MediaDevice *imguMediaDev);\n+\n+\tint configure(const IPU3DeviceFormat &cio2Format,\n+\t\t      const IPU3DeviceFormat &imguFormat);\n+\n+\tV4L2Subdevice *imgu_;\n+\tV4L2Device *input_;\n+\tV4L2Device *output_;\n+\tV4L2Device *viewfinder_;\n+\tV4L2Device *stat_;\n+\t/* TODO: add param video device for 3A tuning */\n+};\n+\n class PipelineHandlerIPU3 : public PipelineHandler\n {\n public:\n@@ -95,10 +125,14 @@ private:\n \t\t\tPipelineHandler::cameraData(camera));\n \t}\n \n+\tint registerImgus();\n \tvoid registerCameras();\n \n \tstd::shared_ptr<MediaDevice> cio2_;\n \tstd::shared_ptr<MediaDevice> imgu_;\n+\n+\tIMGUDevice imgu0_;\n+\tIMGUDevice imgu1_;\n };\n \n } /* namespace libcamera */\ndiff --git a/src/libcamera/pipeline/ipu3/meson.build b/src/libcamera/pipeline/ipu3/meson.build\nindex fcb2d319d517..67f1a5e656d9 100644\n--- a/src/libcamera/pipeline/ipu3/meson.build\n+++ b/src/libcamera/pipeline/ipu3/meson.build\n@@ -1,4 +1,5 @@\n libcamera_sources += files([\n     'cio2.cpp',\n+    'imgu.cpp',\n     'ipu3.cpp',\n ])\n","prefixes":["libcamera-devel","5/5"]}