Show a patch.

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

{
    "id": 10439,
    "url": "https://patchwork.libcamera.org/api/patches/10439/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/10439/",
    "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": "<20201116164918.2055-11-david.plowman@raspberrypi.com>",
    "date": "2020-11-16T16:49:18",
    "name": "[libcamera-devel,10/10] libcamera: src: ipa: raspberrypi: agc: Improve AE locked logic",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "d5fd1b7cbf2c54dee5cf03f63a26c600fcc2cc3c",
    "submitter": {
        "id": 42,
        "url": "https://patchwork.libcamera.org/api/people/42/?format=api",
        "name": "David Plowman",
        "email": "david.plowman@raspberrypi.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/10439/mbox/",
    "series": [
        {
            "id": 1464,
            "url": "https://patchwork.libcamera.org/api/series/1464/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=1464",
            "date": "2020-11-16T16:49:08",
            "name": "Raspberry Pi AGC",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/1464/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/10439/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/10439/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 0D9E4BE082\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 16 Nov 2020 16:49:39 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id CF907632D6;\n\tMon, 16 Nov 2020 17:49:38 +0100 (CET)",
            "from mail-wm1-x332.google.com (mail-wm1-x332.google.com\n\t[IPv6:2a00:1450:4864:20::332])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 85835632D1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 16 Nov 2020 17:49:34 +0100 (CET)",
            "by mail-wm1-x332.google.com with SMTP id s13so24199948wmh.4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 16 Nov 2020 08:49:34 -0800 (PST)",
            "from pi4-davidp.lan (plowpeople3.plus.com. [80.229.223.72])\n\tby smtp.gmail.com with ESMTPSA id\n\tq16sm23716973wrn.13.2020.11.16.08.49.32\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tMon, 16 Nov 2020 08:49:33 -0800 (PST)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=raspberrypi.com header.i=@raspberrypi.com\n\theader.b=\"U74fOlTh\"; 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\t:mime-version:content-transfer-encoding;\n\tbh=bc8pIXR1oLN0cPR7o76WwaFmRCJS7IeSD16dgScTV5Y=;\n\tb=U74fOlTh9+gRoGsA7I1ew8UZ8Gp0YnQ33ebmfHCu1139xp01lcQZxb9OJpt/4nYyoA\n\tt9WcREbC7Cy2IztwsFjvMWwaRhwTsoZPWPBIzf/uvksPkZm+oZHk3b7KUJX5bHmb4TZx\n\tjtw7kQyAuZFpH37rVTHRlL8Ytq4lRQZsW2jnz5avObmw0SfxURyHb8FBRunFXzH9j6ij\n\tSjk/HmXgFpD4cd5NNdrJlx/IF40Ld+VSUxeflPJ9ytjrLWukU0NRcOWQH+fSHtLz8uRJ\n\tFXpUSvOkkUCZn3jL90uLLEjaPqx+t+GQFHhsx+33xKTEXcqWm5houfMi3sG3iKfz3DI1\n\tp0XA==",
        "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:mime-version:content-transfer-encoding;\n\tbh=bc8pIXR1oLN0cPR7o76WwaFmRCJS7IeSD16dgScTV5Y=;\n\tb=HJjxV42W7uDyxOAKK2j6N1o3nhASgwXCNdclXGwC2X6vAWOYwgr3O0sQlraYmnUwiH\n\tHUNzYp8pdV2xlD5UWj/2H+j/cst1TA8E3w2LBQh5X9xpdrJnv0fSbFDbYeixElRaAU/r\n\tryNMvBnCIWXdmRRNnjtX6LkwmPAZ+8qFxpmfV0zK+T9whWkMqn2mULTEH48u7gT2WbHN\n\tEUQQpJVXZwjlty3iq9Zqj/4nwE9aEheq4f89sZALpuaIb5RTYf/489ZmLzcnQV78oK7/\n\tBRxWEPEk7sOHMN4oOFdh9f2Fut0fslRVvDhBBxJIatSXCNnaKhCdXcSUs4uuz6mgVWon\n\tvljA==",
        "X-Gm-Message-State": "AOAM5332MSFGntw0FN5df0HfjR2cayhqByWbzHJOMUoffT0Rrdzs8FSE\n\tdezBq9/graIb+598MKmEkjtIc8xoUnaGzg==",
        "X-Google-Smtp-Source": "ABdhPJzQczI9hMe766aBmspH5aNNtuon3uCub+duQ7RrywWrnOo6iU15nndMmoSjCjWCYnoSNyd4Lw==",
        "X-Received": "by 2002:a1c:3d05:: with SMTP id\n\tk5mr17131635wma.151.1605545373897; \n\tMon, 16 Nov 2020 08:49:33 -0800 (PST)",
        "From": "David Plowman <david.plowman@raspberrypi.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Mon, 16 Nov 2020 16:49:18 +0000",
        "Message-Id": "<20201116164918.2055-11-david.plowman@raspberrypi.com>",
        "X-Mailer": "git-send-email 2.20.1",
        "In-Reply-To": "<20201116164918.2055-1-david.plowman@raspberrypi.com>",
        "References": "<20201116164918.2055-1-david.plowman@raspberrypi.com>",
        "MIME-Version": "1.0",
        "Subject": "[libcamera-devel] [PATCH 10/10] libcamera: src: ipa: raspberrypi:\n\tagc: Improve AE locked logic",
        "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>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "Previously we required that the sensor absolutely reaches the target\nexposure, but this can fail if frame rates or analogue gains are\nlimited. Instead insist only that we get several frames with the same\nexposure time, analogue gain and that the algorithm's target exposure\nhasn't changed either.\n\nSigned-off-by: David Plowman <david.plowman@raspberrypi.com>\n---\n src/ipa/raspberrypi/controller/rpi/agc.cpp | 65 +++++++++++++---------\n src/ipa/raspberrypi/controller/rpi/agc.hpp |  3 +\n 2 files changed, 42 insertions(+), 26 deletions(-)",
    "diff": "diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp\nindex 93b46a28..7be74763 100644\n--- a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n+++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n@@ -164,6 +164,8 @@ Agc::Agc(Controller *controller)\n \tflicker_period_ = 0.0;\n \tfixed_shutter_ = 0;\n \tfixed_analogue_gain_ = 0.0;\n+\tmemset(&last_device_status_, 0, sizeof(last_device_status_));\n+\tlast_target_exposure_ = 0.0;\n }\n \n char const *Agc::Name() const\n@@ -264,8 +266,6 @@ void Agc::SwitchMode([[maybe_unused]] CameraMode const &camera_mode,\n \n void Agc::Prepare(Metadata *image_metadata)\n {\n-\tint lock_count = lock_count_;\n-\tlock_count_ = 0;\n \tstatus_.digital_gain = 1.0;\n \tfetchAwbStatus(image_metadata); // always fetch it so that Process knows it's been done\n \n@@ -289,32 +289,10 @@ void Agc::Prepare(Metadata *image_metadata)\n \t\t\t\tLOG(RPiAgc, Debug) << \"Use digital_gain \" << status_.digital_gain;\n \t\t\t\tLOG(RPiAgc, Debug) << \"Effective exposure \" << actual_exposure * status_.digital_gain;\n \t\t\t\t// Decide whether AEC/AGC has converged.\n-\t\t\t\t// Insist AGC is steady for MAX_LOCK_COUNT\n-\t\t\t\t// frames before we say we are \"locked\".\n-\t\t\t\t// (The hard-coded constants may need to\n-\t\t\t\t// become customisable.)\n-\t\t\t\tif (status_.target_exposure_value) {\n-#define MAX_LOCK_COUNT 3\n-\t\t\t\t\tdouble err = 0.10 * status_.target_exposure_value + 200;\n-\t\t\t\t\tif (actual_exposure <\n-\t\t\t\t\t\t    status_.target_exposure_value + err &&\n-\t\t\t\t\t    actual_exposure >\n-\t\t\t\t\t\t    status_.target_exposure_value - err)\n-\t\t\t\t\t\tlock_count_ =\n-\t\t\t\t\t\t\tstd::min(lock_count + 1,\n-\t\t\t\t\t\t\t\t MAX_LOCK_COUNT);\n-\t\t\t\t\telse if (actual_exposure <\n-\t\t\t\t\t\t\t status_.target_exposure_value + 1.5 * err &&\n-\t\t\t\t\t\t actual_exposure >\n-\t\t\t\t\t\t\t status_.target_exposure_value - 1.5 * err)\n-\t\t\t\t\t\tlock_count_ = lock_count;\n-\t\t\t\t\tLOG(RPiAgc, Debug) << \"Lock count: \" << lock_count_;\n-\t\t\t\t}\n+\t\t\t\tupdateLockStatus(device_status);\n \t\t\t}\n \t\t} else\n-\t\t\tLOG(RPiAgc, Debug) << Name() << \": no device metadata\";\n-\t\tstatus_.locked = lock_count_ >= MAX_LOCK_COUNT;\n-\t\t//printf(\"%s\\n\", status_.locked ? \"+++++++++\" : \"-\");\n+\t\t\tLOG(RPiAgc, Warning) << Name() << \": no device metadata\";\n \t\timage_metadata->Set(\"agc.status\", status_);\n \t}\n }\n@@ -345,6 +323,41 @@ void Agc::Process(StatisticsPtr &stats, Metadata *image_metadata)\n \twriteAndFinish(image_metadata, desaturate);\n }\n \n+void Agc::updateLockStatus(DeviceStatus const &device_status)\n+{\n+\tconst double ERROR_FACTOR = 0.10; // make these customisable?\n+\tconst int MAX_LOCK_COUNT = 5;\n+\n+\t// Add 200us to the exposure time error to allow for line quantisation.\n+\tdouble exposure_error = last_device_status_.shutter_speed * ERROR_FACTOR + 200;\n+\tdouble gain_error = last_device_status_.analogue_gain * ERROR_FACTOR;\n+\tdouble target_error = last_target_exposure_ * ERROR_FACTOR;\n+\n+\t// Note that we don't know the exposure/gain limits of the sensor, so\n+\t// the values we keep requesting may be unachievable. For this reason\n+\t// we only insist that we're close to values in the past few frames.\n+\tif (device_status.shutter_speed > last_device_status_.shutter_speed - exposure_error &&\n+\t    device_status.shutter_speed < last_device_status_.shutter_speed + exposure_error &&\n+\t    device_status.analogue_gain > last_device_status_.analogue_gain - gain_error &&\n+\t    device_status.analogue_gain < last_device_status_.analogue_gain + gain_error &&\n+\t    status_.target_exposure_value > last_target_exposure_ - target_error &&\n+\t    status_.target_exposure_value < last_target_exposure_ + target_error)\n+\t\tlock_count_ = std::min(lock_count_ + 1, MAX_LOCK_COUNT);\n+\telse if (device_status.shutter_speed < last_device_status_.shutter_speed - 1.5 * exposure_error ||\n+\t\t device_status.shutter_speed > last_device_status_.shutter_speed + 1.5 * exposure_error ||\n+\t\t device_status.analogue_gain < last_device_status_.analogue_gain - 1.5 * gain_error ||\n+\t\t device_status.analogue_gain > last_device_status_.analogue_gain + 1.5 * gain_error ||\n+\t\t status_.target_exposure_value < last_target_exposure_ - 1.5 * target_error ||\n+\t\t status_.target_exposure_value > last_target_exposure_ + 1.5 * target_error)\n+\t\tlock_count_ = 0;\n+\n+\tlast_device_status_ = device_status;\n+\tlast_target_exposure_ = status_.target_exposure_value;\n+\n+\tLOG(RPiAgc, Debug) << \"Lock count updated to \" << lock_count_;\n+\tstatus_.locked = lock_count_ >= MAX_LOCK_COUNT;\n+}\n+\n static void copy_string(std::string const &s, char *d, size_t size)\n {\n \tsize_t length = s.copy(d, size - 1);\ndiff --git a/src/ipa/raspberrypi/controller/rpi/agc.hpp b/src/ipa/raspberrypi/controller/rpi/agc.hpp\nindex 859a9650..47ebb324 100644\n--- a/src/ipa/raspberrypi/controller/rpi/agc.hpp\n+++ b/src/ipa/raspberrypi/controller/rpi/agc.hpp\n@@ -82,6 +82,7 @@ public:\n \tvoid Process(StatisticsPtr &stats, Metadata *image_metadata) override;\n \n private:\n+\tvoid updateLockStatus(DeviceStatus const &device_status);\n \tAgcConfig config_;\n \tvoid housekeepConfig();\n \tvoid fetchCurrentExposure(Metadata *image_metadata);\n@@ -111,6 +112,8 @@ private:\n \tExposureValues filtered_; // these values are filtered towards target\n \tAgcStatus status_;\n \tint lock_count_;\n+\tDeviceStatus last_device_status_;\n+\tdouble last_target_exposure_;\n \t// Below here the \"settings\" that applications can change.\n \tstd::string metering_mode_name_;\n \tstd::string exposure_mode_name_;\n",
    "prefixes": [
        "libcamera-devel",
        "10/10"
    ]
}