[libcamera-devel] [PATCH v4 01/10] ipa: workaround libcxx duration limitation

nicholas at rothemail.net nicholas at rothemail.net
Fri Oct 28 00:41:26 CEST 2022


From: Nicholas Roth <nicholas at rothemail.net>

A bug in libcxx [0] used by clang version 11.0.2 is prevalent when
building libcamera for Android SDK30. This has been fixed and
integrated upstream with [1].

As a workaround, directly cast libcamera::utils::Duration objects to
std::chrono::duration when dividing.

Alternatives evaluated:
Considered: Enable public inheritance of std::chrono::duration and
override operator/ in the class.
Outcome: Does not fix the original compiler error.

Considered: Enable public inheritance of std::chrono::duration and
override operator/ in the libcamera namespace.
Outcome: new compiler error:
ld.lld: error: duplicate symbol: libcamera::operator/
(libcamera::utils::Duration const&, libcamera::utils::Duration const&)

Considered: Use private inheritance of std::chrono::duration and
re-implement a pass-through version of each std::chrono::duration
operator within libcamera::utils::Duration and use template
metaprogramming to fix the division operator.
Outcome: Testing shows that this would introduce substantial
limitations, i.e. requring the Duration object to be on the LHS of any
arithmetic operation with other numeric types. This also substantially
increases implementation complexity.

Considered: Extract double values from libcamera::utils::Duration
objects and use those to divide.
Outcome: This creates substantial readability and unit-safety issues.

[0] https://github.com/llvm/llvm-project/issues/40475
[1] https://github.com/llvm/llvm-project/commit/efa6d803c624f9251d0ab7881122501bb9d27368
Bug: https://bugs.libcamera.org/show_bug.cgi?id=156

Signed-off-by: Nicholas Roth <nicholas at rothemail.net>
---
 src/ipa/ipu3/algorithms/agc.cpp                 |  16 ++++++++++------
 src/ipa/raspberrypi/cam_helper.cpp              |   6 +++---
 src/ipa/raspberrypi/cam_helper_imx296.cpp       |   3 ++-
 src/ipa/raspberrypi/controller/rpi/.agc.cpp.swp | Bin 0 -> 45056 bytes
 src/ipa/raspberrypi/controller/rpi/agc.cpp      |  12 ++++++++----
 src/ipa/raspberrypi/controller/rpi/lux.cpp      |   3 ++-
 src/ipa/rkisp1/algorithms/agc.cpp               |  12 ++++++++----
 7 files changed, 33 insertions(+), 19 deletions(-)
 create mode 100644 src/ipa/raspberrypi/controller/rpi/.agc.cpp.swp

diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp
index a1a3c38f..f1650468 100644
--- a/src/ipa/ipu3/algorithms/agc.cpp
+++ b/src/ipa/ipu3/algorithms/agc.cpp
@@ -100,7 +100,8 @@ int Agc::configure(IPAContext &context,
 
 	/* Configure the default exposure and gain. */
 	activeState.agc.gain = std::max(minAnalogueGain_, kMinAnalogueGain);
-	activeState.agc.exposure = 10ms / configuration.sensor.lineDuration;
+	activeState.agc.exposure = 10ms /
+				std::chrono::duration(configuration.sensor.lineDuration);
 
 	frameCount_ = 0;
 	return 0;
@@ -240,17 +241,20 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,
 	 * increase the gain.
 	 */
 	utils::Duration shutterTime =
-		std::clamp<utils::Duration>(exposureValue / minAnalogueGain_,
-					    minShutterSpeed_, maxShutterSpeed_);
-	double stepGain = std::clamp(exposureValue / shutterTime,
-				     minAnalogueGain_, maxAnalogueGain_);
+		std::clamp<utils::Duration>(std::chrono::duration(exposureValue) /
+						minAnalogueGain_,
+					minShutterSpeed_, maxShutterSpeed_);
+	double stepGain = std::clamp(std::chrono::duration(exposureValue) /
+					std::chrono::duration(shutterTime),
+				minAnalogueGain_, maxAnalogueGain_);
 	LOG(IPU3Agc, Debug) << "Divided up shutter and gain are "
 			    << shutterTime << " and "
 			    << stepGain;
 
 	IPAActiveState &activeState = context.activeState;
 	/* Update the estimated exposure and gain. */
-	activeState.agc.exposure = shutterTime / configuration.sensor.lineDuration;
+	activeState.agc.exposure = std::chrono::duration(shutterTime) /
+				std::chrono::duration(configuration.sensor.lineDuration);
 	activeState.agc.gain = stepGain;
 }
 
diff --git a/src/ipa/raspberrypi/cam_helper.cpp b/src/ipa/raspberrypi/cam_helper.cpp
index d90ac1de..48a8a068 100644
--- a/src/ipa/raspberrypi/cam_helper.cpp
+++ b/src/ipa/raspberrypi/cam_helper.cpp
@@ -63,7 +63,7 @@ void CamHelper::process([[maybe_unused]] StatisticsPtr &stats,
 
 uint32_t CamHelper::exposureLines(const Duration exposure, const Duration lineLength) const
 {
-	return exposure / lineLength;
+	return std::chrono::duration(exposure) / std::chrono::duration(lineLength);
 }
 
 Duration CamHelper::exposure(uint32_t exposureLines, const Duration lineLength) const
@@ -85,8 +85,8 @@ std::pair<uint32_t, uint32_t> CamHelper::getBlanking(Duration &exposure,
 	 * frameLengthMax gets calculated on the smallest line length as we do
 	 * not want to extend that unless absolutely necessary.
 	 */
-	frameLengthMin = minFrameDuration / mode_.minLineLength;
-	frameLengthMax = maxFrameDuration / mode_.minLineLength;
+	frameLengthMin = std::chrono::duration(minFrameDuration) / std::chrono::duration(mode_.minLineLength);
+	frameLengthMax = std::chrono::duration(maxFrameDuration) / std::chrono::duration(mode_.minLineLength);
 
 	/*
 	 * Watch out for (exposureLines + frameIntegrationDiff_) overflowing a
diff --git a/src/ipa/raspberrypi/cam_helper_imx296.cpp b/src/ipa/raspberrypi/cam_helper_imx296.cpp
index ecb845e7..c5180de5 100644
--- a/src/ipa/raspberrypi/cam_helper_imx296.cpp
+++ b/src/ipa/raspberrypi/cam_helper_imx296.cpp
@@ -57,7 +57,8 @@ double CamHelperImx296::gain(uint32_t gainCode) const
 uint32_t CamHelperImx296::exposureLines(const Duration exposure,
 					[[maybe_unused]] const Duration lineLength) const
 {
-	return std::max<uint32_t>(minExposureLines, (exposure - 14.26us) / timePerLine);
+	return std::max<uint32_t>(minExposureLines, std::chrono::duration(exposure - 14.26us) /
+							std::chrono::duration(timePerLine));
 }
 
 Duration CamHelperImx296::exposure(uint32_t exposureLines,
diff --git a/src/ipa/raspberrypi/controller/rpi/.agc.cpp.swp b/src/ipa/raspberrypi/controller/rpi/.agc.cpp.swp
new file mode 100644
index 0000000000000000000000000000000000000000..7b26d5511f7338b4cd3f28246243c9110c39aab0
GIT binary patch
literal 45056
zcmeI536xw{dFMN9rT}9CHiWP}w{5vv>aLdLC3b7^X-O?vi6jfPY$3}!#p|lq-4E5~
zdQ~kovLS#68xzI^90m>v8Eg&=Gi+f8<Aj7 at Acll>*qi}|Ng#wZW*IXB%<uc|z3<&u
zOUnjM=FFsZ{C9P|<u2d-?svcK-kMu~)$YB)C8doc{CmvE$kH#auKeB^KY#EgkALV$
zquuN*%JozH)8{5yl~X)6GFgwRaX6`uPj1`2YtQa|S3YC17B`}BA!;U*(TPsfZiF>1
z%~isB)D9<;c4abdg_G?tY0X9L_HrwptTY>)cC%KC+LLX*h6|NarPVrB<*WBsDe!NZ
z0^QF1#3iSXT(EJ&dLhF(qh|+?d+e3}mMOB at _f-n4Qec$=s}xwJz$yh+DX>a`RSNu@
zqd=!s7<n$eevs|?t at iUbdOja&zrWCa{!!2UhuQBZ?dOwh0j`|W?Debd=PP>dKipow
z#(sXk=YGLnFWb*Ow!yCaN7(D3{roRI_a9=f&)LsMJ=px=-nU;ze$(D>^xU_XS3g!M
zuu6ed3anCKl>)02Sf#)!1y(7rN`X}htWsc=0{>4^AgqpzoJ-4JD)ut*e`o)H_KcB{
zPk}dr*MsMRli=AP0#|_<umhY2&IJzv4+h_S^vKBHfVY7^0 at s0);8`FBzY8Y8>EQ2A
z9~rp^d=UHv_)p*s-~f0!cr17fxaUzLBYy^Ba0na(vtToLH2Cf#M at GI1J^|hi-U{9V
zZU?Ug{}EgVHi7~;4cv><;Ge)Z!8^gNpbZwlesBeNDky;aa6tSR{0Mvn{5`k_{0Vq9
zSOiDFZt!!Q8J`B90<Q<J0ylyhI0m+WBKR^+k&l79z=y$~f}6oO_-*h6 at Obb@Pyi1H
z{{u(Mt3eyIz%}3icsh6r_!*9xFN05l_ks6<n?M38;F+Kdc7t7DCn$i^z+E^=UJe at I
zBJdr2AYTSw0IveC1T|0wd%;$)1w0-Uz)#?zZ-Q at tJHZ{`{Xlr at 7I1(5C7rMnSAwKd
zoto-&TeWC&+~|x4(+idD%|_B`hkV`JtVUZ$My?+zw4+Y9-3XQshV6x at Q))+Hwb%;V
zVLdrAx?Jw))zPD4n`qy)m&d`DVC_;^>qeVK3hvd3nce%Yn%={ecs?ket+&TU3i`?O
zuCQy%i}C2u5|wPOHoJ4RXlv1wx~KU7N)5Z6X3$@BtvRUZxn{RfrEvY6?X=^@La=2^
zFnZ<w{WAwfgUf<#^1#%Teh;SH*F9GpnmIsspiX}u3wy5ERXngihMeQUOuOA|j|H1I
z2cy%wwg;ruSo#K?<yI6Vi_LDW8q7t3siD~pwCqt!E5BW5XYE?ECf8!QV_q8zPST{n
zzgwD%7UD*6Y&>AFo849`YD3imqufa5o9%kht0Q~XzZf;DygpJ;exdn7B=5dAf_l}`
z*?W3xadebAPmaJ>c`lopQg%|Z1ZhUn)YRdyUb|xMSy81EtTF5{=JVpoVEuS7AGecE
zaJ}%Ij6=bE-x3^)mg%3enqDeJ^;T!OI0nZRq7$uV(rrh=-N_N2JWA`erS;}gRP=8v
z>!rhcGGH2v2PdzW3Qgf$kRth at 4F63tMGTkA!!W{(S8wiF?lTBM(NI8nca5}b+_3Ob
zc+T{{6ec_3N{4PR#7rb8NzJ_O(b<qh2rWEtzlbX2_ZycK4K>2nX0KqC4gO<WgEfAS
zlkt%uGQ}$-Cr#G7VWSfwT{00-DClI#(`-tJCftyavKBPDb at J4L=6p)ZAY>XZAh&{u
zytOz=0{PPtJ!rL?^KmU2mBHwroJJ}oi`@>Hait`Fc2pb-m{L-l{c31Fc(xC2ZoLa{
zE{01{5O#uE6!NWey!q>D-R59paNTu&3j;2hRw@;IrZ(bO=6t`bT2UTLNoF$diIX0g
z41ejrBS(uyRtHN|FDxmexfHAoHguCs!SzzD@<1kUbYe_wO~sP^ZlsKvjB{b-SUGMa
zQJWzt+My8<bc!Afl>PSg!97W3lF!}$+ES?=(M_akxjtAdx%(ou9++72-y9&8_S%Z2
z;J|;DQTx9xmi)%8AeQ{c5KFEXhL*p)Tsj`b3yYoP2(o6~I$0$$t)`y|^LkAo&xXAU
zO+RH at Ncm+}yhEl=M7>NnBkBv?MiMVHqAC)tBa)A%tROu5#hcMR7AiiSrh?s#O0(S-
ziJA#h+hq}xA{YD?Wm1vFY!>w~nMF>Dz$utz#$T|#7ip~1?p*0dJw+hbrU#-5*wses
zM$ET^9F_LRtw=JSx5b@=7Hqg+Q!u$UNTR5o1Sp4STOk)G=HgD!vX2I9C&|~WM)SND
z?3>;@6O5AgTnZN|qaz~_wY+0y=k9$o<?Yi4XLen2;ILKj&`P?A=tB+GrKA;BQ0YXg
zuEosgu$D|sRTkULMzicLY_iXLx=yzf%Y!?*ZM5=c!#$Cem_FNo3pI0lnyJl_dQRM^
z)VfUOQCePFr0v<2Qi<H~PFM{)q1?&csC7 at 2g{Ix4 at 75x$*jzx}@4Hitmf}h@?7i^#
zoOdg$Zgbk5$+<9zCTq=w(jvM++8!QgbWcpqRq7irx!|ISIBE6VSCeI{_d-2v`Cr4@
zLbDxr7VDHM<H}+r)F6L7m<Z6qC#Ppr6PE<{Abps}<jL*L)^b~>eo)*#7HnL<;nMNo
zfJ=-I_Q%1VPIY8*E&m0x`*%EJVh<!>p_<rTMe~T~<EV|5FuP-7<HYt_*i9m7fY|?H
zgKxnW7yIAEzu$x%zXUoU0lR?M`xk)Iz>j(Uhu~iDG4M+83Qz-L=Sz8;!Ro(N3anCK
zl>)02Sf#)!1y(7rN`X}htWsc=0;?4G|9}G4)p39*PJ&Zm+8MX_S{I7qsTdE|RB+>W
z#5I_O>x$WfYsVVVaf!P~l)>)m=Gl|ZXYV~}3Mytkg<!4sju^eJ9hu=A9LLrUI*YhI
zmT6(Vq`s7_CD#9nSE*qC#3!R(k~(oIducqVhbLx at 556o;WAQ-wmuRl at kVsc>tkmL`
zeW94%v89<{kpw~1`$cph#Ldu+Oo(7qE)o!cno+e}ayNJ3?xtejgSI1@>n at n+-FDq8
zpT!iqEgUJ)6cId)8w8!0z(h~U_MY1RTVTbnNg_P<|D0vZuVLeV3A_*dA$TS at 3J!xa
zz(=s{Zv at W=WpEDoIDUi^U<Pal+rW9?9Pl*odE)dh1<RlVwtzL at G2nB=<KG5u1XJLN
z;2(**e+2v?xE5Rq&IR8l#(oEQD|jP#5x4;y24{jV5?g- at xDEU<sDnjN1tB;c{Fqq!
zzks)Z8^QCzPEZ8jCXW7oa2q%Z&I9)mAHNse32p$FgLU9s at ZX4)-wECat_Qyhc7gN2
z&xnivFYr_F9`G*k9Iz2Q9DISe_-Db3!LvaZ>;?}8GA3Vf8x(#?aY69WvRcMfon|Mj
zxuC*uwz{I*X>~inar{-Cs4<RvlGidWYe(01BPJEz-y|4iR at 6Dg0k5fg@g}w=QKzV$
zKI6L^9cNyN6HjN5Ov3^mt+=j7LUf|qa!D^7qOwRFq0Su`gh_Bbs at 29NYF5E1$AnpK
z;s`w+Ht?YGq~Ug*<mS+bkpez2B0E}JZVEBEGb;4VE%&^g7zbs}_>bG`kjp)3(hD3N
zuad+9-XM5O#rR7jLiFns+~?-Gaw$jlea#)a{IdKZaYbcq&Alq(aj6+sjjWO3iKZLX
zopB>h7K?5Gg0;Ev7$+)@M=@*Mn8vKL8hmQd3;!$4%${>H1u<!)ix7$@G|X)|&AVe{
zoW}iB0QHnROrlNCBLIW>T3k8CXDGc58<hwivLX$BGgbO^Z3$RRW^>Id6#N?LSSsB8
z>*Fa`OSGvxu~iyel1Lwc4m!sa5{8uzBc@@>Fi7HRG!f0u6RCiC^=3U>4hT-+YOgoj
zkwk%I?dh2~1WTHFy&5mXOey<rO|n&p#cIq^xLsZ)fS^eMlvj;P!M>)<jz!|O9em&R
z#Y1VXMuNM(7Bre2R=`^GxRwwu$Rt^41|$)*<%+x|6GZ+gHB1;_YN~3z{KY&K4FP;|
z1#2xG``+|MV=PdLrORKwP?=h0boUcpY*rH}>*iJNhEQMD+uX%OqdP;}Kd>O}hQz7z
zB{`NjWmhDmJh)(qG-<Fpy&a#3s+JD}@?p---I%ruzO3oo6|rZ8p(S3HFCYWS*bx(&
zmlDT}h-9KOy30XWeU=3B-CMfIOJLOYFPk+%QABkNKhDW{K6dcw4yuMftdM$$g0UlB
zg4e5v+O)bfsUf6Xo!Z{mJI$sl>w-uIl at 3Nk_%%X&$Kc+?I|8{DB4TmEq2{H+99rZt
zb7lCjXEWdM?BL1YH`1;NDt0Z~>VUc%{cRI&&1ws_X8o{*z!HXUhYvluT<c5gEhn39
z`en)#gAB8#nxVwVzv5bKR*=cw;mz8V7EDiaBQm5bg at Uisx@s(8Y#Z#jS=y%)-|t4S
z#nB}{Cu}bbF=VEh&XYOPQ<Vy46Y<?-o>{lfyrnq-xlpTC42x}mcrrhIQuXvYtH&Qd
z$W_qno-{AZE)7T43wP$|ro$!bO-bkKv_Hv7*kPnm2Zk~ON`=QxTLPch-W|u*(5J6m
z_A%2m?;RCzMitVQ&6<jOTVpSe6l}_j-#Pl4jb_$P|FRn<!+5^llv7=-*5f4JQrM0|
zk|~3b%s-T-$Vj+uqY+i2BnjK(n$4kt5)3~sD_cE0W>?lk0-M3{#Yj at A&`ztmAd0lC
z$U3LG<SdsZ{w?dMcHPa{N!3S0nM8pk2Hst;HlieORW#p(bzEZdDlC0%tE!Ul%GQis
zmy1S^ays at Xi*Ha}=ry(m(O`(EwVIDwfHdA}-LAS73ubC%dRkwV at WGI~hyV=f`FH`|
zB^m5MRP9!xgNyBm4A5GYQI`4mOT9}DqORSkJ=@=^&Dr{ARi53m`(+##S#f0Gi^mt^
z%Ay(nibky)G;%p;CKXsh(-Q2$sD-BjV_Yl;hMwiAt}%02O<78#hK{$@y{tO76vj1S
zMCBXwsY=*5UvlF_&$9ZP8v<eBv=S8RrC3z`PO}-zhixjbdY4&djaVN-J1uE#P~3oQ
zm<W<q#1ap+`KNy~EJH1aV4Xa-Qn?~%qgtZcUSViCo7Dan)AB;>O|k!9Xzk38V&mTh
z-VAOBw}E9KK7eU(F?bqyD)<q$|G$7AfP27~z!$;0z&zLlE(Pa-CxPDv|A;@}cJNB@
zJn;MA7&ro+0S<v_a2ePN9ts`|z9PN?@LBK{&;s+|8DJy$A%25zfqTF^K?}@-XMjVX
z1kMGI2WNqA;ZJxoh`^J<ckv&52fPOC0}llc0r%lE_=)%pz$d|5!3)6iz;nTKz)>K1
z{rBQS_!M{zxE^c;o57QS<n(_Qf5NTc7O)7e1hYW$_%8$-!MR`*oDIH<kKx<kZ^0+P
zo4{@0R`7Cg3y at s?-vHml=kRs#XP^tVgVVsL at HN~5wt+{3FEZYL3qB6+25$pz0e=eq
z1pG0$8QcWsz{Nm$1pa`l`xd#fx6bse9saW8Kjtk`d6Tv!)7(l{o3%Ml!V+fY$q_YU
z)yWno`{g<EzeRi{9c`C=oGi4|O!r$uBb}%tpDOIuI{rfKz2vp6{~ad^tm!N1Hb at GT
zV-XgkHN;bHr5QCQU6Q#lB;6iepp64#v>GQOd8(u8n=~nF=`IH$*BaMi?PYo^Ig<ar
zkHxDjYRQ1h{ax6eCi{yH$6Jw?1)i(bzmXjAzoj+yUF@%K#w(uM at a||<sVb0uAN?E2
z5&v6STi?b0+V*<IQ=3yaq7yMgV~yva)x;WPg_7m3OTHndVI5j9OkJ|2YC+PhN8)Iz
zEQSpXa~WLx$3c<L<?~rpFv5akjplI-^`@30OduS<0I-;zpRhP6izRLi6H`eZFuMUL
zn^bT~l at F_9vRE~{=q*_0NN&r<e9(MZLitM;Q<GWmby!}uJ6>2jh8l28m{FNMQh-h#
zeNQ>%0c>p$kG_-wMcQW01#7i5$p_3$L#OCQOSCmwD(jHf#U;4L-Wr!}5~9dA=Sk}~
zjzL-d+*rjO2xyjUbi7Jft8`iHu|b!iaxpI94B6jqik3(!dm^i~+-P?jRvBP0I->l!
zmgF=K)l$o%Wjs4-H}SQ^omg#Z9Feso=;B!s4 at sS*Olh*D3;OMq at 8TCaNpt<!KyiJ-
zR+gN&^Dg<4rd$-$PhN*Oq5#NyzCVNqC`%p?adJ>MGPyZq?&%Fw+=R9-#hqnSq`opw
zMr5>|-9a5LQgW?XIhK9ZTD|F5E;hQgTC3CM$-M0F?u-<sgmKbvj32HcKH|+c|0QJ(
z{x>ve!&0I|%#DtrS?-dkN^)76VMVif$`|g^*AcDKQA)>|{MG#T{K}#U%L5hz7}uo-
z+q-2~Sy}9do-JE4hOn=F)KzG`$h`$cmi%RL+VmE*emzbBvqwSLFqoBv!UVGL;-G7W
z4Cry|CPZv7*e&67)*l at 4Z08`)6EPDu(mPdzl!<&5B&~HuCZ%hVTqs9Ny^S!v8DI{0
zugcvrVJfVJGG>%97kUa>U%F7p0$*X3EkyWmcM5Y#>a%Nscdx9Ro7ggZV}5J#Vkw8&
zjGfr(E5lyzc^_%F;o@><YjJ~)jnS&JiuHS6dpA<ga0!eYrs?-*zu_<$&h at amJ-7TO
zW{Xv}w2%A5v77SDrUBi|Xxz4)IFe;y+$}TtGRM at _!hPBE!Ux35))8%k<55|Ilic<)
zmOwW+DW~evxI*oIX{WB+U!aqsFFw4w-Q`pE+%HY)P8Ui#J<QD3{iH0 at qu#Oz1-bIC
zyTeB8I6F$i_wlKlJ{@l+jO7U(I^8Nrw^fnIGeL1lf>JVZ)H|jx2EW#gd=FqNU%qK8
z?3&3x$i5kEw>LXRWKkcmNm$8bHi70g^y!vNVc={>rhF^4y2)Z$qdX=mB-<>rx at 3jF
zU!%kDLH+DSyA4^$F8eF9?s(4(8WP!RW9D6MmyOTOx#DE>Rb>?x?w2a2E2mQLB>(?B
zY`O{TJF)*yTKoSO*!ABA-vXZl9{}$Mk`Hh*xCz_<c7mT{&)*0B4txmQ30?*M1CTud
zviE-(G=S_6I0h~O7lX6F<G^FVKVaW~9efnr1wIUJ1up{$xClH5jDTNY>)!?b8oU}D
z1!DiN2b19Y*!JHA9|0c*e+~W}cmcQuTn!Eb at dKO*<Q#x+0LeLc2Y4lT1vmsQ1{Z;|
zK>+?4f4~R9aj*og29E&W!uJ0s at M>@voCzKWK8?+P2Y5et8EAmZz**oi;2v!JcYqfH
z*~ec1e}ygo9B=|02b;iI;9hL`yTKd4>%mLG3&Hci6!-zQ{q5ieAbAGYgDb&9z-^4N
z*!Qmi*MXBj#(f;zuYaPB;2qNqr0odxShl)~MI-K5tB0DPCz^;(IFUQ at Km#vrFiSR0
zWl`AHY9l?dYXrU~51<Q+xv%q2JZPDp%V}U5I}?W{VX>TEjaz%b#VMJ2>fjup=*cwA
zYOvZR6WZ6~U9q#)dEQr`TmGy|KnOL1wubx_yOKC?ujANKz}P!tg9 at ccZ4k{3Z4bAl
z*ff|Q5?bcA4f;mQ#uF<0#9FOdEZG-c4uy<P!ajP!gJQl0VVjL)ZT#p?NsyQ^rBRpq
zz%iXNBTGA6N(a~klXZxwy@|VBR}-;QX&5H26ePY<smQs})!*7|81F{6HEvw=={{qz
zr)^N&5}IPf)Ve+pXJv4buf3Eq2Q7F*l(P&Z7Ok7p^23;W#yDEN=g=ZK$)P7BBUjSE
zC;G~<u at bExjuBJMx5$D?3|ILX6J>dCj_AUomafpyc^{mv<@SUN at x=ArA?lG(65a#Z
zR*oXQO!Oa(Ur6S&$MGo8kZ=P}vKY7RXu=Sa;mJ}7O!OnHu*uSdM>HA18&1xCNYm!j
znPo<d;hBT2FvX>ADbWzgvPCJ-(1j^yLhnmzpGW~Ld9U-<9S;XrW0EJt@#0<z&7{lR
z>yA&22cK7%5bj~WPmW}^Y~!*q4_?s-LL-Y36+d!%0T~Bfap=$y2&>0jEHa&<#uV>(
z?5I&gn at 5!6C^al?+%XMqoKiUDS#+?Zk!S9=@JPiL%x5`v;QQt|C!<QiL6S${4v0w}
z3o>U^H&V8jjSrF*3}pYTlKxaCSe=Z??adlaED_GqjDdyd9LfvVGIO9`XxolxQ)#V^
zc21%qcSui*4(5C#bf>D4ae0SHu93z#Svx&DJ9FS*G1pKzO+kDyQk|X7`TJhV(8)kN
zKP8cz2M8~@zjt|mZyOIJoTFz86y_tAyXoU|Snx!K#mv#=&FGc7l!_m50Y9YX=;(lG
zN5eFcR^_Rijm$u$Q##`$al{1J@(CyX)Kp$ggSdL%t!4RWvwurc^+pOD1CvC at qNs%;
z%NlCLu_fhT at g~Hid*bCrrjZ_HhEEj&Ul4?~<KZ&*G{vRSY)ptZP6z8Gqajhp0Mkxs
z7OYLF=jFbc87<PaxIGoLM$5)(NUw}*XdqM2<pp&o!_oa$MVrpj>zE_-+q1XKAtc7i
zNUO>{Aw`dAl}@7j74}~1tIkbR?UrZKxXOA9FjYaG)T8eD)_bk5DyW;jG^k&_1(>SD
z`jSM4Q^`BS1+!R3NLoGhMDsUOzd9b*B+wX6aSVk415dU#hm!iIOfWde)W_R>z1rEU
z6}n?U`d-cV#|mWYv-49hdMAZ&_pjP7JN+cq;uk--H}>HyncRQHGC-E2PLWx9dS8Ki
z(+9KSvd2wfd0(_N(RWVw6}i*Do0Xb-$rOyco6 at 4Cz9MFp+$cp$=27PsVTP*e&S&0-
z2!GiKw{@UM)UQ_ at mL&nNZ{W)s_c3XAUb!NQj3Pj6qA9r?PL-;*n=M@`jfawWy{%J4
z7B2O*!R~qIn$|_g>ermIGZ$%=3fg)l?uceCPCM2!WIxlQfhLX0adO0WcbXs#Ix4a!
z-)W`_4YtwF{(eDRp at PpILh$uTp5QDsT?yHc4__q at 9pmp0Z2rGHpI^@Z`!x6zcs+O>
z5SxDjjDrIBG&Z}$_`5*%`acnjfVX3x-vBNI6X2)V<9CA(fhBM;_yIQeUxHge8EgU<
zg9-3`Z0rw#4}w1jcY^D{v%#~#Ja`I_^Z0%M<Sf3IgE|-mj|6i5-iv|c{>R{KAm{D9
z9lRMVgAL$JAU612*xWaQ=Yu-f4xRwc0%wBHV|#xNNX%XA at eSZH;0*8~?Cu0?06)gg
z{t*y6{6B*VcnbI}@L}xiHaG`-7J3WKU+m at g>yqcBtI?j^VxS6Vuys&02wt?$%6V=k
zqm-4?oPc3ekG!bftflPG6Ee*G9$CIljYB;i?tT<!8nr at k6Q?T93f@`CfFb2iY>s?!
zxd+yz=0Vm%nf192=iV69!rTKB1B!HkNQ|mxgIUXwPZB-0=D8?tm6{mEhzx5N+x(>#
z%@5`=eT=9uDQ%*@+Q%qRv?&CL?w=6lPtwLQZn}-IvKU88k`GV{b~2c{aN^oanhljP
z`_lYxN~t!*MIa$)ktS&ujD1&&>vF=3Gq&;1G}|K7RM>d=d_L<K3pTG%i*nBIZZ_LH
z!%C;wMz&ZjS>&4;0P|XY#B#bpZwaX$>QtHG<>ZDbS5B~w6HwN3keAUlt5x$=#>1zE
z+5DtEkXz^+kV||matKdwZI at jnBw)zlHr7f|=?ZP-kVj)9?Zv`iY)K?7U1VxIAf^+U
z9>i6V#>81ijh}--iB441`WB6+PJT(u5teGUXEapKGSx^tp0#(63(!)DRFP|gM}3jx
zr48%#$RN#yq^Gc8g*@<P-Q<y6CZ+odtl1tTHJG_x^asl6l>XcqQ`NP{HP^G5#M?(=
zD3T?mvs^(@$<0(h*7+=eFskwR4fO4>cAAA)O*elx9ClTYm!jWSQWtNc&W(f20d-d}
zX_!-DGm?v``I;^_$MKt)icD$Yh;-GKV609L>uYkd7s=wb^jOPAs*)wN#thSg^eBh<
z>&$V{9js%G8^#$yV{piXt+>ioC+%_1h8)ILJbJ#}T9i44s-PC`VX51ZYBX!osIt3`
z4{i>`5=L_6nA=aKqo6V?PORNO-)&Tc-<b=v(`7se1H(;iGEy{irJ at P{F0(~kd{&gC
zG!);V>9_Mla=}llR2}MgvwciFhK8^MZFcRZrR+Xtr+rBKW%|zc583oEmdZHm8DqZ5
zU?0O at s{6qVVeR|7AfBd{By!4`95UL&#C_EDBwI>#!`|DCufa4)x53HFQmxxs(T*e+
z6=sJd(6NtEtwkdqf$b*SC}po)vn(BUsnyh9j9WyUUtQN2Dhy at R)cF^-+ccwU>KkCY
zr#ys^L9e!ZencT<z8;HlpXfj{h0L_tsYjWTbHFY at M422+#sg`=Jcqkpx+RmY+nVS!
zCuH}jXt|PrBMzpjomE*{%DQ!VeUwu$C6%WrB8pWut|a?As4 at v(2?%4RS|>oBR4S+>
zK#;q9imiwFV>S<k?FOyXeY6eicGPP*;&V!Le<Kvrort5bg7s7LhuxUcCtY)rRNhc`
z-i}D-Q#!{u<ZDvABQk{;2G#KGh{+402g=@@N~as9`!rdHg&bmd+es!2ZfY13<et&J
zX~LB0q?LVhc?x*@h_6I!du7{gJrA(bX>GMvV}DmnqX+Z`8E7K0;R#8KLV(DDb-ES1
zzZK)bh4}4cz6ix+4be}8FTzUC5{73{f=a<&*){;*=GIB~_&#x{Bd(8`2#kq~Y!)vb
z%a1q{MM}nXw&9svYH<(qZwSc`p-&(JavNpM?kL-VemAn|07YtN`*tVgxxjXJ1={r$
z;GXTT+3s}`<+-Pp;G}j^IMHY5oE at R<PF1;l0SsjBy}TMn*-~fEtQ8^6x+drLl}wvQ
zCAUSs&nofAaX|kuUiTf|_1r_!D!emZZlELunx!Z*i*-E;WzNrcYgU>XSt(6giB?3$
zdp)|j9*n74W__9}5ryYui51D}8YJqvq<tc;)h{5rkutBV+Mj@;a$?T=>RhWGks}Zl
zSCol;fhhc(2)99jD6#)ZmKgaPYyZ37-;-GX3&2yrpJUTkz{9~ivFGQ&esBdC2mcd$
z{wLtQ;AU_WxDo6C+rX1S0h|UN1|&cKo8Z;pCU6j(1AdB4e+Re$JQG|4o&X*Meuhnd
zCwM-Peg2OJl8^tFK=$~{8T%4*e=7J9_WWDHOTpFPBCrvB7d!sHgExWafhq7r at D*%$
zIVb;J;NOFzU>t~j|7dVJ_#C$VXTWR03&7>zLhvx~U$O093tj{cf=7VA!p8p~_zUn7
zAp83df at x3!{~LOL0^ALR_8$Yk;y+mlhlr(p&0zY_HoJfz=r}lDma}2AkkCdp1trd*
zhfYhvs(jG^$Tp_9GG}&aSO290_L7`&ioT@&UrFlK7RVJm%ywzdTP;1IlNGt$#!q{~
zxi-+0-n1f!Wi-9y8>vtuy`Gbl^dL0n$`UfXEc<(6Ywj`QpqWxnTc1LLXcGf0s%|EM
z#|Sgdou^nwWfAM?tzd0d;TEr1esgJ+FB&Jd`ZxW)xNi48?@MH!&oRzUj$uXF7DWig
zG4-S)<@n}ozkWEQR|(7d?8|DpZQk>H?mrN$^~;qcMqL)WjTmo9SuF0&ju~+4 at U@sf
z=m1Lk;!^o&dym5H3g|f_VNCT&r+vYhX>3FTDnccznW=rACZw5gi%=_<2rYY`-3w0t
z$^t?9c)lEYVaWXT-*<ber7igc`cl3;qZ?H?G<H^h7{SYJOWPqTmQgD6 at 5*`R`7639
zB<_fI%?;TWxDwN3 at 1lg^4^tf|yO`E5#i$e_g-(NU&eiWl+>(->zb-r`Z5sFl_F;8U
z|5RVnj7QdDn8_^i?Ml5h=;>00V}aXZDh{TK{=k9J{QHUTk5M1#{hP`!Srz^*A-n(m
zff3!knPx*M)!o%o(A<B_qj*X?F;tZF`3IHo{w3|5kliD7-~E0<`;V+hW`ADxk=ei5
zLuUV$klFwKz{u?0G+8A|V|VEkH1;1`k;eH4mB#+1K{W2W-%n%z5kq6=Pr_rdES@^!
ztEw8yU(F`@MG|#rjMnkAjhbCkQ9ChzIB$n%_pA2}qdlHCR=*R0ZbtRRtUS4zduG<=
z+Nq at Mdut_Oxs<nD*@Tpp;Yvl;rnULeOBU8#*iyDGr4RN7mgV8zYke=c8duJ<NGtKS
zOrbOx?~Ab}WW$-bmONrRCyUxQxGcn&&_p`xoU3BGVgUEJgj46ucAe68KTP!qxrz&&
zMfpL2^RHQdzI2 at ZS!LM=E!Vl6u)?&Ki&d)Q4uPi)y4(tVNXOQs32(X4g&TP)jv*EO
zICR)zB%8<9+9D`iN-`_2BeSgP1cC at F@Q2yAB#VRZC#P*gR?0oRLv8rvp_4eGG!srI
zX;z%1wTO+>8|ugoaWH<z8M{wMl{@O}i%ii-UtQ6>zN{MVN-(yNt|kLY9TL-9mkT|(
zo!}ZLk#%sz5={iHw{H@$hFxqhBUd87*CJ*5J;_=6wvE1;))z6%7cSmW6Vy3X(SyQ$
zzAmegcE8;#7VT at b16!SYpqI#Q4a!=sb4eDm9Bp!i4C+AcfnLJ**HXx_OzQLUuC5C<
z=qZGI+>DR~78T@|;DdF3w0KP8|6+Q+O8!Uwf7u$LZ^!Px8A#0k>0mE-IQTd|06F{b
z<=~m%Qt&l=051X?z?ndN0bc^|2JZlppMMS55B7p{!Gplpu=(Y;`sCa{`Mth3foB5A
z$Cq>eo&y#^6;!|mupWFB+yA}b-Qaq#4g4nfI=27Uz*oV`fc(~84EBPDfY0CqxE(~`
zcfbWe&ieZRcn at fR3xMpuF9F$ee+PIscq6zOTm&QsU(Woy6|})Fumwo|{iWb6Faq9z
zAK>@F9_thMJM8`sfZM^<;A!Ad;9h9|J at 9Ry;~--&Ou+4wNQm)Ls#KHtVAi*y5ijM#
zX8AMU4x4+dDy(?oArRQq%)<yMa&(QPI4qK?prz^6UCz5aM9^L-zt(1cYt2Y^wTC#B
zs at X#5ik0Y+x at G=UO8Wb2BFC|FS$C{{KQ*;YoDuF<?8w!jK~gn&0MZuY?fZ4KcTba~
z`jy*zzZ$APW+zESuAy7~hFSwLqpBhQ0%1s2L8Y#antfTQG=#nxjWkS<jV-U(K$UBO
zpT%e+RYJmIWjt79_iy(^32?^Ul3X44hFq<qtgws`B)n8K8^tQ at N|J+CJ%bE)kT^q?
zlhT8^gm`T7Xope>qla^70}f`~Et)1_k6m$YdVBaObRo4pBa8gC0!?<CjoN|baJz5Y
zvbdp8j`tyzmdzf4v}sbj?Q(jJd5}uo4P*nS(Ld6fi)k(Eg3@~W<P$BuCqtm=$hL`x
z)s>9pODM~v2lwofp4e)CbZFeL56x1dOGZGfiUS{;gG)9Au|45Rd*YmKPH~s4S;=HT
zr_#faB!ny5K8U|z*2^iBRo49l!o7)6>UW4gn%KD8QLlkuO;?fdH_<x$()t at SoK7G)
zn{w)|q!_TBc+Nz}`F%zckoKuIqr7$4aL^tJyJR#ZZA0%0;j&j at DK#hEURu&#YGRY;
zE>@d$VdSxrWMdXBC+i3}0;qGHIIM6eAvUwyNYmNncY!>~Wcz;*1=^09;X8@(m{uV;
z8AQVP?PlFXk!;A at 5zy^$kPwh#A?=w`!njcow6MJGhS_aRw=ahi^oNRqMUOEiwn{@e
zv8%Me&x<CIY~Pi8%a`w-J$S{g1JirU+jj4pRc`Y|gdedK_Z&n)L0^h$r*`WK{fv at L
zWQ8xOSJx7jZd|zDWS7`|QeNrAwYlkeaZ`_=_2$adMo4t|-L5^|6SL}8()YLU)0E<s
zL&em8mUL@`p^5OAOq(^9Gse8!YdfWO2 at BYtTq^UEOZwAI92lu)hn-=2Q$KPpCNr)s
zJ)5d&*T=&Q&;U9!)#GdHjFoK=U!ccgi3u6CpRRdAHIBCp5v!$Z_cSqNO8lg3o~KhG
z@=HvIQhp+&U;Czju)h$~kTb`J1E{G)syHgkERjU(28pFAu9UX96`92O at gU>ZHLM`E
z4!8t*+5)vCRN1z>+uvo#x4v{KHj&I#h%U1mYmnpwa##^6%t)>}5ku~X=Ciq at -(qs^
zFkj7)2b#vR-0a%@J=7~d563!FA=`-VNI_QMA<)zs7MW1vXaqHx58ElO87nIPkTzYC
zl6H5f1hFSEL7pT~H*=L1M#Pr}m~+7DP1YS&M46*Hi^;3wBm*gVIl#{y5JBcymkwCu
z(Yc62imPXjNm+*^?%1f3JfRDY5j$?f+{{(7tIC|^DJlZ{XIS3MWFTYba<mpo9}nm}
zN1XfYygbVf?oIM5aVMgh`Lnn|v<?3k=2Uu^SvM!oaO@$W9hrFB_`9 at W!-X)sot6vv
z2X at H=7hUo at 0Y{Bl2GAPWMwfr^fIPVI(o5w*Q3<?c?3`|s6I?y3B^#ezH&~k_r&<(9
zQ7O{v68k0IkLIDZq}SKU(u=vzLbsNL9N9yV9EtVxQ0+4J=cX%_zMI-zZY~VEsa at n|
zd(cfw4K3AE9PBDV-6eiqPKj+KTyem-sPBX}*{16_*>bf(gUem`Rm#=A3@*3*tCZ`g
z54DV<Ar!C|8AR1;a=GoEdShc=`iqU3reg`AgTSbxAqmInUpl1vSIPi<qZ+3VjPkp-
zZO%>2Vlno#An~5*JDib1+NYeLD_I?g4^DwHx{+qrF4}ZjUqLdb`iYD{fQXRL5*)V$
zqQ&Y2l|=qR-%7<9DWZS{Yb|}~i3rhzpxuH59Qe~p^xXRBc=>25fQ6mLoB*~&>X}Hx
z)=8AmX}1wg)DuE7a;(v~+W$|$+<cF<|3k4o`FA(A{+-|sAh`f90WSvP3)ll54L*wP
ze<O&1{06`o;CtBrp93!iF9dS7-zDG-Pyipt?mq#34~&7IVe8A;|L*~B0M7>@*aBo9
zz<0pwz-{2QAO;KIx4?ba{GSJ(0e=9FfUCgi;GePgzX5Is*MKL0Ph#)i1h#>Tf#m=H
z2s{5v;A7x*K+fWOGPoN%|2;r*0^SM4_P+_lAOcSY_hIAz5WE+>1Uv^E1#7|gu=)Q1
zd==aVB2Wea_&PSfoVj-kC<E~YJP~}KG58kv0+8`|HyHAd)!${C4vc#vhedj3X`<>i
z6cvq`l4ehy&z#V6Hg$)gpS#I~kOvRR0jstURwvQvNu>(O0$d>5ki}Jw7Ls*17Ymor
zyM$P5sub(XkhW4o-|3gb9%a(#{s8B>?CEx(Ct|uIev)h3ouYn8SHNNAZe>}ygoaof
zAiuR$<J!=1*vn$(ZXEWq?wzoiX*^SpEA8flS?TL+dKM)@l at m5WmV%;2Ta0Pur*oTe
zlg&k`ejzaclYK15y2~j{q9CB3C-R%#<b{hKLEcfFt-W>>yzTWvx?<BM22w%pA!3Jd
z9P(`7YrG;nc=nJQjcdn^n8_s(0jMdh+hs{F2b<Nkp(Y`6GCTSSsz}jkzLvk=NqjRR
zR0p2LJf^;Gw^*R49gk!yhj1`dwRHq7!Y4MXT+%ejP-!t->;RF)LKcpBJxV>z92Xl>
zgtHpn)mVPJn5XDkCFWOGZThPf*sj9}Vbd?+>Yk(p-BLbdgAc`?MDa0S3Ct!q)b`Cp
zFRk;Sn(O^j)OVHi%qBbH1BZ1bPC*~7E(~wU4znlQ&`SMaoRzGxxvU?TnPz1dg!6c8
zGGm1S$C6oI%ifZCgW%Co*&L`mFul<{`W}*|9DJCdfg6|swV2&dB1M_csuWnw!RFlK
zGlLVbJYXi6p+#CVJ9?D0+)rAo-H}VwSAT<+sH%nVp$idMw+pjf4p}2+#t%+7Glw}Y
zkE*%LP7|t;?0+pse at Q|-A=os`D~|M#=BR8jyBpC4suALW>{hl+a2AG3`!)2ET|#tF
zw>>2_(Wv3(n)rjXNP>(U%N?1+n57LUMiM5jVz`K(sG%9P;w_?(Q59QkQfNw35L2cp
z_UDeQ_EN=#pzS3`H?>gRK_^;_dcA8L2hP+pQ?}Dy7CA?`hB_J1<iv1kmgU~VYz4`O
zqG^pzi5^e+aK6<&$&x|moLcD_-;RHk&r*N9G}$nTSclRU5lB!SsZ5mCZ7OAN1a at PH
zXIzdrH#+EU9+w>rI$G&3fG6EK%y!vGKUd>dNvy+129SjSO%)4vE`o-nm>VaZGuddL
zx(u0^xnm9J>nTn{u;MEBmTImxBm03JhTtFE+qccdRwXn{bzL`ERoFcM!M1`>qt9ZW
z+Of|s^nT9<KA_>ZgZ{7dsAhqT={t#E`jPwbm;!l&Lsuk`Q~7mly8pKW<e_YjHopd5
z$WG+vdahlP=Hx$&-1L5qEGxyf-&+5Dy|6J%+Yx9d|BQjs)0<h7sL|6VdsPYREymfy
zga!^WGe~YBo at HpB&0)L%ns~1n{3eEPw=#LsQ8H4 at jy^mks at o16I+`#zwNqCz^NT*x
zKT`xUOO at HIEk@piIJJ>CBB<g-&WYhcX}=6Cej)t)%*FYd_@!jR8 at Vicwaji`wN@!0
zk7&;+NYrFcLBomKPcJIVUC!}H|J)wN<kWVGY3~HbuW8<UROK)uJt$w4*2*&L1eBDY
z3~O{kYi(?p%+*>7u7FJK<GPzLI=|`+5!qcNiAoKk^DH>sgmE$B(KB!^_nrk=ej$Pb
zQq|50bHgFKnXu?<tYP+OAzdx`*(4FKb{42&C%>L!@_jg&Nscr#d|4Hjri{5AN>NO6
zW94ST%6jQZoVwYuBX(gtsOwa!33`IkXn{H-MS&U<f0_H{YIliG_Ka5}8l8G$ViP0(
E2js%%=l}o!

literal 0
HcmV?d00001

diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp
index bd54a639..65baab99 100644
--- a/src/ipa/raspberrypi/controller/rpi/agc.cpp
+++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp
@@ -418,7 +418,8 @@ void Agc::prepare(Metadata *imageMetadata)
 			Duration actualExposure = deviceStatus.shutterSpeed *
 						  deviceStatus.analogueGain;
 			if (actualExposure) {
-				status_.digitalGain = status_.totalExposureValue / actualExposure;
+				status_.digitalGain = std::chrono::duration(status_.totalExposureValue) /
+							std::chrono::duration(actualExposure);
 				LOG(RPiAgc, Debug) << "Want total exposure " << status_.totalExposureValue;
 				/*
 				 * Never ask for a gain < 1.0, and also impose
@@ -823,7 +824,8 @@ void Agc::divideUpExposure()
 			}
 			if (status_.fixedAnalogueGain == 0.0) {
 				if (exposureMode_->gain[stage] * shutterTime >= exposureValue) {
-					analogueGain = exposureValue / shutterTime;
+					analogueGain = std::chrono::duration(exposureValue) /
+							std::chrono::duration(shutterTime);
 					break;
 				}
 				analogueGain = exposureMode_->gain[stage];
@@ -838,10 +840,12 @@ void Agc::divideUpExposure()
 	 */
 	if (!status_.fixedShutter && !status_.fixedAnalogueGain &&
 	    status_.flickerPeriod) {
-		int flickerPeriods = shutterTime / status_.flickerPeriod;
+		int flickerPeriods = std::chrono::duration(shutterTime) /
+				std::chrono::duration(status_.flickerPeriod);
 		if (flickerPeriods) {
 			Duration newShutterTime = flickerPeriods * status_.flickerPeriod;
-			analogueGain *= shutterTime / newShutterTime;
+			analogueGain *= std::chrono::duration(shutterTime) /
+					std::chrono::duration(newShutterTime);
 			/*
 			 * We should still not allow the ag to go over the
 			 * largest value in the exposure mode. Note that this
diff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp b/src/ipa/raspberrypi/controller/rpi/lux.cpp
index 9759186a..410f6f44 100644
--- a/src/ipa/raspberrypi/controller/rpi/lux.cpp
+++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp
@@ -94,7 +94,8 @@ void Lux::process(StatisticsPtr &stats, Metadata *imageMetadata)
 		double currentY = sum / (double)num + .5;
 		double gainRatio = referenceGain_ / currentGain;
 		double shutterSpeedRatio =
-			referenceShutterSpeed_ / deviceStatus.shutterSpeed;
+			std::chrono::duration(referenceShutterSpeed_) /
+			std::chrono::duration(deviceStatus.shutterSpeed);
 		double apertureRatio = referenceAperture_ / currentAperture;
 		double yRatio = currentY * (65536 / numBins) / referenceY_;
 		double estimatedLux = shutterSpeedRatio * gainRatio *
diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp
index 04062a36..bb874356 100644
--- a/src/ipa/rkisp1/algorithms/agc.cpp
+++ b/src/ipa/rkisp1/algorithms/agc.cpp
@@ -74,7 +74,8 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)
 {
 	/* Configure the default exposure and gain. */
 	context.activeState.agc.gain = std::max(context.configuration.agc.minAnalogueGain, kMinAnalogueGain);
-	context.activeState.agc.exposure = 10ms / context.configuration.sensor.lineDuration;
+	context.activeState.agc.exposure = 10ms /
+					std::chrono::duration(context.configuration.sensor.lineDuration);
 
 	/*
 	 * According to the RkISP1 documentation:
@@ -212,16 +213,19 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,
 	 * Push the shutter time up to the maximum first, and only then
 	 * increase the gain.
 	 */
-	utils::Duration shutterTime = std::clamp<utils::Duration>(exposureValue / minAnalogueGain,
+	utils::Duration shutterTime = std::clamp<utils::Duration>(std::chrono::duration(exposureValue) /
+									minAnalogueGain,
 								  minShutterSpeed, maxShutterSpeed);
-	double stepGain = std::clamp(exposureValue / shutterTime,
+	double stepGain = std::clamp(std::chrono::duration(exposureValue) /
+						std::chrono::duration(shutterTime),
 				     minAnalogueGain, maxAnalogueGain);
 	LOG(RkISP1Agc, Debug) << "Divided up shutter and gain are "
 			      << shutterTime << " and "
 			      << stepGain;
 
 	/* Update the estimated exposure and gain. */
-	activeState.agc.exposure = shutterTime / configuration.sensor.lineDuration;
+	activeState.agc.exposure = std::chrono::duration(shutterTime) /
+				std::chrono::duration(configuration.sensor.lineDuration);
 	activeState.agc.gain = stepGain;
 }
 
-- 
2.34.1



More information about the libcamera-devel mailing list