[{"id":22052,"web_url":"https://patchwork.libcamera.org/comment/22052/","msgid":"<20220119101436.d66ehnefosumza7k@uno.localdomain>","date":"2022-01-19T10:14:36","subject":"Re: [libcamera-devel] [RFC PATCH v2 1/1] libcamera: controls:\n\tControls for driving AF (autofocus) algorithms","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi David,\n  sorry to catch up late and thanks everyone for the great discussion\non v1.\n\nI'll leave a few more comments here\n\nOn Tue, Jan 18, 2022 at 11:37:50AM +0000, David Plowman wrote:\n> This patch describes a series of controls that allow applications to\n> drive AF algorithms:\n>\n> AfMode - manual, auto or continuous\n> AfRange - full, macro or normal\n> AfSpeed - fast or slow\n> AfMethod - single or multi-spot\n> AfWindow - AF window locations\n> AfTrigger - start (trigger an AF scan) or cancel\n> AfPause - pause continuous AF\n> LensPosition - position of lens from lens driver\n> AfState - reset, scanning, focused or failed\n> ---\n>  src/libcamera/control_ids.yaml | 295 ++++++++++++++++++++++++++-------\n>  1 file changed, 235 insertions(+), 60 deletions(-)\n>\n> diff --git a/src/libcamera/control_ids.yaml b/src/libcamera/control_ids.yaml\n> index 9d4638ae..0b5ea9bd 100644\n> --- a/src/libcamera/control_ids.yaml\n> +++ b/src/libcamera/control_ids.yaml\n> @@ -406,27 +406,6 @@ controls:\n>              The camera will cancel any active or completed metering sequence.\n>              The AE algorithm is reset to its initial state.\n>\n> -  - AfTrigger:\n> -      type: int32_t\n> -      draft: true\n> -      description: |\n> -       Control for AF trigger. Currently identical to\n> -       ANDROID_CONTROL_AF_TRIGGER.\n> -\n> -        Whether the camera device will trigger autofocus for this request.\n> -      enum:\n> -        - name: AfTriggerIdle\n> -          value: 0\n> -          description: The trigger is idle.\n> -        - name: AfTriggerStart\n> -          value: 1\n> -          description: The AF routine is started by the camera.\n> -        - name: AfTriggerCancel\n> -          value: 2\n> -          description: |\n> -            The camera will cancel any active trigger and the AF routine is\n> -            reset to its initial state.\n> -\n>    - NoiseReductionMode:\n>        type: int32_t\n>        draft: true\n> @@ -507,45 +486,6 @@ controls:\n>              The AE algorithm has started a pre-capture metering session.\n>              \\sa AePrecaptureTrigger\n>\n> -  - AfState:\n> -      type: int32_t\n> -      draft: true\n> -      description: |\n> -       Control to report the current AF algorithm state. Currently identical to\n> -       ANDROID_CONTROL_AF_STATE.\n> -\n> -        Current state of the AF algorithm.\n> -      enum:\n> -        - name: AfStateInactive\n> -          value: 0\n> -          description: The AF algorithm is inactive.\n> -        - name: AfStatePassiveScan\n> -          value: 1\n> -          description: |\n> -            AF is performing a passive scan of the scene in continuous\n> -            auto-focus mode.\n> -        - name: AfStatePassiveFocused\n> -          value: 2\n> -          description: |\n> -            AF believes the scene is in focus, but might restart scanning.\n> -        - name: AfStateActiveScan\n> -          value: 3\n> -          description: |\n> -            AF is performing a scan triggered by an AF trigger request.\n> -            \\sa AfTrigger\n> -        - name: AfStateFocusedLock\n> -          value: 4\n> -          description: |\n> -            AF believes has focused correctly and has locked focus.\n> -        - name: AfStateNotFocusedLock\n> -          value: 5\n> -          description: |\n> -            AF has not been able to focus and has locked.\n> -        - name: AfStatePassiveUnfocused\n> -          value: 6\n> -          description: |\n> -            AF has completed a passive scan without finding focus.\n> -\n\nAs Naush suggested, should the existing FocusFoM control be removed\ntoo ?\n\n>    - AwbState:\n>        type: int32_t\n>        draft: true\n> @@ -690,4 +630,239 @@ controls:\n>              value. All of the custom test patterns will be static (that is the\n>              raw image must not vary from frame to frame).\n>\n> +  - AfMode:\n> +      type: int32_t\n> +      draft: true\n> +      description: |\n> +        Control to set the mode of the AF (autofocus) algorithm. Applications\n> +        are allowed to set a new mode, and to send additional controls for\n> +        that new mode, in the same request. Furthermore, setting the mode to\n> +        the value it currently has is also permitted (with no effect).\n\nIs the last statement required ? Doesn't this apply to all controls\n(re-setting them to the same is no-op) ?\n\n> +      enum:\n> +        - name: AfModeManual\n> +          value: 0\n> +          description: |\n> +            The AF algorithm is in manual mode. In this mode it will never\n> +            perform any action nor move the lens of its own accord. The only\n> +\t    autofocus controls that have an immediate effect are AfMode (to\n> +\t    switch out of manual mode) and LensPosition (so that the lens can\n> +\t    be moved \"manually\").\n> +\n> +\t    In this mode the AfState will always report AfStateReset.\n\nIndentation seems off here and in the descriptions of other controls.\n\nFor what is worth, I do prefer having a Manual mode where LensPosition\nis valid. I understand it forces applications to move to a different\nstate before moving the lens, but as Han-lin reported it would help\nwith translating to/from Android and matches more closely the AE\ncontrols definition we agreed on.\n\nI think we will never really find out how much Manual helps with\ntranslating to Android until we don't actually do so, but in the\nmeantime I would keep it and if proves unecessary remove it later.\n\nFor RPi it implies apps have to do one extra step. Can this be hidden\nin your applications maybe ?\n\nOne thing which is not clear to me is what happens when transitioning\nto Manual. For AE controls we decided switching to Manual from Auto\nretains the lastly computed exposure time until applications do not\nsubmit an ExposureTime control. Does this make any sense for\nautofocus ? Would 'retain the last lens position' when moving from\nAuto/CAF actually freeze the autofocus and implement the 'pause' that\nwas discussed in v1 ?\n\n> +        - name: AfModeAuto\n> +          value: 1\n> +          description: |\n> +            The AF algorithm is in auto mode. This means that the algorithm\n> +            will never move the lens or change state unless the AfTrigger\n> +            control is used. The AfTrigger control can be used to initiate a\n> +            focus scan, the results of which will also be reported by AfState.\n> +\n> +            If the autofocus algorithm is moved from AfModeAuto to another\n> +            mode while a scan is in progress, the scan is cancelled\n> +            immediately, without waiting for the scan to finish.\n> +\n> +\t    When first entering this mode the AfState will report\n> +\t    AfStateReset. When a trigger control is sent, AfState will\n> +\t    report AfStateScanning for a period before spontaneously\n> +\t    changing to AfStateFocused or AfStateFailed, depending on the\n> +\t    outcome of the scan. It will remain in this state until another\n> +\t    scan is initiated by the AfTrigger control. If a scan is\n> +\t    cancelled (without changing to another mode), AfState will return\n> +\t    to AfStateReset.\n> +        - name: AfModeContinuous\n> +          value: 2\n> +          description: |\n> +            The AF algorithm is in continuous mode. This means that the lens\n> +            can re-start a scan spontaneously at any moment, without any user\n> +            intervention. The AfState still reports whether the algorithm is\n> +            currently scanning or not, though the application has no ability\n> +            to initiate or cancel scans, nor move the lens for itself.\n> +\n> +\t    When set to AfModeContinuous, the system will immediately initiate\n> +\t    a scan so AfState will report AfStateScanning, and will settle on\n> +\t    one of AfStateFocused or AfStateFailed, depending on the scan\n> +\t    result.\n> +\n> +            The continuous autofocus behaviour can be paused with the\n> +\t    AfPause control. Pausing the algorithm does not change the value\n> +\t    reported by AfState, so that applications can determine the\n> +\t    state of the algorithm when the pause control took effect. Once\n> +\t    un-paused (\"resumed\"), the algorithm starts again from exactly\n> +\t    where it left off when it paused.\n> +\n\nI like the defintion of these two modes, the only thing I'm not sure\nis the Pause. As suggested [CAF|Auto]->Manual would have the effect to\npause the algorithm until the lens is not moved explicitely, but would\nreport StateReset according to the current defintion, while you here\nsuggested that [CAF]->Pause would not change the AfState. Why is this\nuseful for applications ? I might have missed that...\n\n> +  - AfRange:\n> +      type: int32_t\n> +      draft: true\n> +      description: |\n> +        Control to set the range of focus distances that is scanned.\n> +      enum:\n> +        - name: AfRangeNormal\n> +          value: 0\n> +          description: |\n> +\t    A wide range of focus distances is scanned, all the way from\n> +\t    infinity down to close distances, though depending on the\n> +\t    implementation, possibly not including the very closest macro\n> +\t    positions.\n> +        - name: AfRangeMacro\n> +          value: 1\n> +          description: Only close distances are scanned.\n> +        - name: AfRangeFull\n> +          value: 2\n> +          description: |\n> +            The full range of focus distances is scanned just as with\n> +\t    AfRangeNormal but this time including the very closest macro\n> +\t    positions.\n\nWe should start thinking how to map the lens movement range to such\n'closest marco' and 'close distances'. I honestly don't know enough to\nimmagine if a linear mapping to the lens movement range is enough or\nnot.\n\n> +\n> +  - AfSpeed:\n> +      type: int32_t\n> +      draft: true\n> +      description: |\n> +        Control that determines whether the AF algorithm is to move the lens\n> +        as quickly as possible or more steadily. For example, during video\n> +        recording it may be desirable not to move the lens too abruptly, but\n> +        when in a preview mode (waiting for a still capture) it may be\n> +        helpful to move the lens as quickly as is reasonably possible.\n> +      enum:\n> +        - name: AfSpeedNormal\n> +          value: 0\n> +          description: Move the lens at its usual speed.\n> +        - name: AfSpeedFast\n> +          value: 1\n> +          description: Move the lens more quickly.\n> +\n> +  - AfMethod:\n> +      type: int32_t\n> +      draft: true\n> +      description: |\n> +        Control whether the AF algorithm uses a single window in the image to\n> +        determine the best focus position, or multiple windows simultaneously.\n> +      enum:\n> +        - name: AfMethodSingle\n> +          value: 0\n> +          description: |\n> +            A single window within the image, defaulting to the centre, is used\n> +            to select the best focus distance.\n> +        - name: AfMethodMultiSpot\n> +          value: 0\n> +          description: |\n> +            Multiple windows within the image are used to select the best focus\n> +            distance. The best focus distance is found for each one of the\n> +            windows, and then the distance that is closest to the camera is\n> +            selected.\n\nI have an hard time understanding why this control cannot be inferred\nby the number of rectangles passed to AfWindow.\n\nIf it's a shortcut for 'default to center' I'm in two minds. Can we\nsay that 'no AfWindow == default to center' ? Do we lose anything with\nthat ?\n\n> +\n> +  - AfWindow:\n> +      type: Rectangle\n> +      draft: true\n> +      description: |\n> +         Sets the focus windows used by the AF algorithm. The units used express\n> +         a proportion of the ScalerCrop control (or if unavailable, of the entire\n> +         image), as u0.16 format numbers.\n\nMy first reaction was \"we should refer to the ActivePixelArray not to\nScalerCrop\", reason being ScalerCrop is optional and might not be of\ninterest of the application to specify one.\n\nBut I'm not sure if the active pixel array is the right target either.\nI assume these rectangles get directly translated to some ISP\nparameters that allows to specify grids where to sample the pixels\ncontrast from ? If that's the case what they do refer to ? I assume\nit's the input RAW picture size, something not exposed to apps by\nlibcamera, but that pipeline handlers have access to...\n\n> +\n> +         In order to be activated, a rectangle must be programmed with non-zero\n> +         width and height. If no rectangles are programmed in this way, then the\n> +         system will choose its own single default window in the centre of the\n> +         image.\n\nAh!\n\n> +\n> +         If AfMethod is set to AfMethodSingle, then only the first Rectangle in\n> +         this list is used (or the system default one if it is unprogrammed).\n> +\n> +         If AfMethod is set to AfMethodMultiSpot then all the valid Rectangles in\n> +         this list are used. The size of the control indicates how many such\n> +         windows can be programmed and will vary between different platforms.\n> +\n> +         size: [platform dependent]\n> +\n> +  - AfTrigger:\n> +      type: int32_t\n> +      draft: true\n> +      description: |\n> +         This control starts an autofocus scan when AfMode is set to AfModeAuto,\n> +         and can also be used to terminate a scan early.\n> +\n> +         It is ignored if AfMode is set to AfModeContinuous.\n\nAnd in Manual too\n\n> +\n> +      enum:\n> +        - name: AfTriggerStart\n> +          value: 0\n> +          description: Start an AF scan. Ignored if a scan is in progress.\n> +        - name: AfTriggerCancel\n> +          value: 1\n> +          description: Cancel an AF scan. Ingored if no scan is in progress.\n> +\n> +  - AfPause:\n> +      type: int32_t\n> +      draft: true\n> +      description: |\n> +        This control has no effect except when in continuous autofocus mode\n> +        (AfModeContinuous). It can be used to pause any lens movements while\n> +        (for example) images are captured. The algorithm remains inactive\n> +        until it is instructed to resume.\n> +\n> +      enum:\n> +        - name: AfPauseImmediate\n> +          value: 0\n> +          description: |\n> +            Pause the continuous autofocus algorithm immediately, whether or\n> +            not any kind of scan is underway. The AfState will continue to\n> +            report whatever value it had when the control was enacted.\n> +        - name AfPauseDeferred\n> +          value: 1\n> +          description: |\n> +            Pause the continuous autofocus algorithm as soon as it is no longer\n> +            scanning. The AfState will report AfStateFocused or AfStateFailed,\n> +            depending on whether the final scan succeeds or not. If no scan is\n> +\t    in currently progress, the algorithm will pause immediately.\n> +        - name: AfPauseResume\n> +          value: 2\n> +          description: |\n> +\t    Resume continous autofocus operation. The algorithm starts again\n> +\t    from exactly where it left off, with AfState unchanged (one of\n> +\t    AfStateFocused, AfStateFailed or following AfPauseImmediate it\n> +\t    might also have been in the AfStateScanning state).\n> +\n> +\n> +  - LensPosition:\n> +      type: int32_t\n> +      draft: true\n> +      description: |\n> +         Acts as a control to instruct the lens to move to a particular position\n> +         and also reports back the position of the lens for each frame.\n> +\n> +         The units are determined by the lens driver.\n\nThis would make it impossible to write apps in a portable way. I know\nnothing at the moment about lenses so I cannot propose a suitable\nrange, but we should indeed define one and translate to the opportune\nlens positions using the CameraLens helper class ?\n\n> +\n> +         The LensPosition control is ignored unless the AfMode is set to\n> +         AfModeManual.\n> +\n> +  - AfState:\n> +      type: int32_t\n> +      draft: true\n> +      description: |\n> +          Reports the current state of the AF algorithm.\n> +      enum:\n> +        - name: AfStateReset\n> +          value: 0\n> +          description: |\n> +              The AF algorithm reports this state when:\n> +                  * It is in manual mode (AfModeManual).\n> +                  * The system has entered auto mode (AfModeAuto) but no scan\n> +\t\t    has yet been initiated.\n> +                  * The system is in auto mode (AfModeAuto) and a scan has been\n> +\t\t    cancelled.\n> +        - name: AfStateScanning\n> +          value: 1\n> +          description:  |\n\nThis is instead indented a bit too much to the right.\n\n> +              AF is performing a scan. This state can be entered spontaneously\n> +              if AfMode is set to AfModeContinuous, otherwise it requires the\n> +              application to use the AfTrigger control to start the scan.\n> +        - name: AfStateFocused\n> +          value: 2\n> +          description: |\n> +              An AF scan has been performed and the algorithm believes the\n> +              scene is in focus.\n> +        - name: AfStateFailed\n> +          value: 3\n> +          description: |\n> +              An AF scan has been performed but the algorithm has not been able\n> +              to find the best focus position.\n> +\n\nI like AfState to be simple, but as suggested by Han-lin I'm afraid to\nbe able to translate back to Android PASSIVE_FOCUSED vs FOCUSED_LOCKED\nwe need an AfModeManual mode as you have in this v2.\n\nThanks\n   j\n\n>  ...\n> --\n> 2.30.2\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 1552DBF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 19 Jan 2022 10:13:36 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 334B56094A;\n\tWed, 19 Jan 2022 11:13:35 +0100 (CET)","from relay12.mail.gandi.net (relay12.mail.gandi.net\n\t[IPv6:2001:4b98:dc4:8::232])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 489996017F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 19 Jan 2022 11:13:34 +0100 (CET)","(Authenticated sender: jacopo@jmondi.org)\n\tby relay12.mail.gandi.net (Postfix) with ESMTPSA id BC47D20000A;\n\tWed, 19 Jan 2022 10:13:33 +0000 (UTC)"],"Date":"Wed, 19 Jan 2022 11:14:36 +0100","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"David Plowman <david.plowman@raspberrypi.com>","Message-ID":"<20220119101436.d66ehnefosumza7k@uno.localdomain>","References":"<20220118113750.19943-1-david.plowman@raspberrypi.com>\n\t<20220118113750.19943-2-david.plowman@raspberrypi.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20220118113750.19943-2-david.plowman@raspberrypi.com>","Subject":"Re: [libcamera-devel] [RFC PATCH v2 1/1] libcamera: controls:\n\tControls for driving AF (autofocus) algorithms","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>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":22054,"web_url":"https://patchwork.libcamera.org/comment/22054/","msgid":"<CAHW6GYLDJb741-uLLZyy0k=S_cAvb0c=mWoNkQrquA60wyM+nw@mail.gmail.com>","date":"2022-01-19T17:11:42","subject":"Re: [libcamera-devel] [RFC PATCH v2 1/1] libcamera: controls:\n\tControls for driving AF (autofocus) algorithms","submitter":{"id":42,"url":"https://patchwork.libcamera.org/api/people/42/","name":"David Plowman","email":"david.plowman@raspberrypi.com"},"content":"Hi Jacopo\n\nThanks for the comments!\n\nOn Wed, 19 Jan 2022 at 10:13, Jacopo Mondi <jacopo@jmondi.org> wrote:\n>\n> Hi David,\n>   sorry to catch up late and thanks everyone for the great discussion\n> on v1.\n>\n> I'll leave a few more comments here\n>\n> On Tue, Jan 18, 2022 at 11:37:50AM +0000, David Plowman wrote:\n> > This patch describes a series of controls that allow applications to\n> > drive AF algorithms:\n> >\n> > AfMode - manual, auto or continuous\n> > AfRange - full, macro or normal\n> > AfSpeed - fast or slow\n> > AfMethod - single or multi-spot\n> > AfWindow - AF window locations\n> > AfTrigger - start (trigger an AF scan) or cancel\n> > AfPause - pause continuous AF\n> > LensPosition - position of lens from lens driver\n> > AfState - reset, scanning, focused or failed\n> > ---\n> >  src/libcamera/control_ids.yaml | 295 ++++++++++++++++++++++++++-------\n> >  1 file changed, 235 insertions(+), 60 deletions(-)\n> >\n> > diff --git a/src/libcamera/control_ids.yaml b/src/libcamera/control_ids.yaml\n> > index 9d4638ae..0b5ea9bd 100644\n> > --- a/src/libcamera/control_ids.yaml\n> > +++ b/src/libcamera/control_ids.yaml\n> > @@ -406,27 +406,6 @@ controls:\n> >              The camera will cancel any active or completed metering sequence.\n> >              The AE algorithm is reset to its initial state.\n> >\n> > -  - AfTrigger:\n> > -      type: int32_t\n> > -      draft: true\n> > -      description: |\n> > -       Control for AF trigger. Currently identical to\n> > -       ANDROID_CONTROL_AF_TRIGGER.\n> > -\n> > -        Whether the camera device will trigger autofocus for this request.\n> > -      enum:\n> > -        - name: AfTriggerIdle\n> > -          value: 0\n> > -          description: The trigger is idle.\n> > -        - name: AfTriggerStart\n> > -          value: 1\n> > -          description: The AF routine is started by the camera.\n> > -        - name: AfTriggerCancel\n> > -          value: 2\n> > -          description: |\n> > -            The camera will cancel any active trigger and the AF routine is\n> > -            reset to its initial state.\n> > -\n> >    - NoiseReductionMode:\n> >        type: int32_t\n> >        draft: true\n> > @@ -507,45 +486,6 @@ controls:\n> >              The AE algorithm has started a pre-capture metering session.\n> >              \\sa AePrecaptureTrigger\n> >\n> > -  - AfState:\n> > -      type: int32_t\n> > -      draft: true\n> > -      description: |\n> > -       Control to report the current AF algorithm state. Currently identical to\n> > -       ANDROID_CONTROL_AF_STATE.\n> > -\n> > -        Current state of the AF algorithm.\n> > -      enum:\n> > -        - name: AfStateInactive\n> > -          value: 0\n> > -          description: The AF algorithm is inactive.\n> > -        - name: AfStatePassiveScan\n> > -          value: 1\n> > -          description: |\n> > -            AF is performing a passive scan of the scene in continuous\n> > -            auto-focus mode.\n> > -        - name: AfStatePassiveFocused\n> > -          value: 2\n> > -          description: |\n> > -            AF believes the scene is in focus, but might restart scanning.\n> > -        - name: AfStateActiveScan\n> > -          value: 3\n> > -          description: |\n> > -            AF is performing a scan triggered by an AF trigger request.\n> > -            \\sa AfTrigger\n> > -        - name: AfStateFocusedLock\n> > -          value: 4\n> > -          description: |\n> > -            AF believes has focused correctly and has locked focus.\n> > -        - name: AfStateNotFocusedLock\n> > -          value: 5\n> > -          description: |\n> > -            AF has not been able to focus and has locked.\n> > -        - name: AfStatePassiveUnfocused\n> > -          value: 6\n> > -          description: |\n> > -            AF has completed a passive scan without finding focus.\n> > -\n>\n> As Naush suggested, should the existing FocusFoM control be removed\n> too ?\n\nAh yes, I forgot about that. Actually I think FocusFoM is useful. For\nexample, on our HQ cams the lens position can only be changed (quite\nliterally) \"manually\", so it's important for the user to be able to\nwatch the FocusFoM change while they twiddle the lens.\n\n>\n> >    - AwbState:\n> >        type: int32_t\n> >        draft: true\n> > @@ -690,4 +630,239 @@ controls:\n> >              value. All of the custom test patterns will be static (that is the\n> >              raw image must not vary from frame to frame).\n> >\n> > +  - AfMode:\n> > +      type: int32_t\n> > +      draft: true\n> > +      description: |\n> > +        Control to set the mode of the AF (autofocus) algorithm. Applications\n> > +        are allowed to set a new mode, and to send additional controls for\n> > +        that new mode, in the same request. Furthermore, setting the mode to\n> > +        the value it currently has is also permitted (with no effect).\n>\n> Is the last statement required ? Doesn't this apply to all controls\n> (re-setting them to the same is no-op) ?\n\nTrue enough, I'm happy to remove that. I just wanted to be sure\neveryone agrees that this is fine and that it won't start spitting out\nwarnings!\n\n>\n> > +      enum:\n> > +        - name: AfModeManual\n> > +          value: 0\n> > +          description: |\n> > +            The AF algorithm is in manual mode. In this mode it will never\n> > +            perform any action nor move the lens of its own accord. The only\n> > +         autofocus controls that have an immediate effect are AfMode (to\n> > +         switch out of manual mode) and LensPosition (so that the lens can\n> > +         be moved \"manually\").\n> > +\n> > +         In this mode the AfState will always report AfStateReset.\n>\n> Indentation seems off here and in the descriptions of other controls.\n\nNot sure what happened there. Maybe some tabs crept in and got removed\nbadly, but I'll fix it up.\n\n>\n> For what is worth, I do prefer having a Manual mode where LensPosition\n> is valid. I understand it forces applications to move to a different\n> state before moving the lens, but as Han-lin reported it would help\n> with translating to/from Android and matches more closely the AE\n> controls definition we agreed on.\n\nI think a separate manual mode is OK if we can send both \"manual mode\"\nand a lens position in the same request.\n\n>\n> I think we will never really find out how much Manual helps with\n> translating to Android until we don't actually do so, but in the\n> meantime I would keep it and if proves unecessary remove it later.\n>\n> For RPi it implies apps have to do one extra step. Can this be hidden\n> in your applications maybe ?\n\nYes, if one can send these commands at the same time then it really is\nvery painless.\n\n>\n> One thing which is not clear to me is what happens when transitioning\n> to Manual. For AE controls we decided switching to Manual from Auto\n> retains the lastly computed exposure time until applications do not\n> submit an ExposureTime control. Does this make any sense for\n> autofocus ? Would 'retain the last lens position' when moving from\n> Auto/CAF actually freeze the autofocus and implement the 'pause' that\n> was discussed in v1 ?\n\nThe behaviour when switching from anything else to manual should be\nthat the lens doesn't move. You're right it would implement a \"pause\"\ncommand but I think the discussion with Hanlin moved us towards a\nseparate control for that. \"Pause\" has a special control value where\nyou can tell it to \"pause when you are not scanning\", and there's the\nquestion of what CAF does when you \"resume\". Does it resume from\nexactly where it left off? Or does it start a scan again? The way I've\ndescribed things here:\n\n* If you switch from something else back to CAF, it will immediately\nproceed to do a scan (it has no reason to believe the lens is anywhere\nsensible).\n* If you \"resume\" after a \"pause\" it will resume from where it left\noff. So if it thought it was in focus, it will stay like that (until\nsuch time as some image statistics suggest it needs to rescan).\n* If it was scanning but got paused during the scan, resuming will\ncarry on with the scan. (Actually I wonder if the scan should start\nover rather than carry on from exactly where it was, but maybe that's\nan implementation detail).\n* Another difference, as I've described things here, is that \"Pause\"\nleaves the state unchanged, so you can see what state CAF was in,\nwhereas moving to \"Manual\" puts it back to \"reset\". This could be\nchanged, of course, though I worry a bit about mixing the modes\ntogether (see next comment).\n\n>\n> > +        - name: AfModeAuto\n> > +          value: 1\n> > +          description: |\n> > +            The AF algorithm is in auto mode. This means that the algorithm\n> > +            will never move the lens or change state unless the AfTrigger\n> > +            control is used. The AfTrigger control can be used to initiate a\n> > +            focus scan, the results of which will also be reported by AfState.\n> > +\n> > +            If the autofocus algorithm is moved from AfModeAuto to another\n> > +            mode while a scan is in progress, the scan is cancelled\n> > +            immediately, without waiting for the scan to finish.\n> > +\n> > +         When first entering this mode the AfState will report\n> > +         AfStateReset. When a trigger control is sent, AfState will\n> > +         report AfStateScanning for a period before spontaneously\n> > +         changing to AfStateFocused or AfStateFailed, depending on the\n> > +         outcome of the scan. It will remain in this state until another\n> > +         scan is initiated by the AfTrigger control. If a scan is\n> > +         cancelled (without changing to another mode), AfState will return\n> > +         to AfStateReset.\n> > +        - name: AfModeContinuous\n> > +          value: 2\n> > +          description: |\n> > +            The AF algorithm is in continuous mode. This means that the lens\n> > +            can re-start a scan spontaneously at any moment, without any user\n> > +            intervention. The AfState still reports whether the algorithm is\n> > +            currently scanning or not, though the application has no ability\n> > +            to initiate or cancel scans, nor move the lens for itself.\n> > +\n> > +         When set to AfModeContinuous, the system will immediately initiate\n> > +         a scan so AfState will report AfStateScanning, and will settle on\n> > +         one of AfStateFocused or AfStateFailed, depending on the scan\n> > +         result.\n> > +\n> > +            The continuous autofocus behaviour can be paused with the\n> > +         AfPause control. Pausing the algorithm does not change the value\n> > +         reported by AfState, so that applications can determine the\n> > +         state of the algorithm when the pause control took effect. Once\n> > +         un-paused (\"resumed\"), the algorithm starts again from exactly\n> > +         where it left off when it paused.\n> > +\n>\n> I like the defintion of these two modes, the only thing I'm not sure\n> is the Pause. As suggested [CAF|Auto]->Manual would have the effect to\n> pause the algorithm until the lens is not moved explicitely, but would\n> report StateReset according to the current defintion, while you here\n> suggested that [CAF]->Pause would not change the AfState. Why is this\n> useful for applications ? I might have missed that...\n\nIt's hard to predict why this might be useful, but it feels like\nproviding full information is usually a good thing. For example, if\nyou pause CAF and do some captures, if the state reports \"failed\" (or\neven \"scanning\") rather than \"focused\" the UI could pop up one of\nthose \"your picture might be blurry\" warnings!\n\nI suppose you could have manual mode report states other than just\n\"reset\", but I worry a bit that we're mixing our modes together, which\nmeans understanding manual mode properly means you have to understand\nCAF. I also quite like the idea that entering a mode (CAF in this\ncase) completely resets and restarts it. CAF algorithms (especially\ncontrast detect ones) can have a nasty habit of getting stuck in the\nwrong place, so it's reassuring if there's a guaranteed way to restart\nit.\n\n>\n> > +  - AfRange:\n> > +      type: int32_t\n> > +      draft: true\n> > +      description: |\n> > +        Control to set the range of focus distances that is scanned.\n> > +      enum:\n> > +        - name: AfRangeNormal\n> > +          value: 0\n> > +          description: |\n> > +         A wide range of focus distances is scanned, all the way from\n> > +         infinity down to close distances, though depending on the\n> > +         implementation, possibly not including the very closest macro\n> > +         positions.\n> > +        - name: AfRangeMacro\n> > +          value: 1\n> > +          description: Only close distances are scanned.\n> > +        - name: AfRangeFull\n> > +          value: 2\n> > +          description: |\n> > +            The full range of focus distances is scanned just as with\n> > +         AfRangeNormal but this time including the very closest macro\n> > +         positions.\n>\n> We should start thinking how to map the lens movement range to such\n> 'closest marco' and 'close distances'. I honestly don't know enough to\n> immagine if a linear mapping to the lens movement range is enough or\n> not.\n\nI remember working with some VCM modules where the driver range was\nmapped to 0-255. But in reality, infinity was around 220, hyperfocal\naround 200 and the closest focus would be around 50. Most of the AF\ntime was spent searching the last few centimetres in front of the\nlens, which is the reason for having AfRangeNormal as well as\nAfRangeFull.\n\n>\n> > +\n> > +  - AfSpeed:\n> > +      type: int32_t\n> > +      draft: true\n> > +      description: |\n> > +        Control that determines whether the AF algorithm is to move the lens\n> > +        as quickly as possible or more steadily. For example, during video\n> > +        recording it may be desirable not to move the lens too abruptly, but\n> > +        when in a preview mode (waiting for a still capture) it may be\n> > +        helpful to move the lens as quickly as is reasonably possible.\n> > +      enum:\n> > +        - name: AfSpeedNormal\n> > +          value: 0\n> > +          description: Move the lens at its usual speed.\n> > +        - name: AfSpeedFast\n> > +          value: 1\n> > +          description: Move the lens more quickly.\n> > +\n> > +  - AfMethod:\n> > +      type: int32_t\n> > +      draft: true\n> > +      description: |\n> > +        Control whether the AF algorithm uses a single window in the image to\n> > +        determine the best focus position, or multiple windows simultaneously.\n> > +      enum:\n> > +        - name: AfMethodSingle\n> > +          value: 0\n> > +          description: |\n> > +            A single window within the image, defaulting to the centre, is used\n> > +            to select the best focus distance.\n> > +        - name: AfMethodMultiSpot\n> > +          value: 0\n> > +          description: |\n> > +            Multiple windows within the image are used to select the best focus\n> > +            distance. The best focus distance is found for each one of the\n> > +            windows, and then the distance that is closest to the camera is\n> > +            selected.\n>\n> I have an hard time understanding why this control cannot be inferred\n> by the number of rectangles passed to AfWindow.\n>\n> If it's a shortcut for 'default to center' I'm in two minds. Can we\n> say that 'no AfWindow == default to center' ? Do we lose anything with\n> that ?\n\nGood point. For a while I was wondering whether there's a \"method\"\nwhere you can have multiple windows but treat them as if they were one\nregion, so you'd sort of get an \"average best focus\".\n\nI also wondered whether AfMethodMultiSpot should be divided into\nAfMethodMultiSpotNear and AfMethodMultiSpotFar - in the latter case\nyou'd choose the furthest focal distance. Does anyone think that might\nbe useful?\n\nMaybe we drop \"AfMethod\" for now, and bring it back in future if we\never find a reason?\n\n>\n> > +\n> > +  - AfWindow:\n> > +      type: Rectangle\n> > +      draft: true\n> > +      description: |\n> > +         Sets the focus windows used by the AF algorithm. The units used express\n> > +         a proportion of the ScalerCrop control (or if unavailable, of the entire\n> > +         image), as u0.16 format numbers.\n>\n> My first reaction was \"we should refer to the ActivePixelArray not to\n> ScalerCrop\", reason being ScalerCrop is optional and might not be of\n> interest of the application to specify one.\n>\n> But I'm not sure if the active pixel array is the right target either.\n> I assume these rectangles get directly translated to some ISP\n> parameters that allows to specify grids where to sample the pixels\n> contrast from ? If that's the case what they do refer to ? I assume\n> it's the input RAW picture size, something not exposed to apps by\n> libcamera, but that pipeline handlers have access to...\n\nI'm not sure what the answer is here. I guess it's worth imagining\nwhat happens to the focus windows if an application zooms in and out\n(digitally). As the zoom changes, do we want applications to have to\nrecalculate the focus windows all the time? That feels quite onerous.\n\nI'm sure an application would prefer to say something like (for\nexample) \"put a window in the middle and one in each corner\" and then\nthose windows stay there (in the output image) regardless. Perhaps\nthat's what we should be aiming for?\n\nIt would certainly be unhelpful if you zoomed in and discovered you\nwere focusing on things that aren't even in the output image!\n\n>\n> > +\n> > +         In order to be activated, a rectangle must be programmed with non-zero\n> > +         width and height. If no rectangles are programmed in this way, then the\n> > +         system will choose its own single default window in the centre of the\n> > +         image.\n>\n> Ah!\n>\n> > +\n> > +         If AfMethod is set to AfMethodSingle, then only the first Rectangle in\n> > +         this list is used (or the system default one if it is unprogrammed).\n> > +\n> > +         If AfMethod is set to AfMethodMultiSpot then all the valid Rectangles in\n> > +         this list are used. The size of the control indicates how many such\n> > +         windows can be programmed and will vary between different platforms.\n> > +\n> > +         size: [platform dependent]\n> > +\n> > +  - AfTrigger:\n> > +      type: int32_t\n> > +      draft: true\n> > +      description: |\n> > +         This control starts an autofocus scan when AfMode is set to AfModeAuto,\n> > +         and can also be used to terminate a scan early.\n> > +\n> > +         It is ignored if AfMode is set to AfModeContinuous.\n>\n> And in Manual too\n\nYes!\n\n>\n> > +\n> > +      enum:\n> > +        - name: AfTriggerStart\n> > +          value: 0\n> > +          description: Start an AF scan. Ignored if a scan is in progress.\n> > +        - name: AfTriggerCancel\n> > +          value: 1\n> > +          description: Cancel an AF scan. Ingored if no scan is in progress.\n> > +\n> > +  - AfPause:\n> > +      type: int32_t\n> > +      draft: true\n> > +      description: |\n> > +        This control has no effect except when in continuous autofocus mode\n> > +        (AfModeContinuous). It can be used to pause any lens movements while\n> > +        (for example) images are captured. The algorithm remains inactive\n> > +        until it is instructed to resume.\n> > +\n> > +      enum:\n> > +        - name: AfPauseImmediate\n> > +          value: 0\n> > +          description: |\n> > +            Pause the continuous autofocus algorithm immediately, whether or\n> > +            not any kind of scan is underway. The AfState will continue to\n> > +            report whatever value it had when the control was enacted.\n> > +        - name AfPauseDeferred\n> > +          value: 1\n> > +          description: |\n> > +            Pause the continuous autofocus algorithm as soon as it is no longer\n> > +            scanning. The AfState will report AfStateFocused or AfStateFailed,\n> > +            depending on whether the final scan succeeds or not. If no scan is\n> > +         in currently progress, the algorithm will pause immediately.\n> > +        - name: AfPauseResume\n> > +          value: 2\n> > +          description: |\n> > +         Resume continous autofocus operation. The algorithm starts again\n> > +         from exactly where it left off, with AfState unchanged (one of\n> > +         AfStateFocused, AfStateFailed or following AfPauseImmediate it\n> > +         might also have been in the AfStateScanning state).\n> > +\n> > +\n> > +  - LensPosition:\n> > +      type: int32_t\n> > +      draft: true\n> > +      description: |\n> > +         Acts as a control to instruct the lens to move to a particular position\n> > +         and also reports back the position of the lens for each frame.\n> > +\n> > +         The units are determined by the lens driver.\n>\n> This would make it impossible to write apps in a portable way. I know\n> nothing at the moment about lenses so I cannot propose a suitable\n> range, but we should indeed define one and translate to the opportune\n> lens positions using the CameraLens helper class ?\n\nSomething like that might work. We could use the min/max of the\nV4L2_CID_FOCUS_ABSOLUTE control to give the lens driver range. Though\nI'm not sure how you would know which end is macro and which is\ninfinity. The default value could give you the setting for hyperfocal.\n\nBut there's a problem because the lens driver range is not the\n_useable_ range, which is normally quite a lot less. Perhaps the\ndevice tree can be used to adjust the values the driver reports? Or\nperhaps there should be some kind of database? Editing the device tree\nbecause you want to try a different module seems harsh.\n\nThe other catch is that the useable range (and hyperfocal position)\nvaries with the module type, even when they share a lens driver, and\nthere's normally no way to determine what module you have. For the Pi,\nI'd probably expect to store the ranges I want to search in the tuning\nfile, so we only have to set the LIBCAMERA_RPI_TUNING_FILE variable\ncorrectly, but that doesn't help an application to know what lens\npositions it should use (for example, when an application starts I'd\nexpect \"move the lens to hyperfocal\" to be quite common).\n\n>\n> > +\n> > +         The LensPosition control is ignored unless the AfMode is set to\n> > +         AfModeManual.\n> > +\n> > +  - AfState:\n> > +      type: int32_t\n> > +      draft: true\n> > +      description: |\n> > +          Reports the current state of the AF algorithm.\n> > +      enum:\n> > +        - name: AfStateReset\n> > +          value: 0\n> > +          description: |\n> > +              The AF algorithm reports this state when:\n> > +                  * It is in manual mode (AfModeManual).\n> > +                  * The system has entered auto mode (AfModeAuto) but no scan\n> > +                 has yet been initiated.\n> > +                  * The system is in auto mode (AfModeAuto) and a scan has been\n> > +                 cancelled.\n> > +        - name: AfStateScanning\n> > +          value: 1\n> > +          description:  |\n>\n> This is instead indented a bit too much to the right.\n>\n> > +              AF is performing a scan. This state can be entered spontaneously\n> > +              if AfMode is set to AfModeContinuous, otherwise it requires the\n> > +              application to use the AfTrigger control to start the scan.\n> > +        - name: AfStateFocused\n> > +          value: 2\n> > +          description: |\n> > +              An AF scan has been performed and the algorithm believes the\n> > +              scene is in focus.\n> > +        - name: AfStateFailed\n> > +          value: 3\n> > +          description: |\n> > +              An AF scan has been performed but the algorithm has not been able\n> > +              to find the best focus position.\n> > +\n>\n> I like AfState to be simple, but as suggested by Han-lin I'm afraid to\n> be able to translate back to Android PASSIVE_FOCUSED vs FOCUSED_LOCKED\n> we need an AfModeManual mode as you have in this v2.\n>\n> Thanks\n>    j\n\nThanks!\nDavid\n\n>\n> >  ...\n> > --\n> > 2.30.2\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 82596BF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 19 Jan 2022 17:11:56 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 98C7860991;\n\tWed, 19 Jan 2022 18:11:55 +0100 (CET)","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 F060D60213\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 19 Jan 2022 18:11:53 +0100 (CET)","by mail-wm1-x336.google.com with SMTP id\n\ti187-20020a1c3bc4000000b0034d2ed1be2aso14247142wma.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 19 Jan 2022 09:11:53 -0800 (PST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=raspberrypi.com header.i=@raspberrypi.com\n\theader.b=\"UBgFHQqE\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=mime-version:references:in-reply-to:from:date:message-id:subject:to\n\t:cc; bh=MKsu261tUv1myZ9F+RKKPdn25TMZ9WPSfpqzz68Gk3Y=;\n\tb=UBgFHQqEuCrNy6IyhcVMD6e/TPYX78CCsKLz5Mo/2kSxe1Rc37yfM0XyUxjzFv4pKd\n\t16ohUtcf2UN9srPpx88L8Us0scJl8Fjof2A7EYURxE7RlaROp4ZmrBM2mrGJL48WF+JM\n\t5AtGt9/8xEIWxZPdx9Vx9ihiuMmoE8LB8ug0EFmDredFqL9DFABoPV5viT/JRTTq/yU0\n\tmNfb38wV1HhcTDA0dGI6yuIFNuKkX64e5ep2xRiV8Vq0pPI0rQbojXB9QXoql5rotiqP\n\t6d6qcoy5qM5ZhDyWT80TbqrMw17ERdvTzgKmK+N7tKql48lX7DWWzUAz5XCfXCym9AIe\n\tzcTg==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=x-gm-message-state:mime-version:references:in-reply-to:from:date\n\t:message-id:subject:to:cc;\n\tbh=MKsu261tUv1myZ9F+RKKPdn25TMZ9WPSfpqzz68Gk3Y=;\n\tb=z28Yv6L7vJEUQ9qR4Cb4iguOkVHh6j59IsDnJAt4U/Y2xIVTlWtd1z27BMkvk/19LY\n\twopCPzhUqM+h/FfLpEmsnbpo13e1y+8RR3oyBXZphLmJbkC4hli5/3CJyLSc9Y2pWj11\n\tYEmoDbxubjZAendY3Hqt/a45u80S9P1GWSXixRA/Db8wlNxPb5LM78adIu+E0nJZPjyY\n\t70m0boX5trs9jSM6yybmGsdriM4SfvOSQzqEsdB+/ndS/W5GJHHoT8vqjFF/da5nHqny\n\tcST+Q/ZSbRy+tupKP7QnPIwr1fSYXmCr2p/80DKFN6KgAFXV+jxEoNGzJVGaH4XxELwl\n\tMo7g==","X-Gm-Message-State":"AOAM5328FZrwQcUrY9UYygWR/H7aWN7wx4dyo7n0lx+bSBwGhLBIMwSg\n\taIEmsLyzwLmiVNh+THuozNA//SfPuYFLFCbyWiGgBpqfFimy7w==","X-Google-Smtp-Source":"ABdhPJw8SYgG+O117KOKE1I735UD35CNmr4s0e5nYHpuWeuTXRisQxjQjVwwyyIZpq//nxhhi8GvBI1LDJTX2aPjeIo=","X-Received":"by 2002:a5d:6d87:: with SMTP id l7mr20988918wrs.24.1642612312963;\n\tWed, 19 Jan 2022 09:11:52 -0800 (PST)","MIME-Version":"1.0","References":"<20220118113750.19943-1-david.plowman@raspberrypi.com>\n\t<20220118113750.19943-2-david.plowman@raspberrypi.com>\n\t<20220119101436.d66ehnefosumza7k@uno.localdomain>","In-Reply-To":"<20220119101436.d66ehnefosumza7k@uno.localdomain>","From":"David Plowman <david.plowman@raspberrypi.com>","Date":"Wed, 19 Jan 2022 17:11:42 +0000","Message-ID":"<CAHW6GYLDJb741-uLLZyy0k=S_cAvb0c=mWoNkQrquA60wyM+nw@mail.gmail.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Content-Type":"text/plain; charset=\"UTF-8\"","Subject":"Re: [libcamera-devel] [RFC PATCH v2 1/1] libcamera: controls:\n\tControls for driving AF (autofocus) algorithms","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>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":22154,"web_url":"https://patchwork.libcamera.org/comment/22154/","msgid":"<CAJAuwM=ieT4SUwCGHva2AmppTFj8oN4XY2QczXV3zRBGGka5fA@mail.gmail.com>","date":"2022-02-09T11:01:39","subject":"Re: [libcamera-devel] [RFC PATCH v2 1/1] libcamera: controls:\n\tControls for driving AF (autofocus) algorithms","submitter":{"id":98,"url":"https://patchwork.libcamera.org/api/people/98/","name":"Hanlin Chen","email":"hanlinchen@chromium.org"},"content":"Hi David and Jacopo,\n\nThanks for the great work!\n\nOn Thu, Jan 20, 2022 at 1:11 AM David Plowman\n<david.plowman@raspberrypi.com> wrote:\n>\n> Hi Jacopo\n>\n> Thanks for the comments!\n>\n> On Wed, 19 Jan 2022 at 10:13, Jacopo Mondi <jacopo@jmondi.org> wrote:\n> >\n> > Hi David,\n> >   sorry to catch up late and thanks everyone for the great discussion\n> > on v1.\n> >\n> > I'll leave a few more comments here\n> >\n> > On Tue, Jan 18, 2022 at 11:37:50AM +0000, David Plowman wrote:\n> > > This patch describes a series of controls that allow applications to\n> > > drive AF algorithms:\n> > >\n> > > AfMode - manual, auto or continuous\n> > > AfRange - full, macro or normal\n> > > AfSpeed - fast or slow\n> > > AfMethod - single or multi-spot\n> > > AfWindow - AF window locations\n> > > AfTrigger - start (trigger an AF scan) or cancel\n> > > AfPause - pause continuous AF\n> > > LensPosition - position of lens from lens driver\n> > > AfState - reset, scanning, focused or failed\n> > > ---\n> > >  src/libcamera/control_ids.yaml | 295 ++++++++++++++++++++++++++-------\n> > >  1 file changed, 235 insertions(+), 60 deletions(-)\n> > >\n> > > diff --git a/src/libcamera/control_ids.yaml b/src/libcamera/control_ids.yaml\n> > > index 9d4638ae..0b5ea9bd 100644\n> > > --- a/src/libcamera/control_ids.yaml\n> > > +++ b/src/libcamera/control_ids.yaml\n> > > @@ -406,27 +406,6 @@ controls:\n> > >              The camera will cancel any active or completed metering sequence.\n> > >              The AE algorithm is reset to its initial state.\n> > >\n> > > -  - AfTrigger:\n> > > -      type: int32_t\n> > > -      draft: true\n> > > -      description: |\n> > > -       Control for AF trigger. Currently identical to\n> > > -       ANDROID_CONTROL_AF_TRIGGER.\n> > > -\n> > > -        Whether the camera device will trigger autofocus for this request.\n> > > -      enum:\n> > > -        - name: AfTriggerIdle\n> > > -          value: 0\n> > > -          description: The trigger is idle.\n> > > -        - name: AfTriggerStart\n> > > -          value: 1\n> > > -          description: The AF routine is started by the camera.\n> > > -        - name: AfTriggerCancel\n> > > -          value: 2\n> > > -          description: |\n> > > -            The camera will cancel any active trigger and the AF routine is\n> > > -            reset to its initial state.\n> > > -\n> > >    - NoiseReductionMode:\n> > >        type: int32_t\n> > >        draft: true\n> > > @@ -507,45 +486,6 @@ controls:\n> > >              The AE algorithm has started a pre-capture metering session.\n> > >              \\sa AePrecaptureTrigger\n> > >\n> > > -  - AfState:\n> > > -      type: int32_t\n> > > -      draft: true\n> > > -      description: |\n> > > -       Control to report the current AF algorithm state. Currently identical to\n> > > -       ANDROID_CONTROL_AF_STATE.\n> > > -\n> > > -        Current state of the AF algorithm.\n> > > -      enum:\n> > > -        - name: AfStateInactive\n> > > -          value: 0\n> > > -          description: The AF algorithm is inactive.\n> > > -        - name: AfStatePassiveScan\n> > > -          value: 1\n> > > -          description: |\n> > > -            AF is performing a passive scan of the scene in continuous\n> > > -            auto-focus mode.\n> > > -        - name: AfStatePassiveFocused\n> > > -          value: 2\n> > > -          description: |\n> > > -            AF believes the scene is in focus, but might restart scanning.\n> > > -        - name: AfStateActiveScan\n> > > -          value: 3\n> > > -          description: |\n> > > -            AF is performing a scan triggered by an AF trigger request.\n> > > -            \\sa AfTrigger\n> > > -        - name: AfStateFocusedLock\n> > > -          value: 4\n> > > -          description: |\n> > > -            AF believes has focused correctly and has locked focus.\n> > > -        - name: AfStateNotFocusedLock\n> > > -          value: 5\n> > > -          description: |\n> > > -            AF has not been able to focus and has locked.\n> > > -        - name: AfStatePassiveUnfocused\n> > > -          value: 6\n> > > -          description: |\n> > > -            AF has completed a passive scan without finding focus.\n> > > -\n> >\n> > As Naush suggested, should the existing FocusFoM control be removed\n> > too ?\n>\n> Ah yes, I forgot about that. Actually I think FocusFoM is useful. For\n> example, on our HQ cams the lens position can only be changed (quite\n> literally) \"manually\", so it's important for the user to be able to\n> watch the FocusFoM change while they twiddle the lens.\n>\n> >\n> > >    - AwbState:\n> > >        type: int32_t\n> > >        draft: true\n> > > @@ -690,4 +630,239 @@ controls:\n> > >              value. All of the custom test patterns will be static (that is the\n> > >              raw image must not vary from frame to frame).\n> > >\n> > > +  - AfMode:\n> > > +      type: int32_t\n> > > +      draft: true\n> > > +      description: |\n> > > +        Control to set the mode of the AF (autofocus) algorithm. Applications\n> > > +        are allowed to set a new mode, and to send additional controls for\n> > > +        that new mode, in the same request. Furthermore, setting the mode to\n> > > +        the value it currently has is also permitted (with no effect).\n> >\n> > Is the last statement required ? Doesn't this apply to all controls\n> > (re-setting them to the same is no-op) ?\n>\n> True enough, I'm happy to remove that. I just wanted to be sure\n> everyone agrees that this is fine and that it won't start spitting out\n> warnings!\n>\n> >\n> > > +      enum:\n> > > +        - name: AfModeManual\n> > > +          value: 0\n> > > +          description: |\n> > > +            The AF algorithm is in manual mode. In this mode it will never\n> > > +            perform any action nor move the lens of its own accord. The only\n> > > +         autofocus controls that have an immediate effect are AfMode (to\n> > > +         switch out of manual mode) and LensPosition (so that the lens can\n> > > +         be moved \"manually\").\n> > > +\n> > > +         In this mode the AfState will always report AfStateReset.\n> >\n> > Indentation seems off here and in the descriptions of other controls.\n>\n> Not sure what happened there. Maybe some tabs crept in and got removed\n> badly, but I'll fix it up.\n>\n> >\n> > For what is worth, I do prefer having a Manual mode where LensPosition\n> > is valid. I understand it forces applications to move to a different\n> > state before moving the lens, but as Han-lin reported it would help\n> > with translating to/from Android and matches more closely the AE\n> > controls definition we agreed on.\n>\n> I think a separate manual mode is OK if we can send both \"manual mode\"\n> and a lens position in the same request.\n>\n> >\n> > I think we will never really find out how much Manual helps with\n> > translating to Android until we don't actually do so, but in the\n> > meantime I would keep it and if proves unecessary remove it later.\n> >\n> > For RPi it implies apps have to do one extra step. Can this be hidden\n> > in your applications maybe ?\n>\n> Yes, if one can send these commands at the same time then it really is\n> very painless.\n>\n> >\n> > One thing which is not clear to me is what happens when transitioning\n> > to Manual. For AE controls we decided switching to Manual from Auto\n> > retains the lastly computed exposure time until applications do not\n> > submit an ExposureTime control. Does this make any sense for\n> > autofocus ? Would 'retain the last lens position' when moving from\n> > Auto/CAF actually freeze the autofocus and implement the 'pause' that\n> > was discussed in v1 ?\n>\n> The behaviour when switching from anything else to manual should be\n> that the lens doesn't move. You're right it would implement a \"pause\"\n> command but I think the discussion with Hanlin moved us towards a\n> separate control for that. \"Pause\" has a special control value where\n> you can tell it to \"pause when you are not scanning\", and there's the\n> question of what CAF does when you \"resume\". Does it resume from\n> exactly where it left off? Or does it start a scan again? The way I've\n> described things here:\n>\n> * If you switch from something else back to CAF, it will immediately\n> proceed to do a scan (it has no reason to believe the lens is anywhere\n> sensible).\n> * If you \"resume\" after a \"pause\" it will resume from where it left\n> off. So if it thought it was in focus, it will stay like that (until\n> such time as some image statistics suggest it needs to rescan).\n> * If it was scanning but got paused during the scan, resuming will\n> carry on with the scan. (Actually I wonder if the scan should start\n> over rather than carry on from exactly where it was, but maybe that's\n> an implementation detail).\n> * Another difference, as I've described things here, is that \"Pause\"\n> leaves the state unchanged, so you can see what state CAF was in,\n> whereas moving to \"Manual\" puts it back to \"reset\". This could be\n> changed, of course, though I worry a bit about mixing the modes\n> together (see next comment).\n>\n> >\n> > > +        - name: AfModeAuto\n> > > +          value: 1\n> > > +          description: |\n> > > +            The AF algorithm is in auto mode. This means that the algorithm\n> > > +            will never move the lens or change state unless the AfTrigger\n> > > +            control is used. The AfTrigger control can be used to initiate a\n> > > +            focus scan, the results of which will also be reported by AfState.\n> > > +\n> > > +            If the autofocus algorithm is moved from AfModeAuto to another\n> > > +            mode while a scan is in progress, the scan is cancelled\n> > > +            immediately, without waiting for the scan to finish.\n> > > +\n> > > +         When first entering this mode the AfState will report\n> > > +         AfStateReset. When a trigger control is sent, AfState will\n> > > +         report AfStateScanning for a period before spontaneously\n> > > +         changing to AfStateFocused or AfStateFailed, depending on the\n> > > +         outcome of the scan. It will remain in this state until another\n> > > +         scan is initiated by the AfTrigger control. If a scan is\n> > > +         cancelled (without changing to another mode), AfState will return\n> > > +         to AfStateReset.\n> > > +        - name: AfModeContinuous\n> > > +          value: 2\n> > > +          description: |\n> > > +            The AF algorithm is in continuous mode. This means that the lens\n> > > +            can re-start a scan spontaneously at any moment, without any user\n> > > +            intervention. The AfState still reports whether the algorithm is\n> > > +            currently scanning or not, though the application has no ability\n> > > +            to initiate or cancel scans, nor move the lens for itself.\n> > > +\n> > > +         When set to AfModeContinuous, the system will immediately initiate\n> > > +         a scan so AfState will report AfStateScanning, and will settle on\n> > > +         one of AfStateFocused or AfStateFailed, depending on the scan\n> > > +         result.\n> > > +\n> > > +            The continuous autofocus behaviour can be paused with the\n> > > +         AfPause control. Pausing the algorithm does not change the value\n> > > +         reported by AfState, so that applications can determine the\n> > > +         state of the algorithm when the pause control took effect. Once\n> > > +         un-paused (\"resumed\"), the algorithm starts again from exactly\n> > > +         where it left off when it paused.\n> > > +\n> >\n> > I like the defintion of these two modes, the only thing I'm not sure\n> > is the Pause. As suggested [CAF|Auto]->Manual would have the effect to\n> > pause the algorithm until the lens is not moved explicitely, but would\n> > report StateReset according to the current defintion, while you here\n> > suggested that [CAF]->Pause would not change the AfState. Why is this\n> > useful for applications ? I might have missed that...\n>\n> It's hard to predict why this might be useful, but it feels like\n> providing full information is usually a good thing. For example, if\n> you pause CAF and do some captures, if the state reports \"failed\" (or\n> even \"scanning\") rather than \"focused\" the UI could pop up one of\n> those \"your picture might be blurry\" warnings!\n\nSince the PauseDeffered would not stop AF immediately if it's scanning\nand only pause when the scanning is done,\nthe application might expect the AfState transit from scanning to\nfocus gradually and can decide whether to\ntake a picture or wait for the focus.\n\nI would understand them as:\n[CAF]->Pause: AF is running according to the hint of pause, and only\nbecause it's running, the AfState has meaning, and the AF can resume\nfrom where it was.\n[CAF|Auto]->Manual: AF is not running and the application has full\ncontrol, and only because it's not running, the AfState has no meaning\nin the case.\nThe definition sets it to StateReset. In fact, the application should\nignore the AfState if it's in Manual mode.\n[Auto]->AF_TRIGGER: Restart a full scan, no matter what's current\nstatus, until focus or fail.\n\nThe difference to me is the duration to get a good focus.\n[CAF|Auto]->Manual: Quick, but whether it's a good focus is due to application.\n[Auto]->AF_TRIGGER: Long time, but good focus.\n[CAF]->Pause: Balanced, quick and good focus. Can be resumed from\nwhere it was, so the image won't be blurry suddenly.\n\nThe Manual mode for 3A also gives applications an opportunity to\nimplement its 3A algorithm, since it delegates the full control to\napplication.\nFor example, GCam has its own AE algorithm working on the manual mode,\nand uses the result for HDRNet processing.\nAlthough it may not be a strong reason =.=, I'm more inclined to treat\nmanual mode as an independent case, which does not mix with other\nmodes.\n\nPause does \"influence\" AfState since it hints the AF to stop\nsomewhere, and needs a period of time to reach the stable state.\nShould we have AF reports the status reacting to the progress, like\n\"pausing\" and \"already paused\"?\n\n>\n> I suppose you could have manual mode report states other than just\n> \"reset\", but I worry a bit that we're mixing our modes together, which\n> means understanding manual mode properly means you have to understand\n> CAF. I also quite like the idea that entering a mode (CAF in this\n> case) completely resets and restarts it. CAF algorithms (especially\n> contrast detect ones) can have a nasty habit of getting stuck in the\n> wrong place, so it's reassuring if there's a guaranteed way to restart\n> it.\n>\n> >\n> > > +  - AfRange:\n> > > +      type: int32_t\n> > > +      draft: true\n> > > +      description: |\n> > > +        Control to set the range of focus distances that is scanned.\n> > > +      enum:\n> > > +        - name: AfRangeNormal\n> > > +          value: 0\n> > > +          description: |\n> > > +         A wide range of focus distances is scanned, all the way from\n> > > +         infinity down to close distances, though depending on the\n> > > +         implementation, possibly not including the very closest macro\n> > > +         positions.\n> > > +        - name: AfRangeMacro\n> > > +          value: 1\n> > > +          description: Only close distances are scanned.\n> > > +        - name: AfRangeFull\n> > > +          value: 2\n> > > +          description: |\n> > > +            The full range of focus distances is scanned just as with\n> > > +         AfRangeNormal but this time including the very closest macro\n> > > +         positions.\n> >\n> > We should start thinking how to map the lens movement range to such\n> > 'closest marco' and 'close distances'. I honestly don't know enough to\n> > immagine if a linear mapping to the lens movement range is enough or\n> > not.\n>\n> I remember working with some VCM modules where the driver range was\n> mapped to 0-255. But in reality, infinity was around 220, hyperfocal\n> around 200 and the closest focus would be around 50. Most of the AF\n> time was spent searching the last few centimetres in front of the\n> lens, which is the reason for having AfRangeNormal as well as\n> AfRangeFull.\n>\n> >\n> > > +\n> > > +  - AfSpeed:\n> > > +      type: int32_t\n> > > +      draft: true\n> > > +      description: |\n> > > +        Control that determines whether the AF algorithm is to move the lens\n> > > +        as quickly as possible or more steadily. For example, during video\n> > > +        recording it may be desirable not to move the lens too abruptly, but\n> > > +        when in a preview mode (waiting for a still capture) it may be\n> > > +        helpful to move the lens as quickly as is reasonably possible.\n> > > +      enum:\n> > > +        - name: AfSpeedNormal\n> > > +          value: 0\n> > > +          description: Move the lens at its usual speed.\n> > > +        - name: AfSpeedFast\n> > > +          value: 1\n> > > +          description: Move the lens more quickly.\n> > > +\n> > > +  - AfMethod:\n> > > +      type: int32_t\n> > > +      draft: true\n> > > +      description: |\n> > > +        Control whether the AF algorithm uses a single window in the image to\n> > > +        determine the best focus position, or multiple windows simultaneously.\n> > > +      enum:\n> > > +        - name: AfMethodSingle\n> > > +          value: 0\n> > > +          description: |\n> > > +            A single window within the image, defaulting to the centre, is used\n> > > +            to select the best focus distance.\n> > > +        - name: AfMethodMultiSpot\n> > > +          value: 0\n> > > +          description: |\n> > > +            Multiple windows within the image are used to select the best focus\n> > > +            distance. The best focus distance is found for each one of the\n> > > +            windows, and then the distance that is closest to the camera is\n> > > +            selected.\n> >\n> > I have an hard time understanding why this control cannot be inferred\n> > by the number of rectangles passed to AfWindow.\n> >\n> > If it's a shortcut for 'default to center' I'm in two minds. Can we\n> > say that 'no AfWindow == default to center' ? Do we lose anything with\n> > that ?\n>\n> Good point. For a while I was wondering whether there's a \"method\"\n> where you can have multiple windows but treat them as if they were one\n> region, so you'd sort of get an \"average best focus\".\n>\n> I also wondered whether AfMethodMultiSpot should be divided into\n> AfMethodMultiSpotNear and AfMethodMultiSpotFar - in the latter case\n> you'd choose the furthest focal distance. Does anyone think that might\n> be useful?\n>\n> Maybe we drop \"AfMethod\" for now, and bring it back in future if we\n> ever find a reason?\n>\n> >\n> > > +\n> > > +  - AfWindow:\n> > > +      type: Rectangle\n> > > +      draft: true\n> > > +      description: |\n> > > +         Sets the focus windows used by the AF algorithm. The units used express\n> > > +         a proportion of the ScalerCrop control (or if unavailable, of the entire\n> > > +         image), as u0.16 format numbers.\n> >\n> > My first reaction was \"we should refer to the ActivePixelArray not to\n> > ScalerCrop\", reason being ScalerCrop is optional and might not be of\n> > interest of the application to specify one.\n> >\n> > But I'm not sure if the active pixel array is the right target either.\n> > I assume these rectangles get directly translated to some ISP\n> > parameters that allows to specify grids where to sample the pixels\n> > contrast from ? If that's the case what they do refer to ? I assume\n> > it's the input RAW picture size, something not exposed to apps by\n> > libcamera, but that pipeline handlers have access to...\n>\n> I'm not sure what the answer is here. I guess it's worth imagining\n> what happens to the focus windows if an application zooms in and out\n> (digitally). As the zoom changes, do we want applications to have to\n> recalculate the focus windows all the time? That feels quite onerous.\n>\n> I'm sure an application would prefer to say something like (for\n> example) \"put a window in the middle and one in each corner\" and then\n> those windows stay there (in the output image) regardless. Perhaps\n> that's what we should be aiming for?\n>\n> It would certainly be unhelpful if you zoomed in and discovered you\n> were focusing on things that aren't even in the output image!\n\nIt's interesting. I quote Android's definition here:\n\"Pixel coordinates within android.sensor.info.activeArraySize...\"\n\"If the metering region is outside the used android.scaler.cropRegion\nreturned in capture result metadata, the camera device will ignore the\nsections outside the crop region and output only the intersection\nrectangle as the metering region in the result metadata. If the region\nis entirely outside the crop region, it will be ignored and not\nreported in the result metadata.\"\nAlthough to me it's not solving the problem just avoid focusing on\nitems outside of the ScalerCrop :D.\n\nI guess we can delegate the calculation to the application?\n1. AfWindow and ScalerCrop in ActivePixelArray coordinate.\n2. AfWindow and ScalerCrop are per-frame controls.\n3. The application knows the ScalerCrop and thus knows how to\ncalculate AfWindow if the application wants it to be the center of\nScalerCrop.\n4. Implicitly intersect ScalerCrop and AfWindow for AF to avoid\naccidentally strange focus.\n\n>\n> >\n> > > +\n> > > +         In order to be activated, a rectangle must be programmed with non-zero\n> > > +         width and height. If no rectangles are programmed in this way, then the\n> > > +         system will choose its own single default window in the centre of the\n> > > +         image.\n> >\n> > Ah!\n> >\n> > > +\n> > > +         If AfMethod is set to AfMethodSingle, then only the first Rectangle in\n> > > +         this list is used (or the system default one if it is unprogrammed).\n> > > +\n> > > +         If AfMethod is set to AfMethodMultiSpot then all the valid Rectangles in\n> > > +         this list are used. The size of the control indicates how many such\n> > > +         windows can be programmed and will vary between different platforms.\n> > > +\n> > > +         size: [platform dependent]\n> > > +\n> > > +  - AfTrigger:\n> > > +      type: int32_t\n> > > +      draft: true\n> > > +      description: |\n> > > +         This control starts an autofocus scan when AfMode is set to AfModeAuto,\n> > > +         and can also be used to terminate a scan early.\n> > > +\n> > > +         It is ignored if AfMode is set to AfModeContinuous.\n> >\n> > And in Manual too\n>\n> Yes!\n>\n> >\n> > > +\n> > > +      enum:\n> > > +        - name: AfTriggerStart\n> > > +          value: 0\n> > > +          description: Start an AF scan. Ignored if a scan is in progress.\n> > > +        - name: AfTriggerCancel\n> > > +          value: 1\n> > > +          description: Cancel an AF scan. Ingored if no scan is in progress.\n> > > +\n> > > +  - AfPause:\n> > > +      type: int32_t\n> > > +      draft: true\n> > > +      description: |\n> > > +        This control has no effect except when in continuous autofocus mode\n> > > +        (AfModeContinuous). It can be used to pause any lens movements while\n> > > +        (for example) images are captured. The algorithm remains inactive\n> > > +        until it is instructed to resume.\n> > > +\n> > > +      enum:\n> > > +        - name: AfPauseImmediate\n> > > +          value: 0\n> > > +          description: |\n> > > +            Pause the continuous autofocus algorithm immediately, whether or\n> > > +            not any kind of scan is underway. The AfState will continue to\n> > > +            report whatever value it had when the control was enacted.\n> > > +        - name AfPauseDeferred\n> > > +          value: 1\n> > > +          description: |\n> > > +            Pause the continuous autofocus algorithm as soon as it is no longer\n> > > +            scanning. The AfState will report AfStateFocused or AfStateFailed,\n> > > +            depending on whether the final scan succeeds or not. If no scan is\n> > > +         in currently progress, the algorithm will pause immediately.\n> > > +        - name: AfPauseResume\n> > > +          value: 2\n> > > +          description: |\n> > > +         Resume continous autofocus operation. The algorithm starts again\n> > > +         from exactly where it left off, with AfState unchanged (one of\n> > > +         AfStateFocused, AfStateFailed or following AfPauseImmediate it\n> > > +         might also have been in the AfStateScanning state).\n> > > +\n> > > +\n> > > +  - LensPosition:\n> > > +      type: int32_t\n> > > +      draft: true\n> > > +      description: |\n> > > +         Acts as a control to instruct the lens to move to a particular position\n> > > +         and also reports back the position of the lens for each frame.\n> > > +\n> > > +         The units are determined by the lens driver.\n> >\n> > This would make it impossible to write apps in a portable way. I know\n> > nothing at the moment about lenses so I cannot propose a suitable\n> > range, but we should indeed define one and translate to the opportune\n> > lens positions using the CameraLens helper class ?\n>\n> Something like that might work. We could use the min/max of the\n> V4L2_CID_FOCUS_ABSOLUTE control to give the lens driver range. Though\n> I'm not sure how you would know which end is macro and which is\n> infinity. The default value could give you the setting for hyperfocal.\n>\n> But there's a problem because the lens driver range is not the\n> _useable_ range, which is normally quite a lot less. Perhaps the\n> device tree can be used to adjust the values the driver reports? Or\n> perhaps there should be some kind of database? Editing the device tree\n> because you want to try a different module seems harsh.\n>\n> The other catch is that the useable range (and hyperfocal position)\n> varies with the module type, even when they share a lens driver, and\n> there's normally no way to determine what module you have. For the Pi,\n> I'd probably expect to store the ranges I want to search in the tuning\n> file, so we only have to set the LIBCAMERA_RPI_TUNING_FILE variable\n> correctly, but that doesn't help an application to know what lens\n> positions it should use (for example, when an application starts I'd\n> expect \"move the lens to hyperfocal\" to be quite common).\n>\n> >\n> > > +\n> > > +         The LensPosition control is ignored unless the AfMode is set to\n> > > +         AfModeManual.\n> > > +\n> > > +  - AfState:\n> > > +      type: int32_t\n> > > +      draft: true\n> > > +      description: |\n> > > +          Reports the current state of the AF algorithm.\n> > > +      enum:\n> > > +        - name: AfStateReset\n> > > +          value: 0\n> > > +          description: |\n> > > +              The AF algorithm reports this state when:\n> > > +                  * It is in manual mode (AfModeManual).\n> > > +                  * The system has entered auto mode (AfModeAuto) but no scan\n> > > +                 has yet been initiated.\n> > > +                  * The system is in auto mode (AfModeAuto) and a scan has been\n> > > +                 cancelled.\n> > > +        - name: AfStateScanning\n> > > +          value: 1\n> > > +          description:  |\n> >\n> > This is instead indented a bit too much to the right.\n> >\n> > > +              AF is performing a scan. This state can be entered spontaneously\n> > > +              if AfMode is set to AfModeContinuous, otherwise it requires the\n> > > +              application to use the AfTrigger control to start the scan.\n> > > +        - name: AfStateFocused\n> > > +          value: 2\n> > > +          description: |\n> > > +              An AF scan has been performed and the algorithm believes the\n> > > +              scene is in focus.\n> > > +        - name: AfStateFailed\n> > > +          value: 3\n> > > +          description: |\n> > > +              An AF scan has been performed but the algorithm has not been able\n> > > +              to find the best focus position.\n> > > +\n> >\n> > I like AfState to be simple, but as suggested by Han-lin I'm afraid to\n> > be able to translate back to Android PASSIVE_FOCUSED vs FOCUSED_LOCKED\n> > we need an AfModeManual mode as you have in this v2.\n> >\n> > Thanks\n> >    j\n>\n> Thanks!\n> David\n>\n> >\n> > >  ...\n> > > --\n> > > 2.30.2\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 C231BBF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  9 Feb 2022 11:01:53 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 05151610F5;\n\tWed,  9 Feb 2022 12:01:53 +0100 (CET)","from mail-oi1-x22f.google.com (mail-oi1-x22f.google.com\n\t[IPv6:2607:f8b0:4864:20::22f])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D3F9D6106D\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  9 Feb 2022 12:01:51 +0100 (CET)","by mail-oi1-x22f.google.com with SMTP id s24so2043668oic.6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 09 Feb 2022 03:01:51 -0800 (PST)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=chromium.org header.i=@chromium.org\n\theader.b=\"IPTlQoem\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org;\n\ts=google; \n\th=mime-version:references:in-reply-to:from:date:message-id:subject:to\n\t:cc; bh=q28VyBkCgowD1BvlkzYtq75DaaxI9OUBmQHrsllIXKk=;\n\tb=IPTlQoemzWFi4FowmYjkCBdq68/Ih5A6JGgr5hCgYW8onjPcG7IPfK1L7berev6Dij\n\tKecTxiHmFXhbeOFuM30mMgE7cqNCPQAZonMhS1nbyYaPNjXUSlVU9f5RagDxD2p5ks+O\n\tMqeW97iZRERN8f+FwbzzRTOQkKf7yK/DmHElI=","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=x-gm-message-state:mime-version:references:in-reply-to:from:date\n\t:message-id:subject:to:cc;\n\tbh=q28VyBkCgowD1BvlkzYtq75DaaxI9OUBmQHrsllIXKk=;\n\tb=S3/Pmg2O3F50Vk/rj8MgKRVpWdWoOQM4/LBO4vzPXWSB4CMuEd6pXdHbaB5LYzHpcX\n\tRfpM/xxPjD5wzha/jh5tqcjPWpRNh7dEfq9DuuIALdy6SmBtt4A6EQVGJpZNmdKlpdi2\n\tcVAaJZCdknbbRR+wyOBXoyPEFk+sq6mCTxcZn9OVUeteh3BmlUO4A5xRqgd1kI2PTPVX\n\t3GAH6ydUzCpK88VH7tPgbRxyLB6bJKrnc00alntT/Q8FGoAM137wOnphOd7vApoCZBd8\n\tsDx2hV7oXFuXczBq8Jb8KzbnwKJof1PnMow5exjlfDuvnCMsdoq7tNQ2akj/q7a3FI37\n\tdNrA==","X-Gm-Message-State":"AOAM533nIQupTDeJibdv62IAh+vUL+22IY7Owdx89LONMUVINhwktPjI\n\tC8l5YPzCg7jBhaxZkqSgfWnj3SrB9D6eURr1dCgj9g==","X-Google-Smtp-Source":"ABdhPJyjU0a/9f9/hc4+Fi8ZCxi2GyotWrj4NHRTPrdf0QdXGCgGE3rrIUzos2f+axJ4cS1qvdgLMschj2Kx9GaBwtI=","X-Received":"by 2002:a05:6808:191c:: with SMTP id\n\tbf28mr671482oib.41.1644404509897; \n\tWed, 09 Feb 2022 03:01:49 -0800 (PST)","MIME-Version":"1.0","References":"<20220118113750.19943-1-david.plowman@raspberrypi.com>\n\t<20220118113750.19943-2-david.plowman@raspberrypi.com>\n\t<20220119101436.d66ehnefosumza7k@uno.localdomain>\n\t<CAHW6GYLDJb741-uLLZyy0k=S_cAvb0c=mWoNkQrquA60wyM+nw@mail.gmail.com>","In-Reply-To":"<CAHW6GYLDJb741-uLLZyy0k=S_cAvb0c=mWoNkQrquA60wyM+nw@mail.gmail.com>","From":"Hanlin Chen <hanlinchen@chromium.org>","Date":"Wed, 9 Feb 2022 19:01:39 +0800","Message-ID":"<CAJAuwM=ieT4SUwCGHva2AmppTFj8oN4XY2QczXV3zRBGGka5fA@mail.gmail.com>","To":"David Plowman <david.plowman@raspberrypi.com>","Content-Type":"text/plain; charset=\"UTF-8\"","Subject":"Re: [libcamera-devel] [RFC PATCH v2 1/1] libcamera: controls:\n\tControls for driving AF (autofocus) algorithms","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>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]