[libcamera-devel] [libcamera] AeLock proposal v3

Jacopo Mondi jacopo at jmondi.org
Mon Sep 13 19:11:23 CEST 2021


Sorry for being late to the party

On Thu, Sep 02, 2021 at 07:32:41PM +0900, paul.elder at ideasonboard.com wrote:
> Hi Laurent,
>
> +CC David and Naush and libcamera-devel

I'll cc them as I don't see them in the receivers' list

>
> Sorry for pulling you guys in late. The designs that we have right now
> for debate is my first diagram and Laurent's two diagrams. This email
> specifically is my thoughts and augumentations on Laurent's second
> diagram (which I think is better than his first (and both are better
> than mine)). Although we do also have a discussion on the "big" AeEnable
> control.
>
> On Tue, Aug 31, 2021 at 05:53:19AM +0300, Laurent Pinchart wrote:
> > Hi Paul,
> >
> > On Thu, Aug 26, 2021 at 05:16:25PM +0900, paul.elder at ideasonboard.com wrote:
> > > Hello,
> > >
> > > Here's v2.
> >
> > I've taken the liberty to update the subject.
>
> I'm going to update this to v3 :D
>
> >
> > > On Fri, Aug 20, 2021 at 07:36:28PM +0900, paul.elder at ideasonboard.com wrote:
> > > > Hello,
> > > >
> > > > I guess I had an idea for AeLock so here we are...
> > > >
> > > > The premises/requiements are:
> > > > - when you set a control, and don't set it in the next request, you
> > > >   expect it to stay
> > > > - we need to support "semi-manual" mode, eg. manual gain with auto
> > > >   exposure
> > > > - we need to support seamless switching between full-manual,
> > > >   semi-manual, and full-auto modes
> > > > - we need to support custom minimum values for the manual controls
> > >
> > > I guess I forgot about the requirement:
> > > - must allow switching from auto to manual without flickering
> >
> > Isn't life easier when you forget the requirements ? :-)
> >
> > > I think we can just introduce lock controls for the sub-ae controls. The
> > > goal is to have a way to tell the camera to use the last auto values
> > > *immediately*, until the manual controls that the application provides
> > > can make it through the pipeline.
> > >
> > > Well, "lock control" or "tristate manual mux". Let's upgrade the
> > > diagram.
> > >
> > > AeEnableTri --------------------------+-----\
> > > 0: full-auto                          |     |
> > > 1: semi-manual                        |     |
> > > 2: full-manual                        |     |
> > >                                       V     |
> > > ExposureManual ----------------\     |\     |
> > > 0: use auto                    |     | \    |
> > > 1: use manual           /------^-----|0 \   |
> > > 2: lock AE              |      |     |   \  |
> > >                         |      V     |   |  |
> > >                         |     |\     |   |  |
> > >                   AE ---+---> |1\    |   |  |
> > >                               | |    |   |  |
> > >        locked AE value -----> |2|----|1  |--)--> set and return ExposureTime
> > >                               | |    |   |  |                   ExposureState?
> > > ExposureTime -----------+---> |0/    |   |  |
> > >                         |     |/     |   |  |
> > >                         |            |   /  |
> > >                         \------------|2 /   |
> > >                                      | /    |
> > >                                      |/     |
> > >                                             V
> > > GainManual --------------------\           |\
> > > 0: use auto                    |           | \
> > > 1: use manual           /------^-----------|0 \
> > > 2: lock AG              |      |           |   \
> > >                         |      V           |   |
> > >                         |     |\           |   |
> > >                   AG ---+---> |1\          |   |
> > >                               | |          |   |
> > >        locked AG value -----> |2|----------|1  |--> set and return AnalogGain
> > >                               | |          |   |                   GainState?
> > > AnalogGain -------------+---> |0/          |   |
> > >                         |     |/           |   |
> > >                         |                  |   /
> > >                         \------------------|2 /
> > >                                            | /
> > >                                            |/
> >
> > I don't want to disturb your beautiful diagram, so I'll reply here.
> >
> > Haven't you swapped "use auto" and "use manual" for the ExposureManual
> > and GainManual controls ?
>
> Oops, looks like I have.
>
> >
> > The diagram is missing the algorithm block, so I'm not sure where it
> > fits. Do I understand correctly that AE and AG are respectively the
> > exposure time and the gain computed by the AGC algorithm ? Or are they
> > the algorithms themselves ? Note that AE and AG are effectively
> > implemented as a single AGC/AEC algorithm (the name varies depending on
> > the phase of the moon, I'll use AGC below).
>
> Oh right, I forgot that they were together as one. I meant the values...
>
> >
> > What's also missing is the inputs to the AGC, which has to take into
> > account for instance when running in manual gain, auto exposure mode,
> > the manual gain value to compute the exposure time.
>
> ...but I see that AEGC needs the manual of the other, okay.
>
> >
> > > So when {Exposure,Gain}Manual is set to 2, the camera will lock the
> > > {AE,AG} value (by saving the last {AE,AG} settings or whatever, that's
> > > implementation-dependent afaict).
> > >
> > > The application first sends a request with {Exposure,Gain}Manual set to
> > > lock, and AeEnableTri set to semi-manual (I think it makes sense too, since
> > > we're "switching" from full-auto and full/semi-manual).
> > >
> > > The application then confirms that the {Exposure,Gain}Manual control
> > > that is returned is 2, or that the {Exposure,Gain}State is locked. I
> > > guess it depends on if {Exposure,Gain}Manual is also an output control.
> > > I'm not sure how I feel about two controls that report the same thing
> > > though, though I think that the state has to be set to locked. Maybe we
> > > could just not output the {Exposure,Gain}Manual controls.
> > >
> > > Once the locking is confirmed, the application can copy the exposure and
> > > gain values, and feed them in along with AeEnableTri set to
> > > full-manual, and {Exposure,Gain}Manual set to manual.
> > >
> > > If the application only wants to go from auto to semi-manual, then they
> > > would only lock the control that they want to go manual.
> >
> > Do we actually need the AeEnableTri control ? Maybe I'm missing
> > something, but by putting the AGC in the middle, I think we could have
> > the following design, without AeEnableTri.
>
> Not really. It was to not confuse users: "wth why is there no ae control?"
>
> Though we could just treat the big ae control as an override?
>
> >
> > (Disclaimer: This is really brainstorming, as you'll see with the
> > multiple versions of the diagram below.)
> >
> >
> >   +----------------------------+-------------+------------------+-----------------+
> >   |          INPUT             |  ALGORITHM  |     RESULT       |     OUTPUT      |
> >   +----------------------------+-------------+------------------+-----------------+
> >
> >     ExposureTimeMode                                             ExposureTimeMode
> >   ---------------------+----------------------------------------+----------------->
> >     0: Manual          |                                        |
> >     1: Auto            |                                        V
> >     2: Locked          |                                       |\
> >                        |                                       | \
> >                        |  /----------------------------------> | 0|  ExposureTime
> >                        |  |    +-------------+  exposure time  |  | -------------->
> >                        \--^--> |             | --------------> |!0|
> >     ExposureTime          |    |             |                 | /
> >   ------------------------+--> |             |                 |/
> >     AnalogGain                 |     AGC     |
> >   ------------------------+--> |             |                 |\
> >                           |    |             |   analog gain   | \
> >                        /--^--> |             | --------------> |!0|    AnalogGain
> >                        |  |    +-------------+                 |  | -------------->
> >                        |  \----------------------------------> | 0|
> >                        |                                       | /
> >                        |                                       |/
> >                        |                                        ^
> >     AnalogGainMode     |                                        |  AnalogGainMode
> >   ---------------------+----------------------------------------+----------------->
> >     0: Manual
> >     1: Auto
> >     2: Locked
> >
> > The diagram is divided in four sections horizontally:
> >
> > - Input: The values received from the request controls
> > - Algorithm: The algorithm itself
> > - Result: The values calculated by the algorithm
> > - Output: The values sent in request metadata and applied to the device
> >
> > (I don't like the word "result" much here.)
> >
> > The four input controls are divided between manual values (ExposureTime
> > and AnalogGain), and operation modes (ExposureTimeMode and
> > AnalogGainMode). The former are the manual values, the latter control
> > how they're applied. The two modes are independent from each other, and
> > each can take one of three values:
> >
> > - Manual (0): The AGC uses the manual value internally. The
> >   corresponding manual control from the request is applied to the
> >   output. The AGC result is ignored.
> > - Auto (1): The AGC computes the value normally. The AGC result is
> >   applied to the output. The manual value is ignored.
> > - Locked (2): The AGC freezes its result to the last value. The AGC
> >   result is applied to the output. The manual value is ignored.
> >
> >
> > Another way to look at it is as follows:
> >
> >   +---------------------+--------------------+
> >   |       INPUT         |      OUTPUT        |
> >   +---------------------+--------------------+
> >
> >     ExposureTimeMode        ExposureTimeMode
> >   ----------------------+-------------------->
> >     0: Manual           |
> >     1: Auto       /-----)----\
> >     2: Locked     |     V    |
> >                   |    |\    |
> >     ExposureTime  \--> |2|   |  ExposureTime
> >   -------------------> |0| --+--------------->
> >                   /--> |1|   |
> >                   |    |/    |
> >                   |          |
> >                   |          V
> >                +----------------+
> >                |                |
> >                |    AGC Core    |
> >                |                |
> >                +----------------+
> >                   |          ^
> >                   |          |
> >                   |    |\    |
> >     AnalogGain    \--> |1|   |    AnalogGain
> >   -------------------> |0| --+--------------->
> >                   /--> |2|   |
> >                   |    |/    |
> >                   |     ^    |
> >                   \-----)----/
> >     AnalogGainMode      |     AnalogGainMode
> >   ----------------------+-------------------->
> >     0: Manual
> >     1: Auto
> >     2: Locked
> >
> >
> > The AGC operates as follows, based on the mode control:
> >
> > - Manual (0): The AGC uses the manual value internally to compute the
> >   other parameters.
> > - Auto (1): The AGC computes the value automatically.
> > - Locked (2): The AGC uses the last output value internally to compute
> >   the other parameters.
> >
> > If all controls are set to manual or locked, the AGC will effectively
> > not compute anything anymore. If some controls are in auto mode, they
> > are computed automatically, with the value of the manual or locked
> > controls fixed to the manual value from the request or the last output
> > value respectively.

I think I already wrote 5 different incarnations of this email and
everytime I end up repeating the description of the existing models,
so I'll just leave one point here and I try to be brief

... I'm having an hard time understanding how a Manual->Locked transition
should happen and what its purpose would be. Locking the AGC to not
update its output makes sense if the AGC is in actual control of
computing the resulting output values, something that in manual mode is
not.

One thing I apreciate about the RPi model is that the AGC is never
really disabled, but is informed about the manual settings received
from application (which allows an smoother Manual->Auto transition).

One possible simplification would be to move the Locked states to only
apply when in Auto mode (ie they only apply to the AGC box, ignored
when in manual mode) to allow a smooth manual->auto transition.

   +---------------------+--------------------+
   |       INPUT         |      OUTPUT        |
   +---------------------+--------------------+

     ExposureTimeMode        ExposureTimeMode
   --------------------------+---------------->
     0: Manual               |
     1: Auto                 |
                             |
     ExposureTime            |    ExposureTime
   --------------------+     |     +---------->
                       |     |     |
                       |     |     |
   ExposureTime        |     V     |
   Lock         +------|---------+ |
   ------------>|      --> [0,1]---+
                |    AGC Core    |
   ------------>|      --> [0,1]---+
   AnalogGain   +------|--- ^----+ |
   Lock                |    |      |
                       |    |      |
                       |    |      |
     AnalogGain        |    |      |
   --------------------+    |      +----------->
                            |       AnalogGain
                            |
     AnalogGainMode         |  AnalogGainMode
   -------------------------+----------------->
     0: Manual
     1: Auto

I know this looks Android-like and I know the counter-argument that in
example RPi does not need this as it models locking the AGC by simply
disabling it. As a consequence, it had introduced the special '0' value that
re-enables the computation of the single channel (exposure or gain),
something I'm sure nobody is really in love with.

To sum it up:

- Explicit Mode states that control where the AGC output values come
  from (algorithm or directly from the application). It allows to
  enable/disable the computation per-channel as RPi does.

- To remove the ambiguity that disabling AGC results in a freeze (use
  the last computed values) and setting the manual values to 0 gives
  back control to the AGC:

  - Add a Lock control to the AGC machine.

  - -Require- a manual Exposure/Gain value when in Manual mode and do
    not reuse the last compute ones. This implies that disabling AGC
    won't fall back to use the lastly computed values but rather
    require application to provide one. As much as like this I'm not
    sure how we could fail accepting a request because of a 'bad
    control' combination.

I tried modeling a few flickerless transition from Auto to Manual and
we should be capable of doing so both on RPi and by receiving controls
from the Android API but I might have overlooked some cases.

I started modeling this version on top the RPi existing code, but it's
really not an exercize for 7pm I'm sorry :)

Thanks
   j

>
> Okay, conceptually the two diagrams show the same control flow. I'll go
> with the second one because the components are more explicit (as opposed
> to a medium-sized black-ish box AGC in the first one).
>
> >
> > (I'm not very fond of the word "Mode" either by the way.)
>
> Really? I think it's fine. It's manual-mode vs auto-mode vs
> locked(?)-mode.
>
> >
> > This is how it would map from Android to libcamera:
> >
> >   aeMode | aeLock || {Exposure,Gain}Mode
> >  --------+--------++----------------------
> >   OFF    | OFF    || 0 (Manual)
> >   OFF    | ON     || 0 (Manual)
> >   ON     | OFF    || 1 (Auto)
> >   ON     | ON     || 2 (Locked)
>
> Yeah, looks good to me.
>
> >
> >
> > On point to consider is the transition from Manual to Locked after a
> > Locked to Manual. When this happens, should we keep outputting the
> > manual value, or the previously locked value ? I'll refrain from sharing
>
> The value was unlocked once, and then locked again, so I think it makes
> more sense to use the manual value.
>
> > my opinion here, and will leave it as an exercise for the reader (i.e.
> > feedback is welcome). The implications of the decision need to be
> > considered on both a semi-manual mode (e.g. the exposure time
> > transitions from Manual to Locked while the gain has always been Auto)
>
> auto manual -> auto locked
>
> In which case this becomes trivial...
>
> > and fully manual mode (both the exposure time and the gain have been
> > Locked and then put to Manual mode, and they either both transition back
>
> locked locked -> manual manual -> locked locked
>
> this too I think.
>
> > to Locked together, or separately). We probably need to detail all the
> > possible transitions and check that everything will operate correctly.
>



> The simplier the better, so I think we could just define locked as
> "apply the values that were last applied". This matches what Laurent's
> second diagram has.
>
>
> START: thinking aloud
>
> Alright, I'm going to think out loud here.
>
>
> Hm, let's enumerate all of the states...
>
> case 1: auto -> locked
> case 2: locked -> auto
> case 3: locked -> manual
> case 4: manual -> locked
>
> auto auto -> auto   auto   - trivial
> auto auto -> auto   locked - 1
> auto auto -> auto   manual - seamful
> auto auto -> locked auto   - dupe
> auto auto -> locked locked - 1
> auto auto -> locked manual - 1 + seamful
> auto auto -> manual auto   - dupe
> auto auto -> manual locked - dupe
> auto auto -> manual manual - seamful
>
> auto locked -> auto   auto   - 2
> auto locked -> auto   locked - trivial
> auto locked -> auto   manual - 3
> auto locked -> locked auto   - 1 + 2
> auto locked -> locked locked - 1
> auto locked -> locked manual - 1 + 3
> auto locked -> manual auto   - seamful + 2
> auto locked -> manual locked - seamful
> auto locked -> manual manual - seamful + 3
>
> auto manual -> auto   auto   - seamful
> auto manual -> auto   locked - 4
> auto manual -> auto   manual - trivial
> auto manual -> locked auto   - 1 + seamful
> auto manual -> locked locked - 1 + 4
> auto manual -> locked manual - 1
> auto manual -> manual auto   - seamful
> auto manual -> manual locked - seamful + 4
> auto manual -> manual manual - seamful
>
> locked auto -> * * - dupe
>
> locked locked -> auto   auto   - 2
> locked locked -> auto   locked - 2
> locked locked -> auto   manual - 2 + 3
> locked locked -> locked auto   - dupe
> locked locked -> locked locked - trivial
> locked locked -> locked manual - 3
> locked locked -> manual auto   - dupe
> locked locked -> manual locked - dupe
> locked locked -> manual manual - 3
>
> locked manual -> auto   auto   - 2 + seamful
> locked manual -> auto   locked - 2 + 4
> locked manual -> auto   manual - 2
> locked manual -> locked auto   - seamful
> locked manual -> locked locked - 4
> locked manual -> locked manual - trivial
> locked manual -> manual auto   - 3 + seamful
> locked manual -> manual locked - 3 + 4
> locked manual -> manual manual - 3
>
> manual auto -> * * - dupe
>
> manual locked -> * * - dupe
>
> manual manual -> auto   auto   - seamful
> manual manual -> auto   locked - seamful + 4
> manual manual -> auto   manual - seamful
> manual manual -> locked auto   - dupe
> manual manual -> locked locked - 4
> manual manual -> locked manual - 4
> manual manual -> manual auto   - dupe
> manual manual -> manual locked - dupe
> manual manual -> manual manual - trivial
>
>
>
> So it looks like we have have to deal with any combination of the
> following cases.
>
> case 1: auto -> locked
> case 2: locked -> auto
> case 3: locked -> manual
> case 4: manual -> locked
>
> In the following transitions:
>
>   auto locked -> locked auto   - 1 + 2
>   auto locked -> locked manual - 1 + 3
>   auto manual -> locked locked - 1 + 4
> locked locked -> auto   manual - 2 + 3
> locked manual -> auto   locked - 2 + 4
> locked manual -> manual locked - 3 + 4
>
>
> Just to clarify, in the locked -> locked case, since our simple
> definition is consistent, the second request uses the value that was
> used in the previous request (and therefore outputted in the result
> metadata of the previous request).
>
>
> case 1: auto -> locked
>
> I think is straightforward. The value used for the sub-control is the
> value that was set for the last request, which is also the value that
> was outputted in the result metadata.
>
> case 2: locked -> auto
>
> This is also straightforward. The value that is used comes from the
> A{E/G}C.
>
> case 3: locked -> manual
>
> Also straightforward. The value is that is used comes from the manual
> control.
>
> case 4: manual -> locked
>
> Still consistent, the value that is used is the value that was last set,
> in which this case is the manual value that was set in the last request.
>
>
> Does it get any more complicated with the combo cases?
>
>
> auto locked -> locked auto - 1 + 2
>
> afaik AEGC needs to know if the other value is manual? I think that
> manual can be treated the same as locked in this sense, since both are
> "the AEGC can't change this value".
>
> So we have E-auto -> E-locked, G-locked -> G-auto, for example. The AEGC
> will use the E-value from the last result (in this case, it was
> calculated), and will calculate the G value. The locked G-value is
> discarded naturally.
>
>
> auto locked -> locked manual - 1 + 3
>
> E-auto -> E-locked, G-locked -> G-manual. AEGC will use the E-value from
> the last result, and use the G-value that is specified. I guess this is
> technically the same as full-manual? There's nothing auto.
>
>
> auto manual -> locked locked - 1 + 4
>
> E-auto -> E-locked, G-manual -> G-locked. Use the E-value from the last
> result (which was calculated), and use the G-value from the last
> result (which was specified).
>
>
> locked locked -> auto   manual - 2 + 3
>
> E-locked -> E-auto, G-locked -> G-manual. Use the G-value that is
> specified, and calculate the E-value.
>
>
> locked manual -> auto   locked - 2 + 4
>
> E-locked -> E-auto, G-manual -> G-locked. Use the G-value from the last
> result (which was specified), and calculate the E-value.
>
>
> locked manual -> manual locked - 3 + 4
>
> E-locked -> E-manual, G-manual -> G-locked. Use the G-value from the
> last request (which was specified), and use the E-value that is
> specified.
>
>
> Hm... that was easier than I expected... everything looks pretty
> straightforward... did I miss something? Is there some corner case that
> I'm overlooking?
>
>
> END: thinking aloud
>
>
> Anyway, my vote is Laurent's second diagram, with the following
> extensions:
> - "locked" means "use the value that was used for the last request"
>   - this is the same value as "the value was the reported in the result
>     from the last request that completed", as per Laurent's second
>     diagram, it's the output from the mux
> - the output of the mux is saved for precisely one request
>   - that means that it is overwritten every request
>   - "locked" will always take this value
>
> The consequence of this is that if you go auto -> locked then the values
> will be locked to the E/G values that were calculated for the *last*
> request, and not the ones calculated for the *current* request (which
> has the "locked" mode set). I think it's a fair decision and allows
> simplicity. I can't think of any consequent corner cases...?
>
> I guess it would cause an issue if you go manual -> locked, then it'll
> take the manual values from the last request... that might be
> noticeable. If we inform the user's it'll be okay, right? :p I don't see
> much purpose in locking in manual mode anyway, so maybe it's an
> acceptable side-effect?
>
> The expected control flow for going locked -> manual makes me think this
> transition is fine, since you wait for the locked mode to propagate
> through the pipeline first before setting your manual control. This
> means that when "manual mode + your control" comes in, it'll use your
> control for that request immediately. Same for locked -> auto.
>
>
> What do you guys think?
>
>
> Paul
>
> >
> > > The same flow should work for mapping android's aelock. When aelock is
> > > on, then AeEnableTri would be semi-manual and {Exposure,Gain}Manual
> > > would be lock. With aelock off, AeEnableTri and {Exposure,Gain}Manual
> > > would come from aemode.
> > >
> > > Let's confirm...
> > >
> > > aelock | aemode || AeEnableTri | {Exposure,Gain}Manual
> > >    off |    off || full-manual | manual
> > >    off |     on || full-auto   | auto
> > >     on |    off || semi-manual | lock | is this combination even valid?
> > >     on |     on || semi-manual | lock
> > >
> > > > I'm going to borrow Laurent's very nice diagram (although I guess I'm
> > > > not using it... it's still a nice diagram though).
> > > >
> > > >
> > > >  Controls                                                        Metadata
> > > >              /---------- == OFF ---------\
> > > >              |                           v
> > > > aeMode      -/             +------+     |\
> > > > aeLock                 --> |  AE  | --> |0\     +--------+
> > > > aeExposureCompensation     +------+     | | --> | Sensor | --> exposureTime
> > > >                                         | |     +--------+     sensitivity
> > > > exposureTime   -----------------------> |1/
> > > > sensitivity                             |/
> > > >
> > > >
> > > > I think keeping an overall AeEnable would still be useful, otherwise
> > > > users might be confused when they have to look for the AE sub-controls.
> > > > But also because we'll have odd interactions with my proposal later, it
> > > > might be good to make this a tri-state, for full-auto, semi-manual, and
> > > > full-manual.
> > > >
> > > > So to satisfy point 1, I think we should separate the manual controls
> > > > from the auto controls. As in, the manual controls should not be touched
> > > > by auto when auto is on. I think normally this shouldn't be an issue,
> > > > but I guess we should note it down otherwise we'll have people like the
> > > > raspberrypi guys do it.
> > > >
> > > > To support points 2 and 3 and 4 simultaneously, I am proposing to have a
> > > > corresponding control for the sub-controls that determines whether the
> > > > auto value should be taken or if the manual value should be taken. This
> > > > essentially consolidates android's "lock" method with raspberrypi's
> > > > "assume the last value" method, by us allowing the user to specify if
> > > > the manual or auto value should be used.
> > > >
> > > > Maybe we can call it ExposureManual and GainManual, or something along
> > > > those lines. An alternative is a single control with bitflags.
> > > >
> > > > Hm, maybe a diagram would be nice.
> > > >
> > > >
> > > > AeEnableTri --------------------------+-----\
> > > > 0: full-auto                          |     |
> > > > 1: semi-manual                        |     |
> > > > 2: full-manual                        |     |
> > > >                                       V     |
> > > > ExposureManual ----------------\     |\     |
> > > > 0: use auto                    |     | \    |
> > > > 1: use manual           /------^-----|0 \   |
> > > >                         |      |     |   \  |
> > > >                         |      V     |   |  |
> > > >                         |     |\     |   |  |
> > > >                   AE ---+---> |1\    |   |  |
> > > >                               | |----|1  |--)--> set and return ExposureTime
> > > > ExposureTime -----------+---> |0/    |   |  |
> > > >                         |     |/     |   |  |
> > > >                         |            |   /  |
> > > >                         \------------|2 /   |
> > > >                                      | /    |
> > > >                                      |/     |
> > > >                                             V
> > > > GainManual --------------------\           |\
> > > > 0: use auto                    |           | \
> > > > 1: use manual           /------^-----------|0 \
> > > >                         |      |           |   \
> > > >                         |      V           |   |
> > > >                         |     |\           |   |
> > > >                   AG ---+---> |1\          |   |
> > > >                               | |----------|1  |--> set and return AnalogGain
> > > > AnalogGain -------------+---> |0/          |   |
> > > >                         |     |/           |   |
> > > >                         |                  |   /
> > > >                         \------------------|2 /
> > > >                                            | /
> > > >                                            |/
> > > >
> > > >
> > > > This obviously extends to when we add aperture.
> > > >
> > > > I hope this makes sense.
> >
> > > The same flow should work for mapping android's aelock. When aelock is
> > > on, then AeEnableTri would be semi-manual and {Exposure,Gain}Manual
> > > would be lock. With aelock off, AeEnableTri and {Exposure,Gain}Manual
> > > would come from aemode.
> > >
> > > Let's confirm...
> > >
> > > aelock | aemode || AeEnableTri | {Exposure,Gain}Manual
> > >    off |    off || full-manual | manual
> > >    off |     on || full-auto   | auto
> > >     on |    off || semi-manual | lock | is this combination even valid?
> > >     on |     on || semi-manual | lock
> > >
> > > > I'm going to borrow Laurent's very nice diagram (although I guess I'm
> > > > not using it... it's still a nice diagram though).
> > > >
> > > >
> > > >  Controls                                                        Metadata
> > > >              /---------- == OFF ---------\
> > > >              |                           v
> > > > aeMode      -/             +------+     |\
> > > > aeLock                 --> |  AE  | --> |0\     +--------+
> > > > aeExposureCompensation     +------+     | | --> | Sensor | --> exposureTime
> > > >                                         | |     +--------+     sensitivity
> > > > exposureTime   -----------------------> |1/
> > > > sensitivity                             |/
> > > >
> > > >
> > > > I think keeping an overall AeEnable would still be useful, otherwise
> > > > users might be confused when they have to look for the AE sub-controls.
> > > > But also because we'll have odd interactions with my proposal later, it
> > > > might be good to make this a tri-state, for full-auto, semi-manual, and
> > > > full-manual.
> > > >
> > > > So to satisfy point 1, I think we should separate the manual controls
> > > > from the auto controls. As in, the manual controls should not be touched
> > > > by auto when auto is on. I think normally this shouldn't be an issue,
> > > > but I guess we should note it down otherwise we'll have people like the
> > > > raspberrypi guys do it.
> > > >
> > > > To support points 2 and 3 and 4 simultaneously, I am proposing to have a
> > > > corresponding control for the sub-controls that determines whether the
> > > > auto value should be taken or if the manual value should be taken. This
> > > > essentially consolidates android's "lock" method with raspberrypi's
> > > > "assume the last value" method, by us allowing the user to specify if
> > > > the manual or auto value should be used.
> > > >
> > > > Maybe we can call it ExposureManual and GainManual, or something along
> > > > those lines. An alternative is a single control with bitflags.
> > > >
> > > > Hm, maybe a diagram would be nice.
> > > >
> > > >
> > > > AeEnableTri --------------------------+-----\
> > > > 0: full-auto                          |     |
> > > > 1: semi-manual                        |     |
> > > > 2: full-manual                        |     |
> > > >                                       V     |
> > > > ExposureManual ----------------\     |\     |
> > > > 0: use auto                    |     | \    |
> > > > 1: use manual           /------^-----|0 \   |
> > > >                         |      |     |   \  |
> > > >                         |      V     |   |  |
> > > >                         |     |\     |   |  |
> > > >                   AE ---+---> |1\    |   |  |
> > > >                               | |----|1  |--)--> set and return ExposureTime
> > > > ExposureTime -----------+---> |0/    |   |  |
> > > >                         |     |/     |   |  |
> > > >                         |            |   /  |
> > > >                         \------------|2 /   |
> > > >                                      | /    |
> > > >                                      |/     |
> > > >                                             V
> > > > GainManual --------------------\           |\
> > > > 0: use auto                    |           | \
> > > > 1: use manual           /------^-----------|0 \
> > > >                         |      |           |   \
> > > >                         |      V           |   |
> > > >                         |     |\           |   |
> > > >                   AG ---+---> |1\          |   |
> > > >                               | |----------|1  |--> set and return AnalogGain
> > > > AnalogGain -------------+---> |0/          |   |
> > > >                         |     |/           |   |
> > > >                         |                  |   /
> > > >                         \------------------|2 /
> > > >                                            | /
> > > >                                            |/
> > > >
> > > >
> > > > This obviously extends to when we add aperture.
> > > >
> > > > I hope this makes sense.
>


More information about the libcamera-devel mailing list