[libcamera-devel] [libcamera] AeLock proposal v3
paul.elder at ideasonboard.com
paul.elder at ideasonboard.com
Tue Sep 7 11:10:47 CEST 2021
CC for real...
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
>
> 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.
>
> 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