Show a patch.

GET /api/patches/15203/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 15203,
    "url": "https://patchwork.libcamera.org/api/patches/15203/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/15203/",
    "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": "<20211221052854.2690659-3-paul.elder@ideasonboard.com>",
    "date": "2021-12-21T05:28:54",
    "name": "[libcamera-devel,2/2] android: Plumb tonemap curves",
    "commit_ref": null,
    "pull_url": null,
    "state": "not-applicable",
    "archived": false,
    "hash": "4ae8474417191ea406019e5b1ad0e0b112b2c154",
    "submitter": {
        "id": 17,
        "url": "https://patchwork.libcamera.org/api/people/17/?format=api",
        "name": "Paul Elder",
        "email": "paul.elder@ideasonboard.com"
    },
    "delegate": {
        "id": 17,
        "url": "https://patchwork.libcamera.org/api/users/17/?format=api",
        "username": "epaul",
        "first_name": "Paul",
        "last_name": "Elder",
        "email": "paul.elder@ideasonboard.com"
    },
    "mbox": "https://patchwork.libcamera.org/patch/15203/mbox/",
    "series": [
        {
            "id": 2856,
            "url": "https://patchwork.libcamera.org/api/series/2856/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=2856",
            "date": "2021-12-21T05:28:52",
            "name": "android: Tonemapping",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/2856/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/15203/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/15203/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 E2C9DBF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 21 Dec 2021 05:29:28 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 943F96090C;\n\tTue, 21 Dec 2021 06:29: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 A9A8A608E9\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 21 Dec 2021 06:29:24 +0100 (CET)",
            "from pyrite.mediacom.info (unknown\n\t[IPv6:2604:2d80:ad90:fb00:96fd:8874:873:6c16])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 819FF881;\n\tTue, 21 Dec 2021 06:29:23 +0100 (CET)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"fQC0z+i5\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1640064564;\n\tbh=omYf7ekd3m0/xp2eFT75886be4ezB/yS1o4HRPei9Y0=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=fQC0z+i5XR4CNa4NTnAomIe4DD6u1h+H/NRfYrEc3RB7S/gvnEjt3t95eDAzXNy0G\n\tYepIUNJ0dptfonn5bPyVnoviJEPvK3zgBXnIJCmOsJyTTmRm8TqPVBNXNosd1dzAiJ\n\tH+XPMVYNvDCwuz50EMNQdYMXYm6uGwYDh1ODMc8M=",
        "From": "Paul Elder <paul.elder@ideasonboard.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Mon, 20 Dec 2021 23:28:54 -0600",
        "Message-Id": "<20211221052854.2690659-3-paul.elder@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.27.0",
        "In-Reply-To": "<20211221052854.2690659-1-paul.elder@ideasonboard.com>",
        "References": "<20211221052854.2690659-1-paul.elder@ideasonboard.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH 2/2] android: Plumb tonemap curves",
        "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": "Plumb everything related to tonemaps:\n- checking for manual post processing capability\n- static metadata: set available modes\n- static metadata: enable keys (if the libcamera camera supports\n  tonemapping)\n- fill out template fields\n- converting between the android tonemap controls and libcamera tonemap\n  controls (for request and result)\n\nNotably, for sending the tonemap in the request, we build the tonemap\nincrementally. That is, if the red, green, and blue parts of the curve\nare passed in separate requests, we \"pool\" them together into a single\ncurve and pass it to the camera. As libcamera will have its own request\ncontrol caching, we only send the tonemap curve to libcamera when at\nleast one of the three curves is provided.\n\nSigned-off-by: Paul Elder <paul.elder@ideasonboard.com>\n---\n src/android/camera_capabilities.cpp | 113 +++++++++++++++++++\n src/android/camera_device.cpp       | 162 ++++++++++++++++++++++++++++\n src/android/camera_device.h         |   3 +\n 3 files changed, 278 insertions(+)",
    "diff": "diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp\nindex cb5ea5e9..2ce465aa 100644\n--- a/src/android/camera_capabilities.cpp\n+++ b/src/android/camera_capabilities.cpp\n@@ -281,6 +281,8 @@ bool CameraCapabilities::validateManualSensorCapability()\n \n bool CameraCapabilities::validateManualPostProcessingCapability()\n {\n+\tcamera_metadata_ro_entry_t entry;\n+\n \tconst char *noMode = \"Manual post processing capability unavailable: \";\n \n \tif (!staticMetadata_->entryContains<uint8_t>(ANDROID_CONTROL_AWB_AVAILABLE_MODES,\n@@ -307,6 +309,28 @@ bool CameraCapabilities::validateManualPostProcessingCapability()\n \t\treturn false;\n \t}\n \n+\tbool found = staticMetadata_->getEntry(ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES, &entry);\n+\tif (!found) {\n+\t\tLOG(HAL, Info) << noMode << \"missing tonemapping\";\n+\t\treturn false;\n+\t}\n+\n+\tstd::set<uint8_t> tonemapModes;\n+\tfor (unsigned int i = 0; i < entry.count; i++)\n+\t\ttonemapModes.insert(entry.data.u8[i]);\n+\n+\tif ((!tonemapModes.count(ANDROID_TONEMAP_MODE_CONTRAST_CURVE) &&\n+\t     !(tonemapModes.count(ANDROID_TONEMAP_MODE_GAMMA_VALUE) &&\n+\t       tonemapModes.count(ANDROID_TONEMAP_MODE_PRESET_CURVE))) ||\n+\t    !tonemapModes.count(ANDROID_TONEMAP_MODE_FAST) ||\n+\t    !tonemapModes.count(ANDROID_TONEMAP_MODE_HIGH_QUALITY)) {\n+\t\tLOG(HAL, Info)\n+\t\t\t<< noMode\n+\t\t\t<< \"tonemap modes must contain at least {contrast, fast, hq} \"\n+\t\t\t<< \"or {gamma, preset, fast, hq}\";\n+\t\treturn false;\n+\t}\n+\n \t/*\n \t * \\todo return true here after we satisfy all the requirements:\n \t * https://developer.android.com/reference/android/hardware/camera2/CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING\n@@ -1165,6 +1189,77 @@ int CameraCapabilities::initializeStaticMetadata()\n \t\tavailableResultKeys_.insert(ANDROID_EDGE_MODE);\n \t}\n \n+\tstd::vector<uint8_t> availableTonemapModes;\n+\tbool tonemapGammaSupported = false;\n+\tbool tonemapPresetSupported = false;\n+\tconst auto tonemapModeInfo = controlsInfo.find(&controls::TonemapMode);\n+\tif (tonemapModeInfo != controlsInfo.end()) {\n+\t\tfor (const auto &value : tonemapModeInfo->second.values()) {\n+\t\t\tuint8_t mode;\n+\t\t\tswitch (value.get<int32_t>()) {\n+\t\t\tcase controls::TonemapModeContrastCurve:\n+\t\t\t\tmode = ANDROID_TONEMAP_MODE_CONTRAST_CURVE;\n+\t\t\t\tbreak;\n+\t\t\tcase controls::TonemapModeFast:\n+\t\t\t\tmode = ANDROID_TONEMAP_MODE_FAST;\n+\t\t\t\tbreak;\n+\t\t\tcase controls::TonemapModeHighQuality:\n+\t\t\t\tmode = ANDROID_TONEMAP_MODE_HIGH_QUALITY;\n+\t\t\t\tbreak;\n+\t\t\tcase controls::TonemapModeGammaValue:\n+\t\t\t\tmode = ANDROID_TONEMAP_MODE_GAMMA_VALUE;\n+\t\t\t\ttonemapGammaSupported = true;\n+\t\t\t\tbreak;\n+\t\t\tcase controls::TonemapModePresetCurve:\n+\t\t\t\tmode = ANDROID_TONEMAP_MODE_PRESET_CURVE;\n+\t\t\t\ttonemapPresetSupported = true;\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tLOG(HAL, Error) << \"Unknown tonemap mode\";\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tavailableTonemapModes.push_back(mode);\n+\t\t}\n+\t}\n+\n+\t/* \\todo Figure out how to report TonemapCurve ControlInfo */\n+\tconst auto tonemapSizeInfo = controlsInfo.find(&controls::TonemapCurveSize);\n+\tif (!availableTonemapModes.empty() &&\n+\t    (tonemapSizeInfo != controlsInfo.end())) {\n+\t\t/* Available tonemap modes */\n+\t\tstaticMetadata_->addEntry(ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES,\n+\t\t\t\t\t  availableTonemapModes);\n+\t\tavailableCharacteristicsKeys_.insert(ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES);\n+\n+\t\t/* Tonemap size */\n+\t\tint32_t tonemapMaxCurvePoints = tonemapSizeInfo->second.max().get<int32_t>();\n+\t\tstaticMetadata_->addEntry(ANDROID_TONEMAP_MAX_CURVE_POINTS,\n+\t\t\t\t\t  tonemapMaxCurvePoints);\n+\t\tavailableCharacteristicsKeys_.insert(ANDROID_TONEMAP_MAX_CURVE_POINTS);\n+\n+\t\t/* Tonemap mode */\n+\t\tavailableRequestKeys_.insert(ANDROID_TONEMAP_MODE);\n+\t\tavailableResultKeys_.insert(ANDROID_TONEMAP_MODE);\n+\n+\t\t/* Tonemap curve */\n+\t\tavailableRequestKeys_.insert(ANDROID_TONEMAP_CURVE_RED);\n+\t\tavailableRequestKeys_.insert(ANDROID_TONEMAP_CURVE_GREEN);\n+\t\tavailableRequestKeys_.insert(ANDROID_TONEMAP_CURVE_BLUE);\n+\t\tavailableResultKeys_.insert(ANDROID_TONEMAP_CURVE_RED);\n+\t\tavailableResultKeys_.insert(ANDROID_TONEMAP_CURVE_GREEN);\n+\t\tavailableResultKeys_.insert(ANDROID_TONEMAP_CURVE_BLUE);\n+\n+\t\tif (tonemapGammaSupported) {\n+\t\t\tavailableRequestKeys_.insert(ANDROID_TONEMAP_GAMMA);\n+\t\t\tavailableResultKeys_.insert(ANDROID_TONEMAP_GAMMA);\n+\t\t}\n+\n+\t\tif (tonemapPresetSupported) {\n+\t\t\tavailableRequestKeys_.insert(ANDROID_TONEMAP_PRESET_CURVE);\n+\t\t\tavailableResultKeys_.insert(ANDROID_TONEMAP_PRESET_CURVE);\n+\t\t}\n+\t}\n+\n \t/* JPEG static metadata. */\n \n \t/*\n@@ -1894,6 +1989,12 @@ std::unique_ptr<CameraMetadata> CameraCapabilities::requestTemplatePreview() con\n \t\trequestTemplate->addEntry(ANDROID_SHADING_MODE, shadingMode);\n \t}\n \n+\tif (staticMetadata_->entryContains<uint8_t>(ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES,\n+\t\t\t\t\t\t    ANDROID_TONEMAP_MODE_FAST)) {\n+\t\tuint8_t tonemapMode = ANDROID_TONEMAP_MODE_FAST;\n+\t\trequestTemplate->addEntry(ANDROID_TONEMAP_MODE, tonemapMode);\n+\t}\n+\n \treturn requestTemplate;\n }\n \n@@ -1922,6 +2023,12 @@ std::unique_ptr<CameraMetadata> CameraCapabilities::requestTemplateStill() const\n \t\tstillTemplate->appendEntry(ANDROID_NOISE_REDUCTION_MODE, noiseReduction);\n \t}\n \n+\tif (staticMetadata_->entryContains<uint8_t>(ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES,\n+\t\t\t\t\t\t    ANDROID_TONEMAP_MODE_HIGH_QUALITY)) {\n+\t\tuint8_t tonemapMode = ANDROID_TONEMAP_MODE_HIGH_QUALITY;\n+\t\tstillTemplate->appendEntry(ANDROID_TONEMAP_MODE, tonemapMode);\n+\t}\n+\n \treturn stillTemplate;\n }\n \n@@ -1945,6 +2052,12 @@ std::unique_ptr<CameraMetadata> CameraCapabilities::requestTemplateVideo() const\n \t\tpreviewTemplate->appendEntry(ANDROID_EDGE_MODE, edgeMode);\n \t}\n \n+\tif (staticMetadata_->entryContains<uint8_t>(ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES,\n+\t\t\t\t\t\t    ANDROID_TONEMAP_MODE_FAST)) {\n+\t\tuint8_t tonemapMode = ANDROID_TONEMAP_MODE_FAST;\n+\t\tpreviewTemplate->appendEntry(ANDROID_TONEMAP_MODE, tonemapMode);\n+\t}\n+\n \t/*\n \t * Assume the AE_AVAILABLE_TARGET_FPS_RANGE static metadata\n \t * has been assembled as {{min, max} {max, max}}.\ndiff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\nindex 7be0ce45..7cffb4b1 100644\n--- a/src/android/camera_device.cpp\n+++ b/src/android/camera_device.cpp\n@@ -1014,6 +1014,95 @@ int CameraDevice::processControls(Camera3RequestDescriptor *descriptor)\n \t\tcontrols.set(controls::LensShadingMode, shadingMode);\n \t}\n \n+\tif (settings.getEntry(ANDROID_TONEMAP_MODE, &entry)) {\n+\t\tconst int32_t data = static_cast<int32_t>(*entry.data.u8);\n+\t\tint32_t tonemapMode;\n+\t\tswitch (data) {\n+\t\tcase ANDROID_TONEMAP_MODE_CONTRAST_CURVE:\n+\t\t\ttonemapMode = controls::TonemapModeContrastCurve;\n+\t\t\tbreak;\n+\t\tcase ANDROID_TONEMAP_MODE_FAST:\n+\t\t\ttonemapMode = controls::TonemapModeFast;\n+\t\t\tbreak;\n+\t\tcase ANDROID_TONEMAP_MODE_HIGH_QUALITY:\n+\t\t\ttonemapMode = controls::TonemapModeHighQuality;\n+\t\t\tbreak;\n+\t\tcase ANDROID_TONEMAP_MODE_GAMMA_VALUE:\n+\t\t\ttonemapMode = controls::TonemapModeGammaValue;\n+\t\t\tbreak;\n+\t\tcase ANDROID_TONEMAP_MODE_PRESET_CURVE:\n+\t\t\ttonemapMode = controls::TonemapModePresetCurve;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tLOG(HAL, Error)\n+\t\t\t\t<< \"Unknown tonemap mode: \" << data;\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tcontrols.set(controls::TonemapMode, tonemapMode);\n+\t}\n+\n+\tbool curveUpdated = false;\n+\ttonemapCurve.resize(3);\n+\tstatic std::map<camera_metadata_tag, unsigned int> curveTags = {\n+\t\t{ ANDROID_TONEMAP_CURVE_RED,   0 },\n+\t\t{ ANDROID_TONEMAP_CURVE_GREEN, 1 },\n+\t\t{ ANDROID_TONEMAP_CURVE_BLUE,  2 },\n+\t};\n+\n+\tfor (const std::pair<camera_metadata_tag, unsigned int> &tag : curveTags) {\n+\t\tif (!settings.getEntry(tag.first, &entry))\n+\t\t\tcontinue;\n+\n+\t\ttonemapCurve[tag.second].resize(entry.count);\n+\t\tfor (unsigned int i = 0; i < entry.count; i++)\n+\t\t\ttonemapCurve[tag.second][i] = *(entry.data.f + i);\n+\n+\t\tcurveUpdated = true;\n+\t}\n+\n+\tif (curveUpdated) {\n+\t\tsize_t size = std::max(tonemapCurve[0].size(),\n+\t\t\t\t       tonemapCurve[1].size());\n+\t\tsize = std::max(size, tonemapCurve[2].size());\n+\t\tcontrols.set(controls::TonemapCurveSize, size);\n+\n+\t\tstd::vector<float> curve;\n+\t\tcurve.resize(3 * size);\n+\t\tcurve.insert(curve.begin(),\n+\t\t\t     tonemapCurve[0].begin(), tonemapCurve[0].end());\n+\t\tcurve.insert(curve.begin() + size,\n+\t\t\t     tonemapCurve[1].begin(), tonemapCurve[1].end());\n+\t\tcurve.insert(curve.begin() + 2 * size,\n+\t\t\t     tonemapCurve[2].begin(), tonemapCurve[2].end());\n+\t\tcontrols.set(controls::TonemapCurve, curve);\n+\t}\n+\n+\tif (settings.getEntry(ANDROID_TONEMAP_GAMMA, &entry)) {\n+\t\tconst float data = *entry.data.f;\n+\t\tcontrols.set(controls::TonemapGamma, data);\n+\t}\n+\n+\tif (settings.getEntry(ANDROID_TONEMAP_PRESET_CURVE, &entry)) {\n+\t\tconst int32_t data = static_cast<int32_t>(*entry.data.u8);\n+\t\tint32_t presetCurve;\n+\t\tswitch (data) {\n+\t\tcase ANDROID_TONEMAP_PRESET_CURVE_SRGB:\n+\t\t\tpresetCurve = controls::TonemapPresetCurveSRGB;\n+\t\t\tbreak;\n+\t\tcase ANDROID_TONEMAP_PRESET_CURVE_REC709:\n+\t\t\tpresetCurve = controls::TonemapPresetCurveREC709;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tLOG(HAL, Error)\n+\t\t\t\t<< \"Unknown tonemap mode: \" << data;\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tcontrols.set(controls::TonemapPresetCurve, presetCurve);\n+\n+\t}\n+\n \treturn 0;\n }\n \n@@ -1812,6 +1901,79 @@ CameraDevice::getResultMetadata(const Camera3RequestDescriptor &descriptor) cons\n \t\t}\n \t}\n \n+\tif (metadata.contains(controls::TonemapMode)) {\n+\t\tbool valid;\n+\t\tswitch (metadata.get(controls::TonemapMode)) {\n+\t\tcase controls::TonemapModeContrastCurve:\n+\t\t\tvalue = ANDROID_TONEMAP_MODE_CONTRAST_CURVE;\n+\t\t\tvalid = true;\n+\t\t\tbreak;\n+\t\tcase controls::TonemapModeFast:\n+\t\t\tvalue = ANDROID_TONEMAP_MODE_FAST;\n+\t\t\tvalid = true;\n+\t\t\tbreak;\n+\t\tcase controls::TonemapModeHighQuality:\n+\t\t\tvalue = ANDROID_TONEMAP_MODE_HIGH_QUALITY;\n+\t\t\tvalid = true;\n+\t\t\tbreak;\n+\t\tcase controls::TonemapModeGammaValue:\n+\t\t\tvalue = ANDROID_TONEMAP_MODE_GAMMA_VALUE;\n+\t\t\tvalid = true;\n+\t\t\tbreak;\n+\t\tcase controls::TonemapModePresetCurve:\n+\t\t\tvalue = ANDROID_TONEMAP_MODE_PRESET_CURVE;\n+\t\t\tvalid = true;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tLOG(HAL, Error) << \"Invalid tonemap mode\";\n+\t\t\tvalid = false;\n+\t\t}\n+\n+\t\t/* Can be null on non-FULL */\n+\t\tif (valid)\n+\t\t\tresultMetadata->addEntry(ANDROID_TONEMAP_MODE, value);\n+\t}\n+\n+\tif (metadata.contains(controls::TonemapCurve) &&\n+\t    metadata.contains(controls::TonemapCurveSize)) {\n+\t\tsize_t size = metadata.get(controls::TonemapCurveSize);\n+\n+\t\tSpan<const float> curve = metadata.get(controls::TonemapCurve);\n+\t\tSpan<const float> red = curve.subspan(0, size);\n+\t\tSpan<const float> green = curve.subspan(size, size);\n+\t\tSpan<const float> blue = curve.subspan(2 * size, size);\n+\n+\t\tresultMetadata->addEntry(ANDROID_TONEMAP_CURVE_RED, red);\n+\t\tresultMetadata->addEntry(ANDROID_TONEMAP_CURVE_GREEN, green);\n+\t\tresultMetadata->addEntry(ANDROID_TONEMAP_CURVE_BLUE, blue);\n+\t}\n+\n+\tif (metadata.contains(controls::TonemapGamma)) {\n+\t\tfloat gamma = metadata.get(controls::TonemapGamma);\n+\t\tresultMetadata->addEntry(ANDROID_TONEMAP_GAMMA, gamma);\n+\t}\n+\n+\tif (metadata.contains(controls::TonemapPresetCurve)) {\n+\t\tbool valid;\n+\t\tswitch (metadata.get(controls::TonemapPresetCurve)) {\n+\t\tcase controls::TonemapPresetCurveSRGB:\n+\t\t\tvalue = ANDROID_TONEMAP_PRESET_CURVE_SRGB;\n+\t\t\tvalid = false;\n+\t\t\tbreak;\n+\t\tcase controls::TonemapPresetCurveREC709:\n+\t\t\tvalue = ANDROID_TONEMAP_PRESET_CURVE_REC709;\n+\t\t\tvalid = false;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tLOG(HAL, Error) << \"Invalid tonemap preset curve\";\n+\t\t\tvalid = false;\n+\t\t}\n+\n+\t\t/* Can be null on non-FULL */\n+\t\tif (valid)\n+\t\t\tresultMetadata->addEntry(ANDROID_TONEMAP_PRESET_CURVE, value);\n+\t}\n+\n \t/*\n \t * Return the result metadata pack even is not valid: get() will return\n \t * nullptr.\ndiff --git a/src/android/camera_device.h b/src/android/camera_device.h\nindex 01c269d3..2cab11c5 100644\n--- a/src/android/camera_device.h\n+++ b/src/android/camera_device.h\n@@ -140,5 +140,8 @@ private:\n \tfloat lastAnalogueGain_;\n \tfloat lastDigitalGain_;\n \n+\t/* Build the tonemap curve incrementally */\n+\tstd::vector<std::vector<float>> tonemapCurve;\n+\n \tCameraMetadata lastSettings_;\n };\n",
    "prefixes": [
        "libcamera-devel",
        "2/2"
    ]
}