Patch Detail
Show a patch.
GET /api/patches/3539/?format=api
{ "id": 3539, "url": "https://patchwork.libcamera.org/api/patches/3539/?format=api", "web_url": "https://patchwork.libcamera.org/patch/3539/", "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": "<20200425004533.26907-6-laurent.pinchart@ideasonboard.com>", "date": "2020-04-25T00:45:31", "name": "[libcamera-devel,v5,5/7] libcamera: controls: Reorder and update description of existing controls", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "f56aaa941e96cd196da431be90c2daa1dfe59570", "submitter": { "id": 2, "url": "https://patchwork.libcamera.org/api/people/2/?format=api", "name": "Laurent Pinchart", "email": "laurent.pinchart@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/3539/mbox/", "series": [ { "id": 824, "url": "https://patchwork.libcamera.org/api/series/824/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=824", "date": "2020-04-25T00:45:26", "name": "Patchset for libcamera controls", "version": 5, "mbox": "https://patchwork.libcamera.org/series/824/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/3539/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/3539/checks/", "tags": {}, "headers": { "Return-Path": "<laurent.pinchart@ideasonboard.com>", "Received": [ "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 2C42062F46\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 25 Apr 2020 02:45:54 +0200 (CEST)", "from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id B261CA2A;\n\tSat, 25 Apr 2020 02:45:53 +0200 (CEST)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"WWjP3ISN\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1587775553;\n\tbh=Wr1ZUSdGxzfgfnN8TbrmAFULWcf48CQEb2xYk2mYw1Q=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=WWjP3ISNzvJW93iFjfRRSU9mRkxMjS52RLYvyKwBZFPuKeGzMuSL7vgBxoq4NpaZE\n\thksxnOdLDrTNbSf9sdRpolLseiCYNuj/yCfbslrCXJJKVt6z0q3KeQ4Ps8X6XbSOht\n\t9X7JzPEesxK/WQc6A58PgB+MESCa06yZhHKVpNWk=", "From": "Laurent Pinchart <laurent.pinchart@ideasonboard.com>", "To": "libcamera-devel@lists.libcamera.org", "Date": "Sat, 25 Apr 2020 03:45:31 +0300", "Message-Id": "<20200425004533.26907-6-laurent.pinchart@ideasonboard.com>", "X-Mailer": "git-send-email 2.25.3", "In-Reply-To": "<20200425004533.26907-1-laurent.pinchart@ideasonboard.com>", "References": "<20200425004533.26907-1-laurent.pinchart@ideasonboard.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Subject": "[libcamera-devel] [PATCH v5 5/7] libcamera: controls: Reorder and\n\tupdate description of existing controls", "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": "Sat, 25 Apr 2020 00:45:55 -0000" }, "content": "From: Naushir Patuck <naush@raspberrypi.com>\n\nGroup AE, AWB, etc. controls together for accessibility.\n\nUpdate descriptions for Contrast, Brightness, and Saturation controls.\n\nUpdate the uvcvideo and vimc pipeline handlers to use the new\nbrightness, contrast and saturation units. UVC has no explicit units for\nthose controls, so map them with a best effort heuristic. For VIMC,\nhardcode the control range based on knowledge of the driver\nimplementation for simplicity.\n\nSigned-off-by: Naushir Patuck <naush@raspberrypi.com>\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n src/libcamera/control_ids.yaml | 42 +++++++-----\n src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 67 +++++++++++++++++---\n src/libcamera/pipeline/vimc/vimc.cpp | 29 ++++++---\n 3 files changed, 103 insertions(+), 35 deletions(-)", "diff": "diff --git a/src/libcamera/control_ids.yaml b/src/libcamera/control_ids.yaml\nindex d8bdb3829be4..f2ac052b3d3e 100644\n--- a/src/libcamera/control_ids.yaml\n+++ b/src/libcamera/control_ids.yaml\n@@ -25,23 +25,6 @@ controls:\n \n \\sa AeEnable\n \n- - AwbEnable:\n- type: bool\n- description: |\n- Enable or disable the AWB.\n-\n- - Brightness:\n- type: int32_t\n- description: Specify a fixed brightness parameter\n-\n- - Contrast:\n- type: int32_t\n- description: Specify a fixed contrast parameter\n-\n- - Saturation:\n- type: int32_t\n- description: Specify a fixed saturation parameter\n-\n - ExposureTime:\n type: int32_t\n description: |\n@@ -58,4 +41,29 @@ controls:\n colour channels. This value cannot be lower than 1.0.\n \n \\sa ExposureTime AeEnable\n+\n+ - Brightness:\n+ type: float\n+ description: |\n+ Specify a fixed brightness parameter. Positive values (up to 1.0)\n+ produce brighter images; negative values (up to -1.0) produce darker\n+ images and 0.0 leaves pixels unchanged.\n+\n+ - Contrast:\n+ type: float\n+ description: |\n+ Specify a fixed contrast parameter. Normal contrast is given by the\n+ value 1.0; larger values produce images with more contrast.\n+\n+ - AwbEnable:\n+ type: bool\n+ description: |\n+ Enable or disable the AWB.\n+\n+ - Saturation:\n+ type: float\n+ description: |\n+ Specify a fixed saturation parameter. Normal saturation is given by\n+ the value 1.0; larger values produce more saturated colours; 0.0\n+ produces a greyscale image.\n ...\ndiff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\nindex 452f38dcad2f..136d6d0af5d5 100644\n--- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n+++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n@@ -262,12 +262,29 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,\n \t\treturn -EINVAL;\n \n \tconst ControlInfo &v4l2Info = controls->infoMap()->at(cid);\n+\tint32_t min = v4l2Info.min().get<int32_t>();\n+\tint32_t def = v4l2Info.def().get<int32_t>();\n+\tint32_t max = v4l2Info.max().get<int32_t>();\n \n \t/*\n \t * See UVCCameraData::addControl() for explanations of the different\n \t * value mappings.\n \t */\n \tswitch (cid) {\n+\tcase V4L2_CID_BRIGHTNESS: {\n+\t\tfloat scale = std::max(max - def, def - min);\n+\t\tfloat fvalue = value.get<float>() * scale + def;\n+\t\tcontrols->set(cid, static_cast<int32_t>(lroundf(fvalue)));\n+\t\tbreak;\n+\t}\n+\n+\tcase V4L2_CID_SATURATION: {\n+\t\tfloat scale = def - min;\n+\t\tfloat fvalue = value.get<float>() * scale + min;\n+\t\tcontrols->set(cid, static_cast<int32_t>(lroundf(fvalue)));\n+\t\tbreak;\n+\t}\n+\n \tcase V4L2_CID_EXPOSURE_AUTO: {\n \t\tint32_t ivalue = value.get<bool>()\n \t\t\t ? V4L2_EXPOSURE_APERTURE_PRIORITY\n@@ -280,11 +297,8 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,\n \t\tcontrols->set(cid, value.get<int32_t>() / 100);\n \t\tbreak;\n \n+\tcase V4L2_CID_CONTRAST:\n \tcase V4L2_CID_GAIN: {\n-\t\tint32_t min = v4l2Info.min().get<int32_t>();\n-\t\tint32_t max = v4l2Info.max().get<int32_t>();\n-\t\tint32_t def = v4l2Info.def().get<int32_t>();\n-\n \t\tfloat m = (4.0f - 1.0f) / (max - def);\n \t\tfloat p = 1.0f - m * def;\n \n@@ -456,6 +470,38 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,\n \tint32_t def = v4l2Info.def().get<int32_t>();\n \n \tswitch (cid) {\n+\tcase V4L2_CID_BRIGHTNESS: {\n+\t\t/*\n+\t\t * The Brightness control is a float, with 0.0 mapped to the\n+\t\t * default value. The control range is [-1.0, 1.0], but the V4L2\n+\t\t * default may not be in the middle of the V4L2 range.\n+\t\t * Accommodate this by restricting the range of the libcamera\n+\t\t * control, but always within the maximum limits.\n+\t\t */\n+\t\tfloat scale = std::max(max - def, def - min);\n+\n+\t\tinfo = ControlInfo{\n+\t\t\t{ static_cast<float>(min - def) / scale },\n+\t\t\t{ static_cast<float>(max - def) / scale },\n+\t\t\t{ 0.0f }\n+\t\t};\n+\t\tbreak;\n+\t}\n+\n+\tcase V4L2_CID_SATURATION:\n+\t\t/*\n+\t\t * The Saturation control is a float, with 0.0 mapped to the\n+\t\t * minimum value (corresponding to a fully desaturated image)\n+\t\t * and 1.0 mapped to the default value. Calculate the maximum\n+\t\t * value accordingly.\n+\t\t */\n+\t\tinfo = ControlInfo{\n+\t\t\t{ 0.0f },\n+\t\t\t{ static_cast<float>(max - min) / (def - min) },\n+\t\t\t{ 1.0f }\n+\t\t};\n+\t\tbreak;\n+\n \tcase V4L2_CID_EXPOSURE_AUTO:\n \t\tinfo = ControlInfo{ false, true, true };\n \t\tbreak;\n@@ -472,14 +518,15 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,\n \t\t};\n \t\tbreak;\n \n+\tcase V4L2_CID_CONTRAST:\n \tcase V4L2_CID_GAIN: {\n \t\t/*\n-\t\t * The AnalogueGain control is a float, with 1.0 mapped to the\n-\t\t * default value. UVC doesn't specify units, and cameras have\n-\t\t * been seen to expose very different ranges for the gain\n-\t\t * control. Arbitrarily assume that the minimum and maximum\n-\t\t * values are respectively no lower than 0.5 and no higher than\n-\t\t * 4.0.\n+\t\t * The Contrast and AnalogueGain controls are floats, with 1.0\n+\t\t * mapped to the default value. UVC doesn't specify units, and\n+\t\t * cameras have been seen to expose very different ranges for\n+\t\t * the controls. Arbitrarily assume that the minimum and\n+\t\t * maximum values are respectively no lower than 0.5 and no\n+\t\t * higher than 4.0.\n \t\t */\n \t\tfloat m = (4.0f - 1.0f) / (max - def);\n \t\tfloat p = 1.0f - m * def;\ndiff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp\nindex c5eea3a01b0e..62279ef17102 100644\n--- a/src/libcamera/pipeline/vimc/vimc.cpp\n+++ b/src/libcamera/pipeline/vimc/vimc.cpp\n@@ -304,14 +304,24 @@ int PipelineHandlerVimc::processControls(VimcCameraData *data, Request *request)\n \n \tfor (auto it : request->controls()) {\n \t\tunsigned int id = it.first;\n-\t\tControlValue &value = it.second;\n+\t\tunsigned int offset;\n+\t\tuint32_t cid;\n \n-\t\tif (id == controls::Brightness)\n-\t\t\tcontrols.set(V4L2_CID_BRIGHTNESS, value);\n-\t\telse if (id == controls::Contrast)\n-\t\t\tcontrols.set(V4L2_CID_CONTRAST, value);\n-\t\telse if (id == controls::Saturation)\n-\t\t\tcontrols.set(V4L2_CID_SATURATION, value);\n+\t\tif (id == controls::Brightness) {\n+\t\t\tcid = V4L2_CID_BRIGHTNESS;\n+\t\t\toffset = 128;\n+\t\t} else if (id == controls::Contrast) {\n+\t\t\tcid = V4L2_CID_CONTRAST;\n+\t\t\toffset = 0;\n+\t\t} else if (id == controls::Saturation) {\n+\t\t\tcid = V4L2_CID_SATURATION;\n+\t\t\toffset = 0;\n+\t\t} else {\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tint32_t value = lroundf(it.second.get<float>() * 128 + offset);\n+\t\tcontrols.set(cid, utils::clamp(value, 0, 255));\n \t}\n \n \tfor (const auto &ctrl : controls)\n@@ -434,18 +444,21 @@ int VimcCameraData::init(MediaDevice *media)\n \tControlInfoMap::Map ctrls;\n \n \tfor (const auto &ctrl : controls) {\n-\t\tconst ControlInfo &info = ctrl.second;\n \t\tconst ControlId *id;\n+\t\tControlInfo info;\n \n \t\tswitch (ctrl.first->id()) {\n \t\tcase V4L2_CID_BRIGHTNESS:\n \t\t\tid = &controls::Brightness;\n+\t\t\tinfo = ControlInfo{ { -1.0f }, { 1.0f }, { 0.0f } };\n \t\t\tbreak;\n \t\tcase V4L2_CID_CONTRAST:\n \t\t\tid = &controls::Contrast;\n+\t\t\tinfo = ControlInfo{ { 0.0f }, { 2.0f }, { 1.0f } };\n \t\t\tbreak;\n \t\tcase V4L2_CID_SATURATION:\n \t\t\tid = &controls::Saturation;\n+\t\t\tinfo = ControlInfo{ { 0.0f }, { 2.0f }, { 1.0f } };\n \t\t\tbreak;\n \t\tdefault:\n \t\t\tcontinue;\n", "prefixes": [ "libcamera-devel", "v5", "5/7" ] }