[{"id":26530,"web_url":"https://patchwork.libcamera.org/comment/26530/","msgid":"<ZACJ9XKjbD90lFYd@pyrite.rasen.tech>","date":"2023-03-02T11:35:17","subject":"Re: [libcamera-devel] [PATCH 2/5] libcamera: imx8-isi: Break out\n\tYUV format selection","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/people/17/","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"content":"On Sun, Jan 29, 2023 at 02:58:27PM +0100, Jacopo Mondi via libcamera-devel wrote:\n> As per the RAW format selection, the media bus format selection\n> procedure relies on the direct association of PixelFormat and media\n> bus code in the formatsMap_ map.\n> \n> As the ISI can generate YUV and RGB formats from any non-Bayer media\n> bus format, break out the YUV/RGB media bus format selection to a\n> separate function.\n> \n> The newly introduced getYuvMediaBusFormat() tests a list of\n> known-supported media bus formats against the list of media bus\n> formats supported by the sensor and tries to prefer media bus\n> codes with the same encoding as the requested PixelFormat.\n> \n> Use the newly introduced function in\n> ISICameraConfiguration::validateYuv() to make sure the sensor can\n> produce a YUV/RGB media bus format.\n> \n> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n\nReviewed-by: Paul Elder <paul.elder@ideasonboard.com>\n\n> ---\n>  src/libcamera/pipeline/imx8-isi/imx8-isi.cpp | 76 ++++++++++++++++++++\n>  1 file changed, 76 insertions(+)\n> \n> diff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp\n> index 72bc310d80ec..445fad32656c 100644\n> --- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp\n> +++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp\n> @@ -60,6 +60,7 @@ public:\n>  \t}\n>  \n>  \tunsigned int getRawMediaBusFormat(PixelFormat *pixelFormat) const;\n> +\tunsigned int getYuvMediaBusFormat(PixelFormat *pixelFormat) const;\n>  \n>  \tstd::unique_ptr<CameraSensor> sensor_;\n>  \tstd::unique_ptr<V4L2Subdevice> csis_;\n> @@ -255,6 +256,65 @@ unsigned int ISICameraData::getRawMediaBusFormat(PixelFormat *pixelFormat) const\n>  \treturn sensorCode;\n>  }\n>  \n> +/*\n> + * Get a YUV/RGB media bus format from which the ISI can produce a processed\n> + * stream, preferring codes with the same colour encoding as the requested\n> + * pixelformat.\n> + *\n> + * If the sensor does not provide any YUV/RGB media bus format the ISI cannot\n> + * generate any processed pixel format as it cannot debayer.\n> + */\n> +unsigned int ISICameraData::getYuvMediaBusFormat(PixelFormat *pixelFormat) const\n> +{\n> +\tstd::vector<unsigned int> mbusCodes = sensor_->mbusCodes();\n> +\n> +\t/*\n> +\t * The ISI can produce YUV/RGB pixel formats from any non-RAW Bayer\n> +\t * media bus formats.\n> +\t *\n> +\t * Keep the list in sync with the mxc_isi_bus_formats[] array in\n> +\t * the ISI driver.\n> +\t */\n> +\tstd::vector<unsigned int> yuvCodes = {\n> +\t\tMEDIA_BUS_FMT_UYVY8_1X16,\n> +\t\tMEDIA_BUS_FMT_YUV8_1X24,\n> +\t\tMEDIA_BUS_FMT_RGB565_1X16,\n> +\t\tMEDIA_BUS_FMT_RGB888_1X24,\n> +\t};\n> +\n> +\tstd::sort(mbusCodes.begin(), mbusCodes.end());\n> +\tstd::sort(yuvCodes.begin(), yuvCodes.end());\n> +\n> +\tstd::vector<unsigned int> supportedCodes;\n> +\tstd::set_intersection(mbusCodes.begin(), mbusCodes.end(),\n> +\t\t\t      yuvCodes.begin(), yuvCodes.end(),\n> +\t\t\t      std::back_inserter(supportedCodes));\n> +\n> +\tif (supportedCodes.empty()) {\n> +\t\tLOG(ISI, Warning) << \"Cannot find a supported YUV/RGB format\";\n> +\t\t*pixelFormat = {};\n> +\n> +\t\treturn 0;\n> +\t}\n> +\n> +\t/* Prefer codes with the same encoding as the requested pixel format. */\n> +\tconst PixelFormatInfo &info = PixelFormatInfo::info(*pixelFormat);\n> +\tfor (unsigned int code : supportedCodes) {\n> +\t\tif (info.colourEncoding == PixelFormatInfo::ColourEncodingYUV &&\n> +\t\t    (code == MEDIA_BUS_FMT_UYVY8_1X16 ||\n> +\t\t     code == MEDIA_BUS_FMT_YUV8_1X24))\n> +\t\t\treturn code;\n> +\n> +\t\tif (info.colourEncoding == PixelFormatInfo::ColourEncodingRGB &&\n> +\t\t    (code == MEDIA_BUS_FMT_RGB565_1X16 ||\n> +\t\t     code == MEDIA_BUS_FMT_RGB888_1X24))\n> +\t\t\treturn code;\n> +\t}\n> +\n> +\t/* Otherwise return the first found code. */\n> +\treturn supportedCodes[0];\n> +}\n> +\n>  /* -----------------------------------------------------------------------------\n>   * Camera Configuration\n>   */\n> @@ -455,6 +515,22 @@ ISICameraConfiguration::validateYuv(std::set<Stream *> &availableStreams,\n>  {\n>  \tCameraConfiguration::Status status = Valid;\n>  \n> +\tStreamConfiguration &yuvConfig = config_[0];\n> +\tPixelFormat yuvPixelFormat = yuvConfig.pixelFormat;\n> +\n> +\t/*\n> +\t * Make sure the sensor can produce a compatible YUV/RGB media bus\n> +\t * format. If the sensor can only produce RAW Bayer we can only fail\n> +\t * here as we can't adjust to anything but RAW.\n> +\t */\n> +\tunsigned int yuvMediaBusCode = data_->getYuvMediaBusFormat(&yuvPixelFormat);\n> +\tif (!yuvMediaBusCode) {\n> +\t\tLOG(ISI, Error) << \"Cannot adjust pixelformat \"\n> +\t\t\t\t<< yuvConfig.pixelFormat;\n> +\t\treturn Invalid;\n> +\t}\n> +\n> +\t/* Adjust all the other streams. */\n>  \tfor (const auto &[i, cfg] : utils::enumerate(config_)) {\n>  \n>  \t\tLOG(ISI, Debug) << \"Stream \" << i << \": \" << cfg.toString();\n> -- \n> 2.39.0\n>","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 955BFBF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu,  2 Mar 2023 11:35:28 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 57700626C0;\n\tThu,  2 Mar 2023 12:35:28 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 94AA96269C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  2 Mar 2023 12:35:26 +0100 (CET)","from pyrite.rasen.tech (h175-177-042-159.catv02.itscom.jp\n\t[175.177.42.159])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 1C9CB56A;\n\tThu,  2 Mar 2023 12:35:24 +0100 (CET)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1677756928;\n\tbh=groR2lECfCX+cQSucWxt3bl0+vW2R7gvJwBXH/FnTdI=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=dENkw9M9dw2dP8Pw7MY1u+cpD+/pe37wig0tmuCenwy0ta+0zJlriH8CzwB3Gp9Qf\n\tvPaJD6WRiK9Td6KiXaXA2KK9wC/TR66Utt1xM6fY6sSqLWPcsB+ah+sqb6CARMnuDN\n\t+pDUoQcF2Q4h+NNYEeYrZ0tpdnJ8CgKwoMJn+V+QWw1Rw0LfrNXTuE9PaY740l1hBd\n\tgNOAkIcV8vfhqdFejDqbOkHXAM56weXWzqJrrUPqSeOHhGv7dSDuS8lZPRqfC742rd\n\ttlDI29xVqUugpivXt2Gs0cQdSrZlGgQJ/N5TvUTdKXi+1/Oc9UqohyD+YNDFrYXZuJ\n\tehVcdMWS3heDA==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1677756926;\n\tbh=groR2lECfCX+cQSucWxt3bl0+vW2R7gvJwBXH/FnTdI=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=ERdzRUP8mTgb9sSEjmXLK2rf4OtREuZEYHuOE3S4jTgjF0pfJQp75yCsofoKbv+n2\n\tY9emz3U1mnaAhhg/90DlxKsD/FXqY+2ilIUusRWVlYF41zej0dcw6U7zoAYQ9/Z/7e\n\tKuF6rMf5SRhHWLis97MF1COqBGTfvqEq9hyOcXMw="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"ERdzRUP8\"; dkim-atps=neutral","Date":"Thu, 2 Mar 2023 20:35:17 +0900","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Message-ID":"<ZACJ9XKjbD90lFYd@pyrite.rasen.tech>","References":"<20230129135830.27490-1-jacopo.mondi@ideasonboard.com>\n\t<20230129135830.27490-3-jacopo.mondi@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<20230129135830.27490-3-jacopo.mondi@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH 2/5] libcamera: imx8-isi: Break out\n\tYUV format selection","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>","From":"Paul Elder via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Paul Elder <paul.elder@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":26640,"web_url":"https://patchwork.libcamera.org/comment/26640/","msgid":"<20230312163342.GZ2545@pendragon.ideasonboard.com>","date":"2023-03-12T16:33:42","subject":"Re: [libcamera-devel] [PATCH 2/5] libcamera: imx8-isi: Break out\n\tYUV format selection","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Jacopo,\n\nThank you for the patch.\n\nOn Sun, Jan 29, 2023 at 02:58:27PM +0100, Jacopo Mondi via libcamera-devel wrote:\n> As per the RAW format selection, the media bus format selection\n> procedure relies on the direct association of PixelFormat and media\n> bus code in the formatsMap_ map.\n> \n> As the ISI can generate YUV and RGB formats from any non-Bayer media\n> bus format, break out the YUV/RGB media bus format selection to a\n> separate function.\n> \n> The newly introduced getYuvMediaBusFormat() tests a list of\n> known-supported media bus formats against the list of media bus\n> formats supported by the sensor and tries to prefer media bus\n> codes with the same encoding as the requested PixelFormat.\n> \n> Use the newly introduced function in\n> ISICameraConfiguration::validateYuv() to make sure the sensor can\n> produce a YUV/RGB media bus format.\n> \n> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> ---\n>  src/libcamera/pipeline/imx8-isi/imx8-isi.cpp | 76 ++++++++++++++++++++\n>  1 file changed, 76 insertions(+)\n> \n> diff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp\n> index 72bc310d80ec..445fad32656c 100644\n> --- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp\n> +++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp\n> @@ -60,6 +60,7 @@ public:\n>  \t}\n>  \n>  \tunsigned int getRawMediaBusFormat(PixelFormat *pixelFormat) const;\n> +\tunsigned int getYuvMediaBusFormat(PixelFormat *pixelFormat) const;\n>  \n>  \tstd::unique_ptr<CameraSensor> sensor_;\n>  \tstd::unique_ptr<V4L2Subdevice> csis_;\n> @@ -255,6 +256,65 @@ unsigned int ISICameraData::getRawMediaBusFormat(PixelFormat *pixelFormat) const\n>  \treturn sensorCode;\n>  }\n>  \n> +/*\n> + * Get a YUV/RGB media bus format from which the ISI can produce a processed\n> + * stream, preferring codes with the same colour encoding as the requested\n> + * pixelformat.\n> + *\n> + * If the sensor does not provide any YUV/RGB media bus format the ISI cannot\n> + * generate any processed pixel format as it cannot debayer.\n> + */\n> +unsigned int ISICameraData::getYuvMediaBusFormat(PixelFormat *pixelFormat) const\n> +{\n> +\tstd::vector<unsigned int> mbusCodes = sensor_->mbusCodes();\n> +\n> +\t/*\n> +\t * The ISI can produce YUV/RGB pixel formats from any non-RAW Bayer\n> +\t * media bus formats.\n> +\t *\n> +\t * Keep the list in sync with the mxc_isi_bus_formats[] array in\n> +\t * the ISI driver.\n> +\t */\n> +\tstd::vector<unsigned int> yuvCodes = {\n> +\t\tMEDIA_BUS_FMT_UYVY8_1X16,\n> +\t\tMEDIA_BUS_FMT_YUV8_1X24,\n> +\t\tMEDIA_BUS_FMT_RGB565_1X16,\n> +\t\tMEDIA_BUS_FMT_RGB888_1X24,\n> +\t};\n> +\n> +\tstd::sort(mbusCodes.begin(), mbusCodes.end());\n> +\tstd::sort(yuvCodes.begin(), yuvCodes.end());\n> +\n> +\tstd::vector<unsigned int> supportedCodes;\n> +\tstd::set_intersection(mbusCodes.begin(), mbusCodes.end(),\n> +\t\t\t      yuvCodes.begin(), yuvCodes.end(),\n> +\t\t\t      std::back_inserter(supportedCodes));\n> +\n> +\tif (supportedCodes.empty()) {\n> +\t\tLOG(ISI, Warning) << \"Cannot find a supported YUV/RGB format\";\n> +\t\t*pixelFormat = {};\n> +\n> +\t\treturn 0;\n> +\t}\n> +\n> +\t/* Prefer codes with the same encoding as the requested pixel format. */\n> +\tconst PixelFormatInfo &info = PixelFormatInfo::info(*pixelFormat);\n> +\tfor (unsigned int code : supportedCodes) {\n> +\t\tif (info.colourEncoding == PixelFormatInfo::ColourEncodingYUV &&\n> +\t\t    (code == MEDIA_BUS_FMT_UYVY8_1X16 ||\n> +\t\t     code == MEDIA_BUS_FMT_YUV8_1X24))\n> +\t\t\treturn code;\n> +\n> +\t\tif (info.colourEncoding == PixelFormatInfo::ColourEncodingRGB &&\n> +\t\t    (code == MEDIA_BUS_FMT_RGB565_1X16 ||\n> +\t\t     code == MEDIA_BUS_FMT_RGB888_1X24))\n> +\t\t\treturn code;\n> +\t}\n> +\n> +\t/* Otherwise return the first found code. */\n> +\treturn supportedCodes[0];\n> +}\n> +\n>  /* -----------------------------------------------------------------------------\n>   * Camera Configuration\n>   */\n> @@ -455,6 +515,22 @@ ISICameraConfiguration::validateYuv(std::set<Stream *> &availableStreams,\n>  {\n>  \tCameraConfiguration::Status status = Valid;\n>  \n> +\tStreamConfiguration &yuvConfig = config_[0];\n> +\tPixelFormat yuvPixelFormat = yuvConfig.pixelFormat;\n> +\n> +\t/*\n> +\t * Make sure the sensor can produce a compatible YUV/RGB media bus\n> +\t * format. If the sensor can only produce RAW Bayer we can only fail\n> +\t * here as we can't adjust to anything but RAW.\n> +\t */\n> +\tunsigned int yuvMediaBusCode = data_->getYuvMediaBusFormat(&yuvPixelFormat);\n> +\tif (!yuvMediaBusCode) {\n> +\t\tLOG(ISI, Error) << \"Cannot adjust pixelformat \"\n> +\t\t\t\t<< yuvConfig.pixelFormat;\n> +\t\treturn Invalid;\n> +\t}\n> +\n> +\t/* Adjust all the other streams. */\n>  \tfor (const auto &[i, cfg] : utils::enumerate(config_)) {\n>  \n>  \t\tLOG(ISI, Debug) << \"Stream \" << i << \": \" << cfg.toString();","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 3FA3BBE080\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSun, 12 Mar 2023 16:33:44 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id AC3F862706;\n\tSun, 12 Mar 2023 17:33:43 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4D7AE62705\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSun, 12 Mar 2023 17:33:42 +0100 (CET)","from pendragon.ideasonboard.com (85-76-21-162-nat.elisa-mobile.fi\n\t[85.76.21.162])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 53FACD5F;\n\tSun, 12 Mar 2023 17:33:41 +0100 (CET)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1678638823;\n\tbh=UwwRT38EI1K5Q2OoasQZmhTbHfRzob5fJtKi+04QDxc=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=e4tvOK0TWKHbv4cqHOI3ZCqh0TfHC9BhQ2t1t2PhySxaOHOW69GM585/OubpqD0f6\n\tJi1uFFe7/MXe6RApOortSXgWLXQKbfM1keLVwF6XDCWjbCWrln0H9/zyQkUeia18G5\n\tpOLnh2lvVDCwjVCXGrB/tnQ6XqOfY91OrvZ9eWTmafBd8X+swJrZsAArn6gqd58s4I\n\tS7taOo8Le11USgLYRlZt14eu/gVrUKY4oP7XRLJPVxA+04GvfRxTSNBo3v/ZnLRXGo\n\tG3EhuZZaqbTTwYmTndJjTsA4NcXNJNR5HMorLSVVlu6CvzTQdObIhquy+Ky8o9ChqG\n\teJXBfnFN7S7rg==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1678638821;\n\tbh=UwwRT38EI1K5Q2OoasQZmhTbHfRzob5fJtKi+04QDxc=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=lQ9ffUYq+GcbbB+nbKBqisojqSigW7Q8bDo+0oSNX7nKP8m5xOAMgO2Kr8lQDdlmB\n\tnktEE/DWXDs5UMtAhOIoVHSKMo/jSqWkt0OV6u6grFtT4BsQaFGeX4YF8iZV9IP+Cw\n\tDZiVCvu1OpRZqvU+0psjfQ9vmzG6qshQJPnjozKY="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"lQ9ffUYq\"; dkim-atps=neutral","Date":"Sun, 12 Mar 2023 18:33:42 +0200","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Message-ID":"<20230312163342.GZ2545@pendragon.ideasonboard.com>","References":"<20230129135830.27490-1-jacopo.mondi@ideasonboard.com>\n\t<20230129135830.27490-3-jacopo.mondi@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20230129135830.27490-3-jacopo.mondi@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH 2/5] libcamera: imx8-isi: Break out\n\tYUV format selection","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>","From":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]