Patch Detail
Show a patch.
GET /api/patches/3786/?format=api
{ "id": 3786, "url": "https://patchwork.libcamera.org/api/patches/3786/?format=api", "web_url": "https://patchwork.libcamera.org/patch/3786/", "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": "<20200513091120.1653-3-naush@raspberrypi.com>", "date": "2020-05-13T09:11:19", "name": "[libcamera-devel,v2,2/3] libcamera: raspberrypi: Add control of sensor vblanking", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "b4ccefae98576da269f065455f42c093844e25d6", "submitter": { "id": 34, "url": "https://patchwork.libcamera.org/api/people/34/?format=api", "name": "Naushir Patuck", "email": "naush@raspberrypi.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/3786/mbox/", "series": [ { "id": 902, "url": "https://patchwork.libcamera.org/api/series/902/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=902", "date": "2020-05-13T09:11:17", "name": "raspberrypi: FPS control", "version": 2, "mbox": "https://patchwork.libcamera.org/series/902/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/3786/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/3786/checks/", "tags": {}, "headers": { "Return-Path": "<naush@raspberrypi.com>", "Received": [ "from mail-wm1-x336.google.com (mail-wm1-x336.google.com\n\t[IPv6:2a00:1450:4864:20::336])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 80C4C60DFC\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 13 May 2020 11:12:43 +0200 (CEST)", "by mail-wm1-x336.google.com with SMTP id f134so13553114wmf.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 13 May 2020 02:12:43 -0700 (PDT)", "from naushir-VirtualBox.patuck.local ([88.97.76.4])\n\tby smtp.gmail.com with ESMTPSA id\n\tn128sm8500184wmb.47.2020.05.13.02.12.41\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tWed, 13 May 2020 02:12:41 -0700 (PDT)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=raspberrypi.com\n\theader.i=@raspberrypi.com\n\theader.b=\"DMYn3uBs\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=7nSYnRG0NQEsGjzIG8Uc9rfvJsxYjJNhMbep/AHEk3c=;\n\tb=DMYn3uBsvpC88kX4UPXzHeO0vNd2KUeJsf9f62ZQ1/RCrnQWaIukgNmXY2po+ceznx\n\t6LOLhcDXGslLiGfK0WRsvHckkelmWxiD5Yh8SoisSywmd4wcn19eqwWTJBvuauvMm76Z\n\to9r1WG/E6y2ORcAFm9qSCjQyzZA/H+Xt0UhD+UDw/siMub1wx5fLViKsubQcpWI8qrL9\n\tDmHOdBXXPczciG7MX+FRfNyD1m+4VqMrFNipovVnWjRPRaXg/tbzwFjZ9kd8CEJmv5fo\n\tlr/cplhDTZdLm8XNT++to/eEKh0rRUoYaC4+iun89bym6mWg+LBszvWaAc8CPX/F/CdG\n\txY8w==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=7nSYnRG0NQEsGjzIG8Uc9rfvJsxYjJNhMbep/AHEk3c=;\n\tb=NveQ9nuSRNFG4sfIEIWI4AOjItsW9QxkB52VsywtEDV3xYhIiWlef3tOl48fxcRXTK\n\tB0QknX41tR+FrxB5PC++y1OdrZCAzSfExoNJq2Nh+IubVcUiUHd0kmRXG9RiRpHsBdp+\n\t3wVMiP8skGD8JZn69mF9uc5llMnp0Rtt7T8gzS6QAdeIWcUu17y3kYkqaHgodxewDW/j\n\tdElfRPOhUrELZ3V33YPb2JX7sEvaT+rG11/3V1bZY+OFNfo8xu0DIQTH+vkAWqmGSm3z\n\tyoZJFDBVzsw7M/aaM12kD5ggOm1Ca0nMHt8NKPLEZBpamZX8Wyy1deYTFb6+vYmqLHz7\n\tajZw==", "X-Gm-Message-State": "AGi0PubDS7gkOT4WUwUZjbqoTpOn8gDAJzWsDOyajF1qvC1+J0XPLoVv\n\t8u2ZS2xTh8bkWRDAtQJp9LjhBXrnvre6xQ==", "X-Google-Smtp-Source": "APiQypIbWsJfPrjClrmYYjDIK7kd0LiwbMPVN57Tj/0V5n9CCBZfH1mxUV3WJk1ikbvo/WA+LsrYLA==", "X-Received": "by 2002:a1c:208a:: with SMTP id\n\tg132mr20063282wmg.78.1589361162413; \n\tWed, 13 May 2020 02:12:42 -0700 (PDT)", "From": "Naushir Patuck <naush@raspberrypi.com>", "To": "libcamera-devel@lists.libcamera.org", "Date": "Wed, 13 May 2020 10:11:19 +0100", "Message-Id": "<20200513091120.1653-3-naush@raspberrypi.com>", "X-Mailer": "git-send-email 2.17.1", "In-Reply-To": "<20200513091120.1653-1-naush@raspberrypi.com>", "References": "<20200513091120.1653-1-naush@raspberrypi.com>", "Subject": "[libcamera-devel] [PATCH v2 2/3] libcamera: raspberrypi: Add\n\tcontrol of sensor vblanking", "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>", "X-List-Received-Date": "Wed, 13 May 2020 09:12:44 -0000" }, "content": "Add support for setting V4L2_CID_VBLANK appropriately when setting\nV4L2_CID_EXPOSURE. This will allow adaptive framerates during\nviewfinder use cases (e.g. when the exposure time goes above 33ms, we\ncan reduce the framerate to lower than 30fps).\n\nThe minimum and maximum frame durations are provided via libcamera\ncontrols, and will prioritise exposure time limits over any AGC request.\n\nV4L2_CID_VBLANK is controlled through the staggered writer, just like\nthe exposure and gain controls.\n\nSigned-off-by: Naushir Patuck <naush@raspberrypi.com>\n---\n include/ipa/raspberrypi.h | 1 +\n src/ipa/raspberrypi/cam_helper.cpp | 38 ++++++++++++++-\n src/ipa/raspberrypi/cam_helper.hpp | 15 +++++-\n src/ipa/raspberrypi/cam_helper_imx219.cpp | 11 ++++-\n src/ipa/raspberrypi/cam_helper_imx477.cpp | 11 ++++-\n src/ipa/raspberrypi/cam_helper_ov5647.cpp | 11 ++++-\n src/ipa/raspberrypi/raspberrypi.cpp | 48 ++++++++++++++++---\n .../pipeline/raspberrypi/raspberrypi.cpp | 2 +\n 8 files changed, 124 insertions(+), 13 deletions(-)", "diff": "diff --git a/include/ipa/raspberrypi.h b/include/ipa/raspberrypi.h\nindex c109469e..74954db2 100644\n--- a/include/ipa/raspberrypi.h\n+++ b/include/ipa/raspberrypi.h\n@@ -51,6 +51,7 @@ static const ControlInfoMap RPiControls = {\n \t{ &controls::Brightness, ControlInfo(-1.0f, 1.0f) },\n \t{ &controls::Contrast, ControlInfo(0.0f, 32.0f) },\n \t{ &controls::Saturation, ControlInfo(0.0f, 32.0f) },\n+\t{ &controls::FrameDurations, ControlInfo(1.0e3f, 1.0e9f) }\n };\n \n } /* namespace libcamera */\ndiff --git a/src/ipa/raspberrypi/cam_helper.cpp b/src/ipa/raspberrypi/cam_helper.cpp\nindex 7f05d2c6..06732241 100644\n--- a/src/ipa/raspberrypi/cam_helper.cpp\n+++ b/src/ipa/raspberrypi/cam_helper.cpp\n@@ -34,8 +34,10 @@ CamHelper *CamHelper::Create(std::string const &cam_name)\n \treturn nullptr;\n }\n \n-CamHelper::CamHelper(MdParser *parser)\n-\t: parser_(parser), initialized_(false)\n+CamHelper::CamHelper(MdParser *parser, unsigned int maxFrameLength,\n+\t\t unsigned int frameIntegrationDiff)\n+\t: parser_(parser), initialized_(false), maxFrameLength_(maxFrameLength),\n+\t frameIntegrationDiff_(frameIntegrationDiff)\n {\n }\n \n@@ -56,6 +58,38 @@ double CamHelper::Exposure(uint32_t exposure_lines) const\n \treturn exposure_lines * mode_.line_length / 1000.0;\n }\n \n+uint32_t CamHelper::GetVBlanking(double &exposure, double minFrameDuration,\n+\t\t\t\t double maxFrameDuration) const\n+{\n+\tuint32_t frameLengthMin, frameLengthMax, vblank;\n+\tuint32_t exposureLines = ExposureLines(exposure);\n+\n+\tassert(initialized_);\n+\t/*\n+\t * Clip frame length by the frame duration range and the maximum allowable\n+\t * value in the sensor, given by maxFrameLength_.\n+\t */\n+\tframeLengthMin = std::min<uint32_t>(1e3 * minFrameDuration / mode_.line_length,\n+\t\t\t\t\t maxFrameLength_);\n+\tframeLengthMax = std::min<uint32_t>(1e3 * maxFrameDuration / mode_.line_length,\n+\t\t\t\t\t maxFrameLength_);\n+\t/*\n+\t * Limit the exposure to the maximum frame duration requested, and\n+\t * re-calculate if it has been clipped.\n+\t */\n+\texposureLines = std::min(frameLengthMax - frameIntegrationDiff_,\n+\t\t\t\t exposureLines);\n+\texposure = Exposure(exposureLines);\n+\n+\t/* Limit the vblank to the range allowed by the frame length limits. */\n+\tvblank = std::max<uint32_t>(mode_.height, exposureLines) -\n+\t\t mode_.height + frameIntegrationDiff_;\n+\tvblank = std::max(vblank, frameLengthMin - mode_.height);\n+\tvblank = std::min(vblank, frameLengthMax - mode_.height);\n+\n+\treturn vblank;\n+}\n+\n void CamHelper::SetCameraMode(const CameraMode &mode)\n {\n \tmode_ = mode;\ndiff --git a/src/ipa/raspberrypi/cam_helper.hpp b/src/ipa/raspberrypi/cam_helper.hpp\nindex 0c8aa29a..fdcdbddb 100644\n--- a/src/ipa/raspberrypi/cam_helper.hpp\n+++ b/src/ipa/raspberrypi/cam_helper.hpp\n@@ -68,12 +68,15 @@ class CamHelper\n {\n public:\n \tstatic CamHelper *Create(std::string const &cam_name);\n-\tCamHelper(MdParser *parser);\n+\tCamHelper(MdParser *parser, unsigned int maxFrameLength,\n+\t\t unsigned int frameIntegrationDiff);\n \tvirtual ~CamHelper();\n \tvoid SetCameraMode(const CameraMode &mode);\n \tMdParser &Parser() const { return *parser_; }\n \tuint32_t ExposureLines(double exposure_us) const;\n \tdouble Exposure(uint32_t exposure_lines) const; // in us\n+\tvirtual uint32_t GetVBlanking(double &exposure_us, double minFrameDuration,\n+\t\t\t\t double maxFrameDuration) const;\n \tvirtual uint32_t GainCode(double gain) const = 0;\n \tvirtual double Gain(uint32_t gain_code) const = 0;\n \tvirtual void GetDelays(int &exposure_delay, int &gain_delay) const;\n@@ -83,10 +86,20 @@ public:\n \tvirtual unsigned int MistrustFramesStartup() const;\n \tvirtual unsigned int MistrustFramesModeSwitch() const;\n \tvirtual CamTransform GetOrientation() const;\n+\n protected:\n \tMdParser *parser_;\n \tCameraMode mode_;\n+\n+private:\n \tbool initialized_;\n+\t/* Largest possible frame length, in units of lines. */\n+\tunsigned int maxFrameLength_;\n+\t/*\n+\t * Smallest difference between the frame length and integration time,\n+\t * in units of lines.\n+\t */\n+\tunsigned int frameIntegrationDiff_;\n };\n \n // This is for registering camera helpers with the system, so that the\ndiff --git a/src/ipa/raspberrypi/cam_helper_imx219.cpp b/src/ipa/raspberrypi/cam_helper_imx219.cpp\nindex 35c6597c..fd95a31a 100644\n--- a/src/ipa/raspberrypi/cam_helper_imx219.cpp\n+++ b/src/ipa/raspberrypi/cam_helper_imx219.cpp\n@@ -50,13 +50,22 @@ public:\n \tunsigned int MistrustFramesModeSwitch() const override;\n \tbool SensorEmbeddedDataPresent() const override;\n \tCamTransform GetOrientation() const override;\n+\n+private:\n+\t/*\n+\t * Smallest difference between the frame length and integration time,\n+\t * in units of lines.\n+\t */\n+\tstatic constexpr int frameIntegrationDiff = 4;\n+\t/* Largest possible frame length, in units of lines. */\n+\tstatic constexpr int maxFrameLength = 0xffff;\n };\n \n CamHelperImx219::CamHelperImx219()\n #if ENABLE_EMBEDDED_DATA\n \t: CamHelper(new MdParserImx219())\n #else\n-\t: CamHelper(new MdParserRPi())\n+\t: CamHelper(new MdParserRPi(), maxFrameLength, frameIntegrationDiff)\n #endif\n {\n }\ndiff --git a/src/ipa/raspberrypi/cam_helper_imx477.cpp b/src/ipa/raspberrypi/cam_helper_imx477.cpp\nindex 69544456..4a1cab76 100644\n--- a/src/ipa/raspberrypi/cam_helper_imx477.cpp\n+++ b/src/ipa/raspberrypi/cam_helper_imx477.cpp\n@@ -39,10 +39,19 @@ public:\n \tdouble Gain(uint32_t gain_code) const override;\n \tbool SensorEmbeddedDataPresent() const override;\n \tCamTransform GetOrientation() const override;\n+\n+private:\n+\t/*\n+\t * Smallest difference between the frame length and integration time,\n+\t * in units of lines.\n+\t */\n+\tstatic constexpr int frameIntegrationDiff = 22;\n+\t/* Largest possible frame length, in units of lines. */\n+\tstatic constexpr int maxFrameLength = 0xffdc;\n };\n \n CamHelperImx477::CamHelperImx477()\n-\t: CamHelper(new MdParserImx477())\n+\t: CamHelper(new MdParserImx477(), maxFrameLength, frameIntegrationDiff)\n {\n }\n \ndiff --git a/src/ipa/raspberrypi/cam_helper_ov5647.cpp b/src/ipa/raspberrypi/cam_helper_ov5647.cpp\nindex 3dbcb164..d814fa90 100644\n--- a/src/ipa/raspberrypi/cam_helper_ov5647.cpp\n+++ b/src/ipa/raspberrypi/cam_helper_ov5647.cpp\n@@ -22,6 +22,15 @@ public:\n \tunsigned int HideFramesModeSwitch() const override;\n \tunsigned int MistrustFramesStartup() const override;\n \tunsigned int MistrustFramesModeSwitch() const override;\n+\n+private:\n+\t/*\n+\t * Smallest difference between the frame length and integration time,\n+\t * in units of lines.\n+\t */\n+\tstatic constexpr int frameIntegrationDiff = 4;\n+\t/* Largest possible frame length, in units of lines. */\n+\tstatic constexpr int maxFrameLength = 0xffff;\n };\n \n /*\n@@ -30,7 +39,7 @@ public:\n */\n \n CamHelperOv5647::CamHelperOv5647()\n-\t: CamHelper(new MdParserRPi())\n+\t: CamHelper(new MdParserRPi(), maxFrameLength, frameIntegrationDiff)\n {\n }\n \ndiff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\nindex 3bcc0815..1af5e74a 100644\n--- a/src/ipa/raspberrypi/raspberrypi.cpp\n+++ b/src/ipa/raspberrypi/raspberrypi.cpp\n@@ -53,6 +53,8 @@ namespace libcamera {\n /* Configure the sensor with these values initially. */\n #define DEFAULT_ANALOGUE_GAIN 1.0\n #define DEFAULT_EXPOSURE_TIME 20000\n+#define DEFAULT_MIN_FRAME_DURATION (1e6 / 30.0)\n+#define DEFAULT_MAX_FRAME_DURATION (1e6 / 0.01)\n \n LOG_DEFINE_CATEGORY(IPARPI)\n \n@@ -136,6 +138,9 @@ private:\n \t/* LS table allocation passed in from the pipeline handler. */\n \tuint32_t lsTableHandle_;\n \tvoid *lsTable_;\n+\n+\t/* Frame duration (1/fps) given in microseconds. */\n+\tdouble minFrameDuration_, maxFrameDuration_;\n };\n \n int IPARPi::init(const IPASettings &settings)\n@@ -252,13 +257,20 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n \t\tcontroller_.Initialise();\n \t\tcontrollerInit_ = true;\n \n-\t\t/* Calculate initial values for gain and exposure. */\n+\t\t/* Calculate initial values for gain, vblank, and exposure */\n+\t\tminFrameDuration_ = DEFAULT_MIN_FRAME_DURATION;\n+\t\tmaxFrameDuration_ = DEFAULT_MAX_FRAME_DURATION;\n+\n+\t\tdouble exposure = DEFAULT_EXPOSURE_TIME;\n+\t\tint32_t vblank = helper_->GetVBlanking(exposure, minFrameDuration_,\n+\t\t\t\t\t\t maxFrameDuration_);\n+\t\tint32_t exposure_lines = helper_->ExposureLines(exposure);\n \t\tint32_t gain_code = helper_->GainCode(DEFAULT_ANALOGUE_GAIN);\n-\t\tint32_t exposure_lines = helper_->ExposureLines(DEFAULT_EXPOSURE_TIME);\n \n \t\tControlList ctrls(unicam_ctrls_);\n-\t\tctrls.set(V4L2_CID_ANALOGUE_GAIN, gain_code);\n+\t\tctrls.set(V4L2_CID_VBLANK, vblank);\n \t\tctrls.set(V4L2_CID_EXPOSURE, exposure_lines);\n+\t\tctrls.set(V4L2_CID_ANALOGUE_GAIN, gain_code);\n \n \t\tIPAOperationData op;\n \t\top.operation = RPI_IPA_ACTION_V4L2_SET_STAGGERED;\n@@ -630,6 +642,17 @@ void IPARPi::queueRequest(const ControlList &controls)\n \t\t\tbreak;\n \t\t}\n \n+\t\tcase controls::FRAME_DURATIONS: {\n+\t\t\tauto frameDurations = ctrl.second.get<Span<const float>>();\n+\n+\t\t\t/* This will be applied once AGC recalculations occur. */\n+\t\t\tminFrameDuration_ = frameDurations[0];\n+\t\t\tmaxFrameDuration_ = frameDurations[1];\n+\t\t\tlibcameraMetadata_.set(controls::FrameDurations,\n+\t\t\t\t\t { frameDurations[0], frameDurations[1] });\n+\t\t\tbreak;\n+\t\t}\n+\n \t\tdefault:\n \t\t\tLOG(IPARPI, Warning)\n \t\t\t\t<< \"Ctrl \" << controls::controls.at(ctrl.first)->name()\n@@ -795,7 +818,12 @@ void IPARPi::applyAGC(const struct AgcStatus *agcStatus)\n \top.operation = RPI_IPA_ACTION_V4L2_SET_STAGGERED;\n \n \tint32_t gain_code = helper_->GainCode(agcStatus->analogue_gain);\n-\tint32_t exposure_lines = helper_->ExposureLines(agcStatus->shutter_time);\n+\n+\t/* GetVBlanking might clip exposure time to the fps limits. */\n+\tdouble exposure = agcStatus->shutter_time;\n+\tint32_t vblanking = helper_->GetVBlanking(exposure, minFrameDuration_,\n+\t\t\t\t\t\t maxFrameDuration_);\n+\tint32_t exposure_lines = helper_->ExposureLines(exposure);\n \n \tif (unicam_ctrls_.find(V4L2_CID_ANALOGUE_GAIN) == unicam_ctrls_.end()) {\n \t\tLOG(IPARPI, Error) << \"Can't find analogue gain control\";\n@@ -807,14 +835,20 @@ void IPARPi::applyAGC(const struct AgcStatus *agcStatus)\n \t\treturn;\n \t}\n \n-\tLOG(IPARPI, Debug) << \"Applying AGC Exposure: \" << agcStatus->shutter_time\n-\t\t\t << \" (Shutter lines: \" << exposure_lines << \") Gain: \"\n+\tLOG(IPARPI, Debug) << \"Applying AGC Exposure: \" << exposure\n+\t\t\t << \" (Shutter lines: \" << exposure_lines << \", AGC requested \"\n+\t\t\t << agcStatus->shutter_time << \") Gain: \"\n \t\t\t << agcStatus->analogue_gain << \" (Gain Code: \"\n \t\t\t << gain_code << \")\";\n \n \tControlList ctrls(unicam_ctrls_);\n-\tctrls.set(V4L2_CID_ANALOGUE_GAIN, gain_code);\n+\t/*\n+\t * VBLANK must be set before EXPOSURE as the former will adjust the\n+\t * limits of the latter control.\n+\t */\n+\tctrls.set(V4L2_CID_VBLANK, vblanking);\n \tctrls.set(V4L2_CID_EXPOSURE, exposure_lines);\n+\tctrls.set(V4L2_CID_ANALOGUE_GAIN, gain_code);\n \top.controls.push_back(ctrls);\n \tqueueFrameAction.emit(0, op);\n }\ndiff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\nindex 21a1d7f7..948290e2 100644\n--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n@@ -1159,7 +1159,9 @@ void RPiCameraData::queueFrameAction(unsigned int frame, const IPAOperationData\n \t\tif (!staggeredCtrl_) {\n \t\t\tstaggeredCtrl_.init(unicam_[Unicam::Image].dev(),\n \t\t\t\t\t { { V4L2_CID_ANALOGUE_GAIN, action.data[0] },\n+\t\t\t\t\t { V4L2_CID_VBLANK, action.data[1] },\n \t\t\t\t\t { V4L2_CID_EXPOSURE, action.data[1] } });\n+\n \t\t\tsensorMetadata_ = action.data[2];\n \t\t}\n \n", "prefixes": [ "libcamera-devel", "v2", "2/3" ] }