From 1bfd40ae5e99c676132e94d858253557a61c51e9 Mon Sep 17 00:00:00 2001 From: Avinash Kumar Date: Thu, 23 Jul 2026 09:50:01 +0000 Subject: [PATCH] Release for CCG kernel v7.0.5 Signed-off-by: Avinash Kumar --- .../ipu75xa/gcss/IMX471_BBG803N3.IPU75XA.bin | Bin 219852 -> 228812 bytes config/linux/ipu75xa/libcamhal_configs.json | 22 -- .../linux/ipu8/gcss/OV08X40_KAFE799.IPU8.bin | Bin 296576 -> 299316 bytes config/linux/ipu8/libcamhal_configs.json | 14 +- config/linux/ipu8/sensors/ov13b10-uf.json | 4 +- config/linux/ipu8/sensors/ov13b10-wf.json | 4 +- include/utils/ScopedAtrace.h | 4 + modules/algowrapper/IntelCca.h | 3 + .../ipu75xa/FragmentsConfigurator.cpp | 7 - .../ipu75xa/GraphResolutionConfigurator.cpp | 2 +- .../ipu_desc/ipu7x/FragmentsConfigurator.cpp | 7 - .../ipu7x/GraphResolutionConfigurator.cpp | 2 +- .../ipu_desc/ipu8/FragmentsConfigurator.cpp | 7 - .../ipu8/GraphResolutionConfigurator.cpp | 2 +- modules/v4l2/v4l2_device.h | 5 + src/3a/AiqCore.cpp | 2 +- src/3a/AiqEngine.cpp | 3 - src/3a/AiqResult.cpp | 33 +++ src/3a/AiqResult.h | 1 + src/3a/AiqResultStorage.h | 2 + src/3a/AiqUtils.cpp | 10 +- src/3a/MakerNote.cpp | 2 +- src/3a/SensorManager.cpp | 10 +- src/3a/SensorManager.h | 3 - src/3a/intel3a/Intel3AParameter.cpp | 2 +- src/3a/intel3a/Intel3AParameter.h | 2 +- src/core/CameraBuffer.h | 6 + src/core/CameraContext.h | 37 +-- src/core/CameraDevice.cpp | 10 +- src/core/CaptureUnit.cpp | 2 +- src/core/CsiMetaDevice.cpp | 6 +- src/core/CsiMetaDevice.h | 6 +- src/core/DeviceBase.cpp | 2 +- src/core/FileSource.cpp | 1 + src/core/IProcessingUnit.h | 2 + src/core/InputEventMonitor.cpp | 7 +- src/core/IpuPacAdaptor.cpp | 21 ++ src/core/PSysDevice.h | 3 + src/core/ProcessingUnit.cpp | 10 +- src/core/RequestThread.cpp | 21 +- src/core/SensorHwCtrl.cpp | 257 ------------------ src/core/SensorHwCtrl.h | 22 -- src/core/SwPostProcessUnit.cpp | 19 -- src/core/processingUnit/IPipeManager.h | 2 +- src/core/processingUnit/PipeLine.cpp | 3 +- src/core/processingUnit/PipeLine.h | 3 + src/core/processingUnit/PipeManager.cpp | 4 +- src/core/processingUnit/PipeManager.h | 5 +- src/image_process/PostProcessorBase.cpp | 206 -------------- src/image_process/PostProcessorBase.h | 35 --- src/image_process/PostProcessorCore.cpp | 5 - src/iutils/CameraLog.h | 4 + src/iutils/CameraShm.cpp | 16 +- src/iutils/LogSink.cpp | 7 + src/iutils/LogSink.h | 1 + src/iutils/RWLock.h | 16 +- src/iutils/SwImageConverter.cpp | 6 +- src/iutils/Utils.cpp | 8 +- src/metadata/CameraMetadata.cpp | 22 +- src/metadata/ParameterHelper.h | 4 + src/metadata/icamera_metadata_base.cpp | 6 +- src/platformdata/AiqInitData.cpp | 39 ++- src/platformdata/CMakeLists.txt | 16 +- src/platformdata/CameraSensorsParser.cpp | 16 +- src/platformdata/JsonParserBase.h | 9 + src/platformdata/PlatformData.h | 4 + src/platformdata/gc/GraphConfig.cpp | 41 ++- src/v4l2/MediaControl.cpp | 107 +++----- src/v4l2/MediaControl.h | 20 +- src/v4l2/V4l2DeviceFactory.h | 4 + 70 files changed, 349 insertions(+), 845 deletions(-) diff --git a/config/linux/ipu75xa/gcss/IMX471_BBG803N3.IPU75XA.bin b/config/linux/ipu75xa/gcss/IMX471_BBG803N3.IPU75XA.bin index 3523005b2144b07105c457631fa08d20958e24f4..0164b31a30b71b511f3268f4639415c2c5712f24 100644 GIT binary patch literal 228812 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 diff --git a/config/linux/ipu75xa/libcamhal_configs.json b/config/linux/ipu75xa/libcamhal_configs.json index f04d7b1c..2e976a0a 100644 --- a/config/linux/ipu75xa/libcamhal_configs.json +++ b/config/linux/ipu75xa/libcamhal_configs.json @@ -21,33 +21,11 @@ // The value format of availableSensors is "sensor name"-wf/uf-"CSI port ID". // wf is word facing, and uf is user facing. "availableSensors": [ - "ov8856-wf-0", "ov13b10-wf-0", "ov13b10-uf-2", "ov08x40-uf-0", "ov08x40-uf-2", "imx471-uf-0", - "ov05c10-uf-0", - "lt6911gxd-1-0", - "lt6911gxd-2-2", - "isx031-1-0", - "isx031-2-0", - "isx031-3-0", - "isx031-4-0", - "isx031-5-2", - "isx031-6-2", - "isx031-7-2", - "isx031-8-2", - "ar0233-1-0", - "ar0820-1-0", - "isx031-5-0", - "isx031-6-0", - "isx031-7-0", - "isx031-8-0", - "ar0830-a-0", - "ar0830-b-2", - "isx031-a-0", - "isx031-b-2" ], "videoStreamNum" : 2 } diff --git a/config/linux/ipu8/gcss/OV08X40_KAFE799.IPU8.bin b/config/linux/ipu8/gcss/OV08X40_KAFE799.IPU8.bin index e3cfe05a60dbd075e7a72086afe023180518a30d..b333b9120302ff339f08d92b9a8bbbf0d95e2a69 100644 GIT binary patch delta 5572 zcma)94@g{f9KYYY=c)64dFpNV^gKPO(FP+=vT2%i3&O<=-uB#Tp{b14)+?rC#foG% z8cQgL_N^YlWUh?LCY(9EYLh8!Zj8|!1pOh|O~UsGr~W zeLlbM=llJA-|r&b`Nu!YU+FM^Zob-5^^E>E(LaA>5=XJa>5v@D9Yu}|hjW;=kh~we z&c6A>LE`xQH{~beAp%FUC3s7yhX%ouZLB8IOPM~9Z)Sm8kP+G@sI;lr;jqPNp>IhR zL`zmdKapTua5EtrS4i+|L9M>(hGNl8zpJ(rNHE`$3BNlVn3W1qrQXf z88Ec07J76#d&q=ef$1)n2CE`-)g>HMW1l=x$L3;xdtS(7r zax&9RR}HeyG+)ewNHFO{stA=Hm~xEJoV|AA}zeVSTpD ztQ^f&siYU(Dob9jA41Dy2JOi4!+?(NDaNrCq7OVC5u_Y;r6WhBQ`I>3ipT$6u4>BFQ6g~=c^229F@8Pg}SS8+;ejx!Fz^a_PR4PRwnBmLzJj!mK>ob$=Fat5!I zNh*UFISok)?YWEN3}1tVjSOnUeq5-~8%0j!>0F`8AZ3ytB1JM?UxnigSLTWoI-p=Q zsU*SwA7B<3ec6KG2*M79d{9Ac&AX)8o)*J#nl$*_@0a}7@>c#V~L zYD3yGo}NS^om+Sc{ac)jRiz#wU8_RJ5(>?JVQH&IzcB<*wPX9SgjcnsD(o?WCGFKxUMjE^>W;CoW=F+z|A^MhAY(9ksoIIb3z-+U= z-F%xOdyxjOiq)4A)illBW{cVWc;=Bkw(6ZY$ z0ym52`^32wFR37G7G(>(Uk z^N5^VWjnb!I_lykdFt}&w-BqmeDC)iLgh8RZ~l+B^;lSNTI^|fZ<8?H>6Dz@Lr{Vw z_}-^t@2ljpM`{o|-+UXpY5tgOvZpp*zo1$6a3>KQ8ARrrGidrXF8lay#GZ!vrzVla zy~gk2+7my7B>48A1oXGTfHN`R0$=bl(65)4J^a$9+I!suckjWoh@HQ88@pNB=4sy6 zWBSF_+B={9@(l9bWbeG=+zy}W?_#rYL@nYMt*=?J)&)e*f8l$*BH}mS^?l35?eO-N zCHZwVYx~@>pjC!2zd0AiDs=uAYnJ5iuR{FX(lY#JUrs;A=O0%P|EZV6CBOA}G`l~> ewO8ILCceMT@8p{l--SfDHD;19iySy8Zu=j~x5?`O delta 5091 zcma)9e{7q@8TQ?GZu}+wVmEb?FLlzmDr?t~5F-lxk(fG6rG~}S!v2GlWib$@f}1u} z5gpT9c~iAX6B!Yg?No_WNjq3I8c1-&v5s`n#D=;mqD38|T4Cun@k^tW5zv@qy7#mF zeZKR)%uW7C?w<2|_dd__zIUEIR+ky6(;V<~<@t?w?0~;$=4<^(Q{vaOQ$I$IXYT*U zpB!}D)kuT5i_RlA-HW}dff}D#L(!c+s_`m1?IN(E$C*cHyGN(vIIabn9S(Wz;EpO9 z_Ba9Uq~BKDss*A5VEY4Hv z*dK}^Kmk7usxfu;vN#jj6*wHSu;2}^oyeB5iw0I%E-<$Yg4Y22h{H+;nCFJ+6iTAnvbYf*pn8^XY^dA$CYG9wbm@xBk z9pu-Di)@5y{WP;GCd?RqTv`Pg-(s#wSA%(caW%2aoLTTej@HP)`|9KBaLUBz>QlnV zh}hGRP{)2^;!_R4fi*JluEvBqd)&mw8-W9BG@^qCbja~{CO)D=j(;&neSSX;G(nEm zOu7kj{I`imoBhpq#s9QFCQS7CA-$jp8@2PXAJXeFXQIuJo;5P? zcbens*d7xPwLp5-$f%`-mbf~5*u>k{fP@p~$f%pSHF064r8T83y;{Wc?Pdnu$gb96 zSFwkzYZ_>EIF3P|GJbp)%aSYjm+S{Lj~ z+tzkz!|lQ>yPQxu*wA@QiiN%IhCM=rvAarZy`GEDwdD?8Jt@SL54U zwEMv7UtB{q+4THAl5O4mS3+Y?wG{!nIO3!)+&4zI-x7w7=Ay|1UfQ~Onl6QswC!Lq zlJ`hA%7%6vQ^j!FuBcie5}W@c^01>inPda4q?bk4;wmdDUp$Y(gpNKG$u17uzd{Jj z=N`qCWA|T1(`?fRsF%$>Erf-%yAe-+g05i(3MJX}A*@sH!*8?TP0GzY_Zixbjemn| z?-%H?takbiEN&hB5>?!qULEn!qbKUvr5t(+nA*zD5FB9bL@8yL^&XMg*LLkAEVu>a zjQzSMd-TM)N-|iBVXH|x@M1|1K0k}QNp|Wt$3)gZ--;(UVtUwD`_UxxoyEOOdtW#* zpI}NiVcHd?pNF4O9#B~NE!@E}-@=d4@t(6h@P%>^iCnc`x(=DH<`fTm_g*~7e%T8< zKB5pes)HM88%u_i2pyVksR^J$iNRkM*p0jL_I>FSnZM=S%W4B?%FiVheafEg#ar1&Yti~rz@l$6 zH%5544OKR-88LrAX1NyM>11y>QOK-S)3g)NtCNZyBZc#q4D{OLBF#Lw9?ZkFAEJt;l#W~GNco(xZ(`^W2Gi5y zWlY<7PYx^_&j{SQ8yD#=Hne0F%dJ9Z`PI`%a(33Hx3PQ9lzdj!*s!arq^02xiCx=v zW`@(*?eBxnZv6oDmn>%WFsb8myWS+l3EPUlK?n?q6B^yQlLtIlvM!`tp+A{BSw6^j zvSM@Ul_`J*6(%h37K%{s#vpXxi`m?%{g^FYL_t2WNA|Q`<1#nP(-ST?i9|P;M5f!; z8b$SV_QHKQU)KHXhTXVuzezVy6XDEc)>#y|CsHOBWf;`?)Qr!^5xJM)Cpy7Pp z_ag*yEPMvm&mBfDiR~PCTV4)v+j2Fe{h;+$RAZT7hr1L}jC{j2o=y3V`-H+r?pFRL z9@thFDR!AGaL|%0-XoK)Wjk)A_H)xoq2A1gl+}JB+e`ZtDuQ>tq8u-KAT3WeJH1T~ zUwkIzy`M}7>cT5YV%wGyRy=L~HvN=+KBb8LCjWlpp;r{i^R`8_%(0Bu8!kUqlCX0R zps(}A3yRd+?N2C0E~$25l3954Hd1x1nEPdx1T*U?Ir*-r?6 qeUSXt=Bq;)HS&iTeCSE|3bB>V42!Ao%=cy9?VTc}QIZjylKd~QXx~Br diff --git a/config/linux/ipu8/libcamhal_configs.json b/config/linux/ipu8/libcamhal_configs.json index 76b58642..ab53b93f 100644 --- a/config/linux/ipu8/libcamhal_configs.json +++ b/config/linux/ipu8/libcamhal_configs.json @@ -1,5 +1,5 @@ // -// Copyright (C) 2025-2026 Intel Corporation +// Copyright (C) 2025 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,17 +23,7 @@ "availableSensors": [ "ov13b10-wf-0", "ov13b10-uf-2", - "lt6911gxd-1-0", - "lt6911gxd-2-2", - "isx031-1-0", - "isx031-2-0", - "isx031-3-0", - "isx031-4-0", - "isx031-5-2", - "isx031-6-2", - "isx031-7-2", - "isx031-8-2" - + "ov08x40-uf-0" ], "videoStreamNum" : 2 } diff --git a/config/linux/ipu8/sensors/ov13b10-uf.json b/config/linux/ipu8/sensors/ov13b10-uf.json index 6046b760..9c8ce687 100644 --- a/config/linux/ipu8/sensors/ov13b10-uf.json +++ b/config/linux/ipu8/sensors/ov13b10-uf.json @@ -43,12 +43,12 @@ }, { "srcName": "Intel IPU7 CSI2 $CSI_PORT", "srcPad": 1, - "sinkName": "Intel IPU7 ISYS Capture 16", "sinkPad": 0, "enable": true + "sinkName": "Intel IPU7 ISYS Capture $CAP_N", "sinkPad": 0, "enable": true } ], "videonode": [ { - "name": "Intel IPU7 ISYS Capture 16", "videoNodeType": "VIDEO_GENERIC" + "name": "Intel IPU7 ISYS Capture $CAP_N", "videoNodeType": "VIDEO_GENERIC" }, { "name": "Intel IPU7 CSI2 $CSI_PORT", "videoNodeType": "VIDEO_ISYS_RECEIVER" diff --git a/config/linux/ipu8/sensors/ov13b10-wf.json b/config/linux/ipu8/sensors/ov13b10-wf.json index ff14cd65..ca1bf397 100644 --- a/config/linux/ipu8/sensors/ov13b10-wf.json +++ b/config/linux/ipu8/sensors/ov13b10-wf.json @@ -43,12 +43,12 @@ }, { "srcName": "Intel IPU7 CSI2 $CSI_PORT", "srcPad": 1, - "sinkName": "Intel IPU7 ISYS Capture 0", "sinkPad": 0, "enable": true + "sinkName": "Intel IPU7 ISYS Capture $CAP_N", "sinkPad": 0, "enable": true } ], "videonode": [ { - "name": "Intel IPU7 ISYS Capture 0", "videoNodeType": "VIDEO_GENERIC" + "name": "Intel IPU7 ISYS Capture $CAP_N", "videoNodeType": "VIDEO_GENERIC" }, { "name": "Intel IPU7 CSI2 $CSI_PORT", "videoNodeType": "VIDEO_ISYS_RECEIVER" diff --git a/include/utils/ScopedAtrace.h b/include/utils/ScopedAtrace.h index bdc4a6ea..a846626f 100644 --- a/include/utils/ScopedAtrace.h +++ b/include/utils/ScopedAtrace.h @@ -39,6 +39,10 @@ class ScopedAtrace { long value = -1, const char* note2 = NULL, int value2 = -1, const char* note3 = NULL, int value3 = -1); ~ScopedAtrace(); + + ScopedAtrace(const ScopedAtrace&) = delete; + ScopedAtrace& operator=(const ScopedAtrace&) = delete; + static void setTraceLevel(uint32_t); private: diff --git a/modules/algowrapper/IntelCca.h b/modules/algowrapper/IntelCca.h index 7f632f94..069b71e3 100644 --- a/modules/algowrapper/IntelCca.h +++ b/modules/algowrapper/IntelCca.h @@ -33,6 +33,9 @@ class IntelCca { IntelCca(int cameraId, TuningMode mode); virtual ~IntelCca(); + IntelCca(const IntelCca&) = delete; + IntelCca& operator=(const IntelCca&) = delete; + static IntelCca* getInstance(int cameraId, TuningMode mode); static void releaseInstance(int cameraId, TuningMode mode); diff --git a/modules/ipu_desc/ipu75xa/FragmentsConfigurator.cpp b/modules/ipu_desc/ipu75xa/FragmentsConfigurator.cpp index a42549ef..9ca2cb84 100644 --- a/modules/ipu_desc/ipu75xa/FragmentsConfigurator.cpp +++ b/modules/ipu_desc/ipu75xa/FragmentsConfigurator.cpp @@ -205,13 +205,6 @@ StaticGraphStatus Gen2FragmentsConfigurator::configFragmentsDownscaler(StaticGra for (int32_t stripe = leftNonVanishedStripe; stripe <= rightNonVanishedStripe; stripe++) { - if (scaleFactor == 1.0) - { - kernelFragments[stripe].fragmentOutputWidth = kernelFragments[stripe].fragmentInputWidth; - _outputStartX[runKernel->kernel_uuid][stripe] = kernelFragments[stripe].fragmentStartX; - continue; - } - int rightCrop = stripe == static_cast(_numberOfFragments - 1) ? resInfo->input_crop.right : 0; double value = (static_cast(kernelFragments[stripe].fragmentInputWidth - rightCrop) * scaleFactor) / 4; diff --git a/modules/ipu_desc/ipu75xa/GraphResolutionConfigurator.cpp b/modules/ipu_desc/ipu75xa/GraphResolutionConfigurator.cpp index 9abc7417..28ee47e3 100644 --- a/modules/ipu_desc/ipu75xa/GraphResolutionConfigurator.cpp +++ b/modules/ipu_desc/ipu75xa/GraphResolutionConfigurator.cpp @@ -720,7 +720,7 @@ StaticGraphStatus GraphResolutionConfigurator::updateRunKernelUpScaler(StaticGra upscalerActualInputWidth = GRA_ROUND_DOWN(upscalerActualInputWidth, stepW); upscalerActualInputHeight = (upscalerActualInputWidth / stepW) * stepH; - if ((static_cast(upscalerActualOutputWidth) / upscalerActualInputWidth) > max_upscaling) + if ((upscalerActualOutputWidth / upscalerActualInputWidth) > max_upscaling) { // Perform the max possible up scaling, downscaler will adjust itself upscalerActualInputWidth = upscalerActualOutputWidth / max_upscaling; diff --git a/modules/ipu_desc/ipu7x/FragmentsConfigurator.cpp b/modules/ipu_desc/ipu7x/FragmentsConfigurator.cpp index a42549ef..9ca2cb84 100644 --- a/modules/ipu_desc/ipu7x/FragmentsConfigurator.cpp +++ b/modules/ipu_desc/ipu7x/FragmentsConfigurator.cpp @@ -205,13 +205,6 @@ StaticGraphStatus Gen2FragmentsConfigurator::configFragmentsDownscaler(StaticGra for (int32_t stripe = leftNonVanishedStripe; stripe <= rightNonVanishedStripe; stripe++) { - if (scaleFactor == 1.0) - { - kernelFragments[stripe].fragmentOutputWidth = kernelFragments[stripe].fragmentInputWidth; - _outputStartX[runKernel->kernel_uuid][stripe] = kernelFragments[stripe].fragmentStartX; - continue; - } - int rightCrop = stripe == static_cast(_numberOfFragments - 1) ? resInfo->input_crop.right : 0; double value = (static_cast(kernelFragments[stripe].fragmentInputWidth - rightCrop) * scaleFactor) / 4; diff --git a/modules/ipu_desc/ipu7x/GraphResolutionConfigurator.cpp b/modules/ipu_desc/ipu7x/GraphResolutionConfigurator.cpp index 9abc7417..28ee47e3 100644 --- a/modules/ipu_desc/ipu7x/GraphResolutionConfigurator.cpp +++ b/modules/ipu_desc/ipu7x/GraphResolutionConfigurator.cpp @@ -720,7 +720,7 @@ StaticGraphStatus GraphResolutionConfigurator::updateRunKernelUpScaler(StaticGra upscalerActualInputWidth = GRA_ROUND_DOWN(upscalerActualInputWidth, stepW); upscalerActualInputHeight = (upscalerActualInputWidth / stepW) * stepH; - if ((static_cast(upscalerActualOutputWidth) / upscalerActualInputWidth) > max_upscaling) + if ((upscalerActualOutputWidth / upscalerActualInputWidth) > max_upscaling) { // Perform the max possible up scaling, downscaler will adjust itself upscalerActualInputWidth = upscalerActualOutputWidth / max_upscaling; diff --git a/modules/ipu_desc/ipu8/FragmentsConfigurator.cpp b/modules/ipu_desc/ipu8/FragmentsConfigurator.cpp index a42549ef..9ca2cb84 100644 --- a/modules/ipu_desc/ipu8/FragmentsConfigurator.cpp +++ b/modules/ipu_desc/ipu8/FragmentsConfigurator.cpp @@ -205,13 +205,6 @@ StaticGraphStatus Gen2FragmentsConfigurator::configFragmentsDownscaler(StaticGra for (int32_t stripe = leftNonVanishedStripe; stripe <= rightNonVanishedStripe; stripe++) { - if (scaleFactor == 1.0) - { - kernelFragments[stripe].fragmentOutputWidth = kernelFragments[stripe].fragmentInputWidth; - _outputStartX[runKernel->kernel_uuid][stripe] = kernelFragments[stripe].fragmentStartX; - continue; - } - int rightCrop = stripe == static_cast(_numberOfFragments - 1) ? resInfo->input_crop.right : 0; double value = (static_cast(kernelFragments[stripe].fragmentInputWidth - rightCrop) * scaleFactor) / 4; diff --git a/modules/ipu_desc/ipu8/GraphResolutionConfigurator.cpp b/modules/ipu_desc/ipu8/GraphResolutionConfigurator.cpp index 9abc7417..28ee47e3 100644 --- a/modules/ipu_desc/ipu8/GraphResolutionConfigurator.cpp +++ b/modules/ipu_desc/ipu8/GraphResolutionConfigurator.cpp @@ -720,7 +720,7 @@ StaticGraphStatus GraphResolutionConfigurator::updateRunKernelUpScaler(StaticGra upscalerActualInputWidth = GRA_ROUND_DOWN(upscalerActualInputWidth, stepW); upscalerActualInputHeight = (upscalerActualInputWidth / stepW) * stepH; - if ((static_cast(upscalerActualOutputWidth) / upscalerActualInputWidth) > max_upscaling) + if ((upscalerActualOutputWidth / upscalerActualInputWidth) > max_upscaling) { // Perform the max possible up scaling, downscaler will adjust itself upscalerActualInputWidth = upscalerActualOutputWidth / max_upscaling; diff --git a/modules/v4l2/v4l2_device.h b/modules/v4l2/v4l2_device.h index 0c9ea94b..2050df98 100644 --- a/modules/v4l2/v4l2_device.h +++ b/modules/v4l2/v4l2_device.h @@ -40,6 +40,7 @@ class V4L2Buffer { public: V4L2Buffer(); explicit V4L2Buffer(const V4L2Buffer& buf); + ~V4L2Buffer() = default; uint32_t Index() const { return v4l2_buf_.index; } void SetIndex(uint32_t index) { v4l2_buf_.index = index; } uint32_t Type() const { return v4l2_buf_.type; } @@ -141,6 +142,10 @@ class V4L2Device { virtual ~V4L2Device(); + // Explicitly delete copy and move operations (manages file descriptor) + V4L2Device(const V4L2Device&) = delete; + V4L2Device& operator=(const V4L2Device&) = delete; + // This method opens the V4L2 device. // // Args: diff --git a/src/3a/AiqCore.cpp b/src/3a/AiqCore.cpp index b4784b49..99681501 100644 --- a/src/3a/AiqCore.cpp +++ b/src/3a/AiqCore.cpp @@ -547,7 +547,7 @@ int AiqCore::reFormatLensShadingMap(const LSCGrid& inputLscGrid, float* dstLscGr // Metadata spec request order [R, Geven, Godd, B] // the lensShading from ISP is 4 width * height block, // for ia_aiq_bayer_order_grbg, the four block is G, R, B, G - const size_t size = inputLscGrid.height * inputLscGrid.width; + const size_t size = static_cast(inputLscGrid.height) * static_cast(inputLscGrid.width); for (size_t i = 0U; i < size; i++) { *dstLscGridRGGB = inputLscGrid.gridR[i]; dstLscGridRGGB++; diff --git a/src/3a/AiqEngine.cpp b/src/3a/AiqEngine.cpp index a2e348fe..296ae115 100644 --- a/src/3a/AiqEngine.cpp +++ b/src/3a/AiqEngine.cpp @@ -295,9 +295,6 @@ AiqEngine::AiqState AiqEngine::prepareInputParam(AiqStatistics* aiqStats, AiqRes // Update sensor info for the first-run of AIQ if (mFirstAiqRunning) { - // CRL_MODULE_S - mSensorManager->setFrameRate(aiqParams.fps); - // CRL_MODULE_E // set sensor info if needed ia_aiq_exposure_sensor_descriptor sensorDescriptor = {}; ia_aiq_frame_params frameParams = {}; diff --git a/src/3a/AiqResult.cpp b/src/3a/AiqResult.cpp index f0cf9335..b9f771b0 100644 --- a/src/3a/AiqResult.cpp +++ b/src/3a/AiqResult.cpp @@ -51,6 +51,39 @@ AiqResult::~AiqResult() { deinit(); } +AiqResult::AiqResult(const AiqResult& other) : + mCameraId(other.mCameraId), + mTimestamp(other.mTimestamp), + mSequence(other.mSequence), + mFrameId(other.mFrameId), + mTuningMode(other.mTuningMode), + mAfDistanceDiopters(other.mAfDistanceDiopters), + mSkip(other.mSkip), + mFocusRange(other.mFocusRange), + mLensPosition(other.mLensPosition), + mSceneMode(other.mSceneMode), + mAeResults(other.mAeResults), + mAwbResults(other.mAwbResults), + mAfResults(other.mAfResults), + mGbceResults(other.mGbceResults), + mPaResults(other.mPaResults), + mOutStats(other.mOutStats), + mFrameDuration(other.mFrameDuration), + mRollingShutter(other.mRollingShutter) { + CLEAR(mCustomControls); + CLEAR(mCustomControlsParams); + + mOutStats.rgbs_grid[0].blocks_ptr = mOutStats.rgbs_blocks[0]; + + mCustomControls.count = other.mCustomControls.count; + mCustomControls.parameters = mCustomControlsParams; + for (int i = 0; i < mCustomControls.count; i++) { + mCustomControlsParams[i] = other.mCustomControlsParams[i]; + } + MEMCPY_S(mLensShadingMap, sizeof(mLensShadingMap), + other.mLensShadingMap, sizeof(other.mLensShadingMap)); +} + int AiqResult::init() { CLEAR(mAeResults); CLEAR(mAfResults); diff --git a/src/3a/AiqResult.h b/src/3a/AiqResult.h index 87c19cf4..dc0bb370 100644 --- a/src/3a/AiqResult.h +++ b/src/3a/AiqResult.h @@ -34,6 +34,7 @@ class AiqResult { public: AiqResult(int cameraId); ~AiqResult(); + AiqResult(const AiqResult& other); int init(); int deinit() const; diff --git a/src/3a/AiqResultStorage.h b/src/3a/AiqResultStorage.h index 35f0d37a..0ef16fa9 100644 --- a/src/3a/AiqResultStorage.h +++ b/src/3a/AiqResultStorage.h @@ -124,6 +124,8 @@ class AiqResultStorage { AiqResultStorage(int cameraId); ~AiqResultStorage(); + AiqResultStorage(const AiqResultStorage&) = delete; + AiqResultStorage& operator=(const AiqResultStorage&) = delete; private: int mCameraId; diff --git a/src/3a/AiqUtils.cpp b/src/3a/AiqUtils.cpp index 4f9ec24b..cc7d8bea 100644 --- a/src/3a/AiqUtils.cpp +++ b/src/3a/AiqUtils.cpp @@ -370,11 +370,11 @@ void AiqUtils::applyTonemapSRGB(cca::cca_gbce_params* results) { CheckAndLogError(lutSize < MIN_TONEMAP_POINTS, VOID_VALUE, "Bad gamma lut size (%d) in gbce results", lutSize); for (int i = 0; i < lutSize; i++) { - if (i / (lutSize - 1) < 0.0031308) { - results->g_gamma_lut[i] = 12.92 * (i / (lutSize - 1)); + if (i / (static_cast(lutSize) - 1.0F) < 0.0031308) { + results->g_gamma_lut[i] = 12.92 * (i / (static_cast(lutSize) - 1.0F)); } else { results->g_gamma_lut[i] = - 1.055 * pow(i / static_cast(lutSize - 1), 1 / 2.4) - 0.055; + 1.055 * pow(i / (static_cast(lutSize) - 1.0F), 1 / 2.4) - 0.055; } } @@ -498,9 +498,9 @@ void AiqUtils::applyAwbGainForTonemapCurve(const camera_tonemap_curves_t& curves */ float AiqUtils::calculateHyperfocalDistance(const cca::cca_cmc &cmc) { const float DEFAULT_HYPERFOCAL_DISTANCE = 5000.0F; - // Pixel size is stored in CMC in hundreds of micrometers - const float pixelSizeMicro = cmc.optics.sensor_pix_size_h / 100; + const float pixelSizeMicro = static_cast(cmc.optics.sensor_pix_size_h) / 100; + // focal length is stored in CMC in hundreds of millimeters const float focalLengthMillis = static_cast(cmc.optics.effect_focal_length) / 100; diff --git a/src/3a/MakerNote.cpp b/src/3a/MakerNote.cpp index 9e7a9501..5c8a0e8f 100644 --- a/src/3a/MakerNote.cpp +++ b/src/3a/MakerNote.cpp @@ -127,8 +127,8 @@ int MakerNote::saveMakernoteData(int cameraId, camera_makernote_mode_t makernote } void MakerNote::updateTimestamp(int64_t sequence, uint64_t timestamp) { - LOG2("@%s, mMknState:%d", __func__, mMknState); AutoMutex lock(mMknLock); + LOG2("@%s, mMknState:%d", __func__, mMknState); CheckAndLogError(mMknState != INIT, VOID_VALUE, "@%s, mkn isn't initialized", __func__); for (auto rit = mMakernoteDataList.rbegin(); rit != mMakernoteDataList.rend(); ++rit) { diff --git a/src/3a/SensorManager.cpp b/src/3a/SensorManager.cpp index 7ab99b79..90a27eb7 100644 --- a/src/3a/SensorManager.cpp +++ b/src/3a/SensorManager.cpp @@ -120,7 +120,7 @@ void SensorManager::handleSensorModeSwitch(int64_t sequence) { if (mWdrModeSetting.sequence <= sequence) { const int wdrMode = convertTuningModeToWdrMode(mWdrModeSetting.tuningMode); LOG2("@%s, tunning mode %d, set wdrMode %d sequence %ld", sequence, __func__, - wdrMode, mWdrModeSetting.sequence); + mWdrModeSetting.tuningMode, wdrMode, mWdrModeSetting.sequence); if (mSensorHwCtrl->setWdrMode(wdrMode) == OK) { mModeSwitched = false; @@ -253,12 +253,6 @@ uint32_t SensorManager::updateSensorExposure(SensorExpGroup sensorExposures, int effectSeq, applyingSeq); return static_cast(effectSeq); } -// CRL_MODULE_S -int SensorManager::setFrameRate(float fps) -{ - return mSensorHwCtrl->setFrameRate(fps); -} -// CRL_MODULE_E int SensorManager::getSensorInfo(ia_aiq_frame_params &frameParams, ia_aiq_exposure_sensor_descriptor &sensorDescriptor) { @@ -276,7 +270,7 @@ int SensorManager::getSensorInfo(ia_aiq_frame_params &frameParams, CheckAndLogError(res.empty(), BAD_VALUE, "Supported ISYS resolutions are not configured."); // In none-ISYS cases, only take 30 fps into account. const int fps = 30; - float freq = res[0].width * res[0].height * fps / 1000000; + float freq = (res[0].width * res[0].height * fps) / 1000000.0F; sensorDescriptor = {freq, static_cast(res[0].width), static_cast(res[0].height), 24, 0, static_cast(res[0].width), 6, 0, diff --git a/src/3a/SensorManager.h b/src/3a/SensorManager.h index e6549b60..6afeee40 100644 --- a/src/3a/SensorManager.h +++ b/src/3a/SensorManager.h @@ -68,9 +68,6 @@ class SensorManager { int setAWB(float r_per_g, float b_per_g); // HDR_FEATURE_E - // CRL_MODULE_S - int setFrameRate(float fps); - // CRL_MODULE_E int getCurrentExposureAppliedDelay(); uint64_t getSofTimestamp(int64_t sequence); private: diff --git a/src/3a/intel3a/Intel3AParameter.cpp b/src/3a/intel3a/Intel3AParameter.cpp index 9aba5e4e..d3163e4d 100644 --- a/src/3a/intel3a/Intel3AParameter.cpp +++ b/src/3a/intel3a/Intel3AParameter.cpp @@ -167,7 +167,7 @@ int Intel3AParameter::setSensorInfo(ia_aiq_exposure_sensor_descriptor descriptor return OK; } -int Intel3AParameter::updateParameter(aiq_parameter_t param) { +int Intel3AParameter::updateParameter(const aiq_parameter_t& param) { updateAeParameter(param); updateAwbParameter(param); updateAfParameter(param); diff --git a/src/3a/intel3a/Intel3AParameter.h b/src/3a/intel3a/Intel3AParameter.h index 6f8bb05d..f7b7671c 100644 --- a/src/3a/intel3a/Intel3AParameter.h +++ b/src/3a/intel3a/Intel3AParameter.h @@ -34,7 +34,7 @@ class Intel3AParameter { void init(); int getCMCInfo(TuningMode tuningMode); int setSensorInfo(ia_aiq_exposure_sensor_descriptor descriptor); - int updateParameter(aiq_parameter_t param); + int updateParameter(const aiq_parameter_t& param); void updateAeResult(cca::cca_ae_results* aeResult) const ; void updateAwbResult(cca::cca_awb_results* awbResult); void updatePaResult(cca::cca_pa_params* paResult); diff --git a/src/core/CameraBuffer.h b/src/core/CameraBuffer.h index 8ecbf509..6eeea843 100644 --- a/src/core/CameraBuffer.h +++ b/src/core/CameraBuffer.h @@ -168,6 +168,10 @@ class CameraBuffer { DeviceRender(); explicit DeviceRender(const char* path_file); ~DeviceRender(); + + DeviceRender(const DeviceRender&) = delete; + DeviceRender& operator=(const DeviceRender&) = delete; + void* mapDmaBufferAddr(int fd, unsigned int bufferSize); private: @@ -185,6 +189,8 @@ class CameraBufferMapper { public: explicit CameraBufferMapper(std::shared_ptr buffer); ~CameraBufferMapper(); + CameraBufferMapper(const CameraBufferMapper&) = delete; + CameraBufferMapper& operator=(const CameraBufferMapper&) = delete; void* addr(); int size(); diff --git a/src/core/CameraContext.h b/src/core/CameraContext.h index d7d88f48..bffa74ac 100644 --- a/src/core/CameraContext.h +++ b/src/core/CameraContext.h @@ -24,9 +24,6 @@ #include "AiqSetting.h" #include "CameraTypes.h" #include "ParamDataType.h" -// JPEG_ENCODE_S -#include "EXIFMetaData.h" -// JPEG_ENCODE_E namespace icamera { @@ -51,30 +48,6 @@ struct IspParameters { } }; -// JPEG_ENCODE_S -struct JpegParameters { - double latitude; - double longitude; - double altitude; - char gpsProcessingMethod[MAX_NUM_GPS_PROCESSING_METHOD + 1]; - uint8_t gpsProcessingMethodSize; - int64_t gpsTimestamp; - int32_t rotation; - uint8_t jpegQuality; - uint8_t thumbQuality; - camera_resolution_t thumbSize; - float focalLength; - float aperture; - - JpegParameters() { - memset(this, 0, sizeof(*this)); - - jpegQuality = DEFAULT_JPEG_QUALITY; - thumbQuality = DEFAULT_JPEG_QUALITY; - } -}; -// JPEG_ENCODE_E - class DataContext { public: int64_t mFrameNumber; @@ -90,11 +63,9 @@ class DataContext { struct aiq_parameter_t mAiqParams; struct IspParameters mIspParams; -// JPEG_ENCODE_S - struct JpegParameters mJpegParams; -// JPEG_ENCODE_E DataContext(int cameraId); + DataContext(const DataContext&) = default; ~DataContext() {} void reset(); @@ -106,9 +77,6 @@ class DataContext { zoomRegion = other.zoomRegion; mAiqParams = other.mAiqParams; mIspParams = other.mIspParams; -// JPEG_ENCODE_S - mJpegParams = other.mJpegParams; -// JPEG_ENCODE_E return *this; } @@ -122,6 +90,9 @@ class CameraContext { explicit CameraContext(int cameraId); ~CameraContext(); + CameraContext(const CameraContext&) = delete; + CameraContext& operator=(const CameraContext&) = delete; + static CameraContext* getInstance(int cameraId); static void releaseInstance(int cameraId); diff --git a/src/core/CameraDevice.cpp b/src/core/CameraDevice.cpp index 96bac0e0..17d54af7 100644 --- a/src/core/CameraDevice.cpp +++ b/src/core/CameraDevice.cpp @@ -465,11 +465,6 @@ int CameraDevice::configure(stream_config_t* streamList) { CheckAndLogError(ret != OK, ret, "@%s failed to configure CSI meta device", __func__); // CSI_META_E - // CRL_MODULE_S - ret = mSensorCtrl->configure(); - CheckAndLogError(ret != OK, ret, "@%s failed to configure sensor HW", __func__); - // CRL_MODULE_E - ret = mSofSource->configure(); CheckAndLogError(ret != OK, ret, "@%s failed to configure SOF source device", __func__); @@ -652,7 +647,7 @@ int CameraDevice::createStreams(const stream_config_t* streamList, int configure for (int streamId = 0; streamId < streamCounts; streamId++) { stream_t& streamConf = streamList->streams[streamId]; LOG1("@%s, stream_number:%d, stream configure: format:%s (%dx%d)", __func__, streamCounts, - CameraUtils::pixelCode2String(streamConf.format), streamConf.width, streamConf.height); + CameraUtils::pixelCode2String(streamConf.format), streamConf.width, streamConf.height); CameraStream* stream = nullptr; // Create a normal CameraStream @@ -889,8 +884,9 @@ int CameraDevice::dqbuf(int streamId, camera_buffer_t** ubuffer) { PERF_CAMERA_ATRACE(); LOG2("@%s, stream id:%d", mCameraId, __func__, streamId); - int ret; + int ret = OK; do { + AutoMutex m(mDeviceLock); ret = mRequestThread->waitFrame(streamId, ubuffer); } while (ret == TIMED_OUT); diff --git a/src/core/CaptureUnit.cpp b/src/core/CaptureUnit.cpp index 16407426..375e930b 100644 --- a/src/core/CaptureUnit.cpp +++ b/src/core/CaptureUnit.cpp @@ -212,6 +212,7 @@ void CaptureUnit::streamOff() { int CaptureUnit::stop() { PERF_CAMERA_ATRACE(); LOG1("%s", mCameraId, __func__); + AutoMutex l(mLock); CheckWarning(mState != CAPTURE_START, OK, "@%s: device not started", __func__); mExitPending = true; @@ -225,7 +226,6 @@ int CaptureUnit::stop() { streamOff(); mPollThread->wait(); - AutoMutex l(mLock); mState = CAPTURE_STOP; for (auto device : mDevices) { diff --git a/src/core/CsiMetaDevice.cpp b/src/core/CsiMetaDevice.cpp index e01ec836..694eb0cd 100644 --- a/src/core/CsiMetaDevice.cpp +++ b/src/core/CsiMetaDevice.cpp @@ -318,7 +318,7 @@ void CsiMetaDevice::handleCsiMetaBuffer() { mCsiMetaBufferDQIndex = (mCsiMetaBufferDQIndex + 1) % mCsiMetaCameraBuffers.size(); if (CameraDump::isDumpTypeEnable(DUMP_EMBEDDED_METADATA)) { - BinParam_t bParam; + BinParam_t bParam{}; bParam.bType = BIN_TYPE_SENSOR_METADATA; bParam.mType = M_ISYS; bParam.sequence = camBuffer->getSequence(); @@ -345,9 +345,7 @@ void CsiMetaDevice::handleCsiMetaBuffer() { } int CsiMetaDevice::setFormat() { - struct v4l2_format v4l2fmt; - CLEAR(v4l2fmt); - + struct v4l2_format v4l2fmt = {}; v4l2fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; v4l2fmt.fmt.pix_mp.width = mEmbeddedMetaData.width; v4l2fmt.fmt.pix_mp.height = mEmbeddedMetaData.height; diff --git a/src/core/CsiMetaDevice.h b/src/core/CsiMetaDevice.h index 551a1711..cb420ec4 100644 --- a/src/core/CsiMetaDevice.h +++ b/src/core/CsiMetaDevice.h @@ -62,8 +62,10 @@ class CsiMetaDevice : public EventSource { int configure(); int start(); int stop(); - bool isEnabled() { return mIsCsiMetaEnabled; } - + bool isEnabled() { + AutoMutex l(mCsiMetaDeviceLock); + return mIsCsiMetaEnabled; + } void deinitLocked(); int resetState(); int initDev(); diff --git a/src/core/DeviceBase.cpp b/src/core/DeviceBase.cpp index dfc0b22a..d075290c 100644 --- a/src/core/DeviceBase.cpp +++ b/src/core/DeviceBase.cpp @@ -301,7 +301,7 @@ int MainDevice::createBufferPool(const stream_t& config) { LOG1("%s, fmt:%s(%dx%d) field:%d", DeviceBase::mCameraId, __func__, CameraUtils::pixelCode2String(config.format), config.width, config.height, config.field); - struct v4l2_format v4l2fmt; + struct v4l2_format v4l2fmt = {}; v4l2fmt.fmt.pix_mp.field = config.field; v4l2fmt.fmt.pix.width = config.width; diff --git a/src/core/FileSource.cpp b/src/core/FileSource.cpp index 6440ddee..3a61b016 100644 --- a/src/core/FileSource.cpp +++ b/src/core/FileSource.cpp @@ -264,6 +264,7 @@ bool FileSource::produce() { notifyFrame(qBuffer); + AutoMutex l(mLock); return !mExitPending; } diff --git a/src/core/IProcessingUnit.h b/src/core/IProcessingUnit.h index cf312da7..df75db6b 100644 --- a/src/core/IProcessingUnit.h +++ b/src/core/IProcessingUnit.h @@ -27,6 +27,8 @@ namespace icamera { class IProcessingUnit : public BufferQueue { public: IProcessingUnit() : mProcessThread(nullptr), mThreadRunning(false) {} + virtual ~IProcessingUnit() = default; + virtual int configure(const std::map& inputInfo, const std::map& outputInfo, const ConfigMode configModes) { diff --git a/src/core/InputEventMonitor.cpp b/src/core/InputEventMonitor.cpp index 656d3adb..75edefa1 100644 --- a/src/core/InputEventMonitor.cpp +++ b/src/core/InputEventMonitor.cpp @@ -83,8 +83,7 @@ int InputEventMonitor::configure(int eventType, int eventCode) { mFd = status; mEventType = eventType; mEventCode = eventCode; - const uint32_t modes_count = sizeof(EVENTIOCTLMODES) / sizeof(struct EventIoctlMode); - for (uint32_t i = 0; i < modes_count; ++i) { + for (uint32_t i = 0; i < sizeof(EVENTIOCTLMODES) / sizeof(EVENTIOCTLMODES[0]); ++i) { if (mEventType == EVENTIOCTLMODES[i].type) { mEventIoctlModesIndex = i; break; @@ -115,7 +114,7 @@ int InputEventMonitor::getValue() { int InputEventMonitor::readRawValue() { // Only used inside locked context so no need to get lock again if (mFd < 0 || mEventType < 0 || mEventCode < 0) return -1; - + int status = -1; uint32_t bits = EVENTIOCTLMODES[mEventIoctlModesIndex].max; uint32_t req = EVENTIOCTLMODES[mEventIoctlModesIndex].rq; @@ -124,7 +123,7 @@ int InputEventMonitor::readRawValue() { memset(codeBits, 0, sizeof(codeBits)); status = ioctl(mFd, req, codeBits); if (status >= 0) { - mValue = (codeBits[mEventCode / U32_BITS] & (1UL << (mEventCode % U32_BITS)) != 0U) ? 1 : 0; + mValue = ((codeBits[mEventCode / U32_BITS] & (1UL << (mEventCode % U32_BITS))) != 0U) ? 1 : 0; } return status; diff --git a/src/core/IpuPacAdaptor.cpp b/src/core/IpuPacAdaptor.cpp index a8aad3f5..2541654a 100644 --- a/src/core/IpuPacAdaptor.cpp +++ b/src/core/IpuPacAdaptor.cpp @@ -232,6 +232,13 @@ status_t IpuPacAdaptor::storeTerminalResult(int64_t sequence, int32_t streamId) LOG2("%s, get the aic buffer for streamId: %d, contextId: %u, terminal num: %d", __func__, streamId, data.first.second, index); + /* False Positive: Lock held by caller runAIC() which owns mPacAdaptorLock */ + /* storeTerminalResult() is only called from runAIC() */ + /* runAIC() acquires mPacAdaptorLock before calling this function */ + /* mIntelCca access here is protected by caller's lock */ + /* Adding lock here would cause deadlock */ + /* Waive by deviation: False Positive */ + /* coverity[missing_lock : FALSE] */ const ia_err iaErr = mIntelCca->getAicBuf(ccaTermConfig, streamId); CheckAndLogError(iaErr != ia_err_none, UNKNOWN_ERROR, "%s, Failed to getAicBuf. streamId: %d, contextId: %d", @@ -356,18 +363,32 @@ status_t IpuPacAdaptor::runAIC(const IspSettings* ispSettings, if (STILL_STREAM_ID == streamId) { inputParams->force_lsc_update = true; } + /* False Positive: Pipeline execution guarantees temporal separation */ + /* ProcessingUnit writes manualSettings under mIspSettingsLock protection */ + /* After write completes, settings become read-only for this frame */ + /* Pipeline advances to PAC stage where runAIC() executes */ + /* This function only reads already-finalized immutable settings */ + /* No concurrent modifications possible, writer finished before reader starts */ + /* Lock is owned by ProcessingUnit and intentionally not accessible here */ + /* Waive by deviation: False Positive */ + /* coverity[missing_lock : FALSE] */ if (ispSettings != nullptr) { inputParams->nr_setting = ispSettings->nrSetting; inputParams->ee_setting = ispSettings->eeSetting; + //coverity[missing_lock : FALSE] LOG2("%s: ISP NR setting, level: %d, strength: %d", __func__, static_cast(ispSettings->nrSetting.feature_level), static_cast(ispSettings->nrSetting.strength)); inputParams->effects = ispSettings->effects; + //coverity[missing_lock : FALSE] inputParams->manual_brightness = ispSettings->manualSettings.manualBrightness; + //coverity[missing_lock : FALSE] inputParams->manual_contrast = ispSettings->manualSettings.manualContrast; + //coverity[missing_lock : FALSE] inputParams->manual_hue = ispSettings->manualSettings.manualHue; + //coverity[missing_lock : FALSE] inputParams->manual_saturation = ispSettings->manualSettings.manualSaturation; LOG2("%s: ISP EE setting, level: %d, strength: %d", __func__, ispSettings->eeSetting.feature_level, ispSettings->eeSetting.strength); diff --git a/src/core/PSysDevice.h b/src/core/PSysDevice.h index 6e644540..57908e42 100644 --- a/src/core/PSysDevice.h +++ b/src/core/PSysDevice.h @@ -94,6 +94,9 @@ class PSysDevice { explicit PSysDevice(int cameraId); virtual ~PSysDevice(); + PSysDevice(const PSysDevice&) = delete; + PSysDevice& operator=(const PSysDevice&) = delete; + virtual int init(); virtual void deinit(); virtual void registerPSysDeviceCallback(uint8_t contextId, IPSysDeviceCallback* callback); diff --git a/src/core/ProcessingUnit.cpp b/src/core/ProcessingUnit.cpp index cab66bc4..8e805ea4 100644 --- a/src/core/ProcessingUnit.cpp +++ b/src/core/ProcessingUnit.cpp @@ -178,8 +178,11 @@ void ProcessingUnit::stop() { mProcessThread->wait(); - mRawBufferMap.clear(); - // Thread is not running. It is safe to clear the Queue + { + AutoMutex l(mBufferMapLock); + mRawBufferMap.clear(); + // Thread is not running. It is safe to clear the Queue + } BufferQueue::clearBufferQueues(); } @@ -755,8 +758,7 @@ status_t ProcessingUnit::prepareTask(CameraBufferPortMap* srcBuffers, sendPsysRequestEvent(dstBuffers, settingSequence, timestamp, EVENT_REQUEST_METADATA_READY); } - } else if ((!holdOnInput) && (!isBufferHoldForRawReprocess(inputSequence)) - && mBufferProducer != nullptr) { + } else if ((!holdOnInput) && (!isBufferHoldForRawReprocess(inputSequence)) && (mBufferProducer != nullptr)) { for (const auto& src : *srcBuffers) { mBufferProducer->qbuf(src.first, src.second); } diff --git a/src/core/RequestThread.cpp b/src/core/RequestThread.cpp index a376fd30..dd822dbd 100644 --- a/src/core/RequestThread.cpp +++ b/src/core/RequestThread.cpp @@ -118,8 +118,6 @@ void RequestThread::clearRequests() { int RequestThread::configure(const stream_config_t *streamList) { int previewIndex = -1, videoIndex = -1, stillIndex = -1; - bool block_request = false; - for (int i = 0; i < streamList->num_streams; i++) { if (streamList->streams[i].usage == CAMERA_STREAM_PREVIEW) { previewIndex = i; @@ -131,17 +129,15 @@ int RequestThread::configure(const stream_config_t *streamList) { } // Don't block request handling if no 3A stats (from video pipe) - block_request = PlatformData::isEnableAIQ(mCameraId) && - ((previewIndex >= 0) || (videoIndex >= 0)); + AutoMutex l(mPendingReqLock); + mBlockRequest = PlatformData::isEnableAIQ(mCameraId) && ((previewIndex >= 0) || + (videoIndex >= 0)); LOG1("%s: user specified Configmode: %d, blockRequest: %d", __func__, - static_cast(streamList->operation_mode), block_request); - { - AutoMutex l(mPendingReqLock); - mBlockRequest = block_request; - } + static_cast(streamList->operation_mode), mBlockRequest); mGet3AStatWithFakeRequest = mPerframeControlSupport ? PlatformData::isPsysContinueStats(mCameraId) : false; + if (mGet3AStatWithFakeRequest) { const int fakeStreamIndex = (previewIndex >= 0) ? previewIndex : ((videoIndex >= 0) ? videoIndex : stillIndex); @@ -245,7 +241,7 @@ int RequestThread::waitFrame(int streamId, camera_buffer_t **ubuffer) { int RequestThread::wait1stRequestDone() { int ret = OK; std::unique_lock lock(mFirstRequestLock); - if (mFirstRequest) { + while (mFirstRequest) { LOG2("%s, waiting the first request done", __func__); std::cv_status status = mFirstRequestSignal.wait_for( lock, @@ -253,6 +249,7 @@ int RequestThread::wait1stRequestDone() { if (status == std::cv_status::timeout) { LOGE("@%s: Wait 1st request timed out", __func__); ret = TIMED_OUT; + break; } } @@ -306,6 +303,7 @@ void RequestThread::handleEvent(EventData eventData) { break; case EVENT_FRAME_AVAILABLE: { + AutoMutex l(mPendingReqLock); if (eventData.buffer->getUserBuffer() != &mFakeReqBuf) { const int streamId = eventData.data.frameDone.streamId; FrameQueue& frameQueue = mOutputFrames[streamId]; @@ -320,7 +318,6 @@ void RequestThread::handleEvent(EventData eventData) { LOG2("%s: fake request return %u", __func__, eventData.buffer->getSequence()); } - AutoMutex l(mPendingReqLock); // Insert fake request if no any request in the HAL to keep 3A running if (mGet3AStatWithFakeRequest && (eventData.buffer->getSequence() >= mLastEffectSeq) && @@ -371,7 +368,7 @@ bool RequestThread::threadLoop() { { std::unique_lock lock(mPendingReqLock); - if (blockRequest()) { + while (blockRequest()) { std::cv_status ret = mRequestSignal.wait_for(lock, std::chrono::nanoseconds(kWaitDuration * SLOWLY_MULTIPLIER)); CheckWarning(ret == std::cv_status::timeout, true, diff --git a/src/core/SensorHwCtrl.cpp b/src/core/SensorHwCtrl.cpp index 65d26b7f..799e02e2 100644 --- a/src/core/SensorHwCtrl.cpp +++ b/src/core/SensorHwCtrl.cpp @@ -19,9 +19,6 @@ #include #include #include -// CRL_MODULE_S -#include -// CRL_MODULE_E #include "PlatformData.h" #include "SensorHwCtrl.h" @@ -35,9 +32,6 @@ namespace icamera { SensorHwCtrl::SensorHwCtrl(int cameraId, V4L2Subdevice* pixelArraySubdev, V4L2Subdevice* sensorOutputSubdev) : mPixelArraySubdev(pixelArraySubdev), - // CRL_MODULE_S - mSensorOutputSubdev(sensorOutputSubdev), - // CRL_MODULE_E mCameraId(cameraId), mHorzBlank(0), mVertBlank(0), @@ -49,21 +43,6 @@ SensorHwCtrl::SensorHwCtrl(int cameraId, V4L2Subdevice* pixelArraySubdev, mCurFll(0), mCalculatingFrameDuration(true) { LOG1(" @%s", mCameraId, __func__); - // CRL_MODULE_S - /** - * Try to call V4L2_CID_LINE_LENGTH_PIXELS, if failed, it means llp can't - * be read directly from sensor. Then calculate it with HBlank. - * fll will be in the same case. - */ - if (mPixelArraySubdev != nullptr) { - int llp = 0; - const int status = mPixelArraySubdev->GetControl(V4L2_CID_LINE_LENGTH_PIXELS, &llp); - if (status == OK) { - LOG1("%s, some sensors can get llp directly, don't calculate it", __func__); - mCalculatingFrameDuration = false; - } - } - // CRL_MODULE_E } SensorHwCtrl* SensorHwCtrl::createSensorCtrl(int cameraId) { @@ -106,12 +85,6 @@ SensorHwCtrl* SensorHwCtrl::createSensorCtrl(int cameraId) { return sensorCtrl; } -// CRL_MODULE_S -int SensorHwCtrl::configure() { - return OK; -} -// CRL_MODULE_E - int SensorHwCtrl::getActivePixelArraySize(int& width, int& height, int& pixelCode) { HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2); CheckAndLogError(mPixelArraySubdev == nullptr, NO_INIT, "pixel array sub device is not set"); @@ -150,17 +123,6 @@ int SensorHwCtrl::setExposure(const vector& coarseExposures, CheckAndLogError((coarseExposures.empty() || fineExposures.empty()), BAD_VALUE, "No exposure data!"); - // CRL_MODULE_S - if (coarseExposures.size() > 1) { - if (PlatformData::getSensorExposureType(mCameraId) == SENSOR_MULTI_EXPOSURES) { - return setMultiExposures(coarseExposures, fineExposures); - } else if (PlatformData::getSensorExposureType(mCameraId) == - SENSOR_DUAL_EXPOSURES_DCG_AND_VS) { - return setDualExposuresDCGAndVS(coarseExposures, fineExposures); - } - } - // CRL_MODULE_E - LOG2("%s coarseExposure=%d fineExposure=%d", __func__, coarseExposures[0], fineExposures[0]); LOG2("SENSORCTRLINFO: exposure_value=%d", coarseExposures[0]); int status = mPixelArraySubdev->SetControl(V4L2_CID_EXPOSURE, coarseExposures[0]); @@ -169,79 +131,11 @@ int SensorHwCtrl::setExposure(const vector& coarseExposures, return OK; } -// CRL_MODULE_S -int SensorHwCtrl::setMultiExposures(const vector& coarseExposures, - const vector& fineExposures) { - int status = BAD_VALUE; - int shortExp = coarseExposures[0]; - int longExp = coarseExposures[1]; - - if (coarseExposures.size() > 2) { - LOG2("coarseExposure[0]=%d fineExposure[0]=%d", coarseExposures[0], fineExposures[0]); - // The first exposure is very short exposure if larger than 2 exposures. - status = mPixelArraySubdev->SetControl(CRL_CID_EXPOSURE_SHS2, coarseExposures[0]); - CheckAndLogError(status != OK, status, "failed to set exposure SHS2 %d.", - coarseExposures[0]); - - shortExp = coarseExposures[1]; - longExp = coarseExposures[2]; - - LOG2("SENSORCTRLINFO: exposure_long=%d", coarseExposures[2]); // long - LOG2("SENSORCTRLINFO: exposure_med=%d", coarseExposures[1]); // short - LOG2("SENSORCTRLINFO: exposure_short=%d", coarseExposures[0]); // very short - } - - LOG2("shortExp=%d longExp=%d", shortExp, longExp); - status = mPixelArraySubdev->SetControl(CRL_CID_EXPOSURE_SHS1, shortExp); - CheckAndLogError(status != OK, status, "failed to set exposure SHS1 %d.", shortExp); - - status = mPixelArraySubdev->SetControl(V4L2_CID_EXPOSURE, longExp); - CheckAndLogError(status != OK, status, "failed to set long exposure %d.", longExp); - LOG2("SENSORCTRLINFO: exposure_value=%d", longExp); - - return status; -} - -int SensorHwCtrl::setDualExposuresDCGAndVS(const vector& coarseExposures, - const vector& fineExposures) { - int status = BAD_VALUE; - int longExp = coarseExposures[1]; - - if (coarseExposures.size() > 2) { - LOG2("coarseExposure[0]=%d fineExposure[0]=%d", coarseExposures[0], fineExposures[0]); - // The first exposure is very short exposure for DCG + VS case. - status = mPixelArraySubdev->SetControl(CRL_CID_EXPOSURE_SHS1, coarseExposures[0]); - CheckAndLogError(status != OK, status, "failed to set exposure SHS1 %d.", - coarseExposures[0]); - - longExp = coarseExposures[2]; - LOG2("SENSORCTRLINFO: exposure_long=%d", coarseExposures[2]); // long - } - - status = mPixelArraySubdev->SetControl(V4L2_CID_EXPOSURE, longExp); - CheckAndLogError(status != OK, status, "failed to set long exposure %d.", longExp); - LOG2("SENSORCTRLINFO: exposure_value=%d", longExp); - - return status; -} -// CRL_MODULE_E - int SensorHwCtrl::setAnalogGains(const vector& analogGains) { HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2); CheckAndLogError(mPixelArraySubdev == nullptr, NO_INIT, "pixel array sub device is not set"); CheckAndLogError(analogGains.empty(), BAD_VALUE, "No analog gain data!"); - // CRL_MODULE_S - if (analogGains.size() > 1) { - if (PlatformData::getSensorGainType(mCameraId) == SENSOR_MULTI_DG_AND_CONVERSION_AG) { - return setConversionGain(analogGains); - } else if (PlatformData::getSensorGainType(mCameraId) == SENSOR_MULTI_DG_AND_DIRECT_AG) { - LOG2("sensor multi conversion gain"); - return setMultiAnalogGain(analogGains); - } - } - // CRL_MODULE_E - LOG2("%s analogGain=%d", __func__, analogGains[0]); int status = mPixelArraySubdev->SetControl(V4L2_CID_ANALOGUE_GAIN, analogGains[0]); CheckAndLogError((status != 0), status, "failed to set analog gain %d.", analogGains[0]); @@ -254,26 +148,6 @@ int SensorHwCtrl::setDigitalGains(const vector& digitalGains) { CheckAndLogError(mPixelArraySubdev == nullptr, NO_INIT, "pixel array sub device is not set"); CheckAndLogError(digitalGains.empty(), BAD_VALUE, "No digital gain data!"); - // CRL_MODULE_S - if (digitalGains.size() > 1) { - if (PlatformData::getSensorGainType(mCameraId) == SENSOR_MULTI_DG_AND_CONVERSION_AG) { - return setMultiDigitalGain(digitalGains); - } else if (PlatformData::getSensorGainType(mCameraId) == SENSOR_MULTI_DG_AND_DIRECT_AG) { - LOG2("sensor multi conversion gain"); - return setMultiDigitalGain(digitalGains); - } - } - - if ((mWdrMode != 0) && - (PlatformData::getSensorGainType(mCameraId) == ISP_DG_AND_SENSOR_DIRECT_AG)) { - LOG2("%s: WDR mode, skip sensor DG, all digital gain is passed to ISP", __func__); - } else if (PlatformData::isUsingSensorDigitalGain(mCameraId)) { - if (mPixelArraySubdev->SetControl(V4L2_CID_GAIN, digitalGains[0]) != OK) { - LOGW("set digital gain failed"); - } - } - // CRL_MODULE_E - LOG2("%s digitalGain=%d", __func__, digitalGains[0]); int status = mPixelArraySubdev->SetControl(V4L2_CID_DIGITAL_GAIN, digitalGains[0]); CheckAndLogError((status != 0), status, "failed to set digitalGain gain %d.", digitalGains[0]); @@ -281,78 +155,6 @@ int SensorHwCtrl::setDigitalGains(const vector& digitalGains) { return OK; } -// CRL_MODULE_S -int SensorHwCtrl::setMultiDigitalGain(const vector& digitalGains) { - int status = BAD_VALUE; - int shortDg = digitalGains[0]; - int longDg = digitalGains[1]; - - if (digitalGains.size() > 2) { - LOG2("digitalGains[0]=%d", digitalGains[0]); - status = mPixelArraySubdev->SetControl(CRL_CID_DIGITAL_GAIN_VS, digitalGains[0]); - CheckAndLogError(status != OK, status, "failed to set very short DG %d.", digitalGains[0]); - - shortDg = digitalGains[1]; - longDg = digitalGains[2]; - } - - LOG2("shortDg=%d longDg=%d", shortDg, longDg); - status = mPixelArraySubdev->SetControl(CRL_CID_DIGITAL_GAIN_S, shortDg); - CheckAndLogError(status != OK, status, "failed to set short DG %d.", shortDg); - - status = mPixelArraySubdev->SetControl(V4L2_CID_GAIN, longDg); - CheckAndLogError(status != OK, status, "failed to set long DG %d.", longDg); - - return status; -} - -int SensorHwCtrl::setMultiAnalogGain(const vector& analogGains) { - int status = BAD_VALUE; - int shortAg = analogGains[0]; - int longAg = analogGains[1]; - - if (analogGains.size() > 2) { - LOG2("VS AG %d", analogGains[0]); - const int status = mPixelArraySubdev->SetControl(CRL_CID_ANALOG_GAIN_VS, analogGains[0]); - CheckAndLogError(status != OK, status, "failed to set VS AG %d", analogGains[0]); - - shortAg = analogGains[1]; - longAg = analogGains[2]; - - LOG2("SENSORCTRLINFO: gain_long=%d", analogGains[2]); // long - LOG2("SENSORCTRLINFO: gain_med=%d", analogGains[1]); // short - LOG2("SENSORCTRLINFO: gain_short=%d", analogGains[0]); // very short - } - - LOG2("shortAg=%d longAg=%d", shortAg, longAg); - status = mPixelArraySubdev->SetControl(CRL_CID_ANALOG_GAIN_S, shortAg); - CheckAndLogError(status != OK, status, "failed to set short AG %d.", shortAg); - - status = mPixelArraySubdev->SetControl(V4L2_CID_ANALOGUE_GAIN, longAg); - CheckAndLogError(status != OK, status, "failed to set long AG %d.", longAg); - - return status; -} - -int SensorHwCtrl::setConversionGain(const vector& analogGains) { - CheckAndLogError(analogGains.size() < 2, BAD_VALUE, "Gain data error!"); - - /* [0, 1] bits are long AG, [2, 3] bits are short AG, [4, 5] bits are very short AG. - [6] bit is long conversion gain, [7] bit is very short conversion gain. - Long AG: 0x0X0000XX - Short AG: 0x0000XX00 - Very Short AG: 0xX0XX0000 */ - int value = analogGains[0] | analogGains[1] | analogGains[2]; - LOG2("very short AG %d, short AG %d, long AG %d, conversion value %d", analogGains[0], - analogGains[1], analogGains[2], value); - - const int status = mPixelArraySubdev->SetControl(V4L2_CID_ANALOGUE_GAIN, value); - CheckAndLogError(status != OK, status, "failed to set AG %d", value); - - return OK; -} -// CRL_MODULE_E - int SensorHwCtrl::setLineLengthPixels(int llp) { int status = OK; LOG2("@%s, llp:%d", __func__, llp); @@ -362,10 +164,6 @@ int SensorHwCtrl::setLineLengthPixels(int llp) { if (mHorzBlank != horzBlank) { status = mPixelArraySubdev->SetControl(V4L2_CID_HBLANK, horzBlank); } - // CRL_MODULE_S - } else { - status = mPixelArraySubdev->SetControl(V4L2_CID_LINE_LENGTH_PIXELS, llp); - // CRL_MODULE_E } CheckAndLogError(status != OK, status, "failed to set llp. (%d)", status); @@ -383,10 +181,6 @@ int SensorHwCtrl::setFrameLengthLines(int fll) { if (mVertBlank != vertBlank) { status = mPixelArraySubdev->SetControl(V4L2_CID_VBLANK, vertBlank); } - // CRL_MODULE_S - } else { - status = mPixelArraySubdev->SetControl(V4L2_CID_FRAME_LENGTH_LINES, fll); - // CRL_MODULE_E } mCurFll = fll; @@ -424,13 +218,6 @@ int SensorHwCtrl::getLineLengthPixels(int& llp) { mHorzBlank = horzBlank; llp = horzBlank + mCropWidth; } - // CRL_MODULE_S - } else { - status = mPixelArraySubdev->GetControl(V4L2_CID_LINE_LENGTH_PIXELS, &llp); - if (status == OK) { - mHorzBlank = llp - mCropWidth; - } - // CRL_MODULE_E } LOG2("@%s, llp:%d", __func__, llp); @@ -449,13 +236,6 @@ int SensorHwCtrl::getFrameLengthLines(int& fll) { mVertBlank = vertBlank; fll = vertBlank + mCropHeight; } - // CRL_MODULE_S - } else { - status = mPixelArraySubdev->GetControl(V4L2_CID_FRAME_LENGTH_LINES, &fll); - if (status == OK) { - mVertBlank = fll - mCropHeight; - } - // CRL_MODULE_E } LOG2("@%s, fll:%d", __func__, fll); @@ -515,8 +295,6 @@ int SensorHwCtrl::getExposureRange(int& exposureMin, int& exposureMax, int& expo // HDR_FEATURE_S int SensorHwCtrl::setWdrMode(int mode) { HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2); - CheckAndLogError(mSensorOutputSubdev == nullptr, NO_INIT, "sensor output sub device is not set"); - LOG2("%s WDR Mode=%d", __func__, mode); int ret = OK; @@ -525,7 +303,6 @@ int SensorHwCtrl::setWdrMode(int mode) { if ((PlatformData::getSensorExposureType(mCameraId) != SENSOR_RELATIVE_MULTI_EXPOSURES) && (PlatformData::getSensorExposureType(mCameraId) != SENSOR_DUAL_EXPOSURES_DCG_AND_VS)) { LOG2("%s: set WDR mode", __func__); - ret = mSensorOutputSubdev->SetControl(V4L2_CID_WDR_MODE, mode); } return ret; @@ -544,38 +321,4 @@ int SensorHwCtrl::setAWB(float r_per_g, float b_per_g) { } // HDR_FEATURE_E -// CRL_MODULE_S -int SensorHwCtrl::setFrameRate(float fps) { - HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2); - CheckAndLogError(mSensorOutputSubdev == nullptr, NO_INIT, "sensor output sub device is not set"); - - struct v4l2_queryctrl query; - CLEAR(query); - query.id = V4L2_CID_LINK_FREQ; - int status = mSensorOutputSubdev->QueryControl(&query); - CheckAndLogError(status != OK, status, "Couldn't get V4L2_CID_LINK_FREQ, status:%d", status); - - LOG2("@%s, query V4L2_CID_LINK_FREQ:, default_value:%d, maximum:%d, minimum:%d, step:%d", - __func__, query.default_value, query.maximum, query.minimum, query.step); - - int mode = 0; - if (query.maximum == query.minimum) { - mode = query.default_value; - } else { - /*********************************************************************************** - * WA: This heavily depends on sensor driver implementation, need to find a graceful - * solution. - * imx185: - * When fps larger than 30, should switch to high speed mode, currently only - * 0, 1, 2 are available. 0 means 720p 30fps, 1 means 2M 30fps, and 2 means 2M 60fps. - * imx290: - * 0 and 1 available, for 30 and higher FPS. - ***********************************************************************************/ - mode = (fps > 30) ? query.maximum : (query.maximum - 1); - } - LOG2("@%s, set V4L2_CID_LINK_FREQ to %d, fps %f", __func__, mode, fps); - return mSensorOutputSubdev->SetControl(V4L2_CID_LINK_FREQ, mode); -} -// CRL_MODULE_E - } // namespace icamera diff --git a/src/core/SensorHwCtrl.h b/src/core/SensorHwCtrl.h index 1963eb39..171751f7 100644 --- a/src/core/SensorHwCtrl.h +++ b/src/core/SensorHwCtrl.h @@ -32,9 +32,6 @@ class SensorHwCtrl { SensorHwCtrl(int cameraId, V4L2Subdevice* pixelArraySubdev, V4L2Subdevice* sensorOutputSubdev); virtual ~SensorHwCtrl() {} - // CRL_MODULE_S - virtual int configure(); - // CRL_MODULE_E virtual int setTestPatternMode(int32_t testPatternMode); virtual int getPixelRate(int& pixelRate); virtual int setExposure(const std::vector& coarseExposures, @@ -69,29 +66,13 @@ class SensorHwCtrl { virtual int setAWB(float r_per_g, float b_per_g); // HDR_FEATURE_E - // CRL_MODULE_S - virtual int setFrameRate(float fps); - // CRL_MODULE_E private: int setLineLengthPixels(int llp); int getLineLengthPixels(int& llp); int setFrameLengthLines(int fll); int getFrameLengthLines(int& fll); - // CRL_MODULE_S - int setMultiExposures(const std::vector& coarseExposures, - const std::vector& fineExposures); - int setDualExposuresDCGAndVS(const std::vector& coarseExposures, - const std::vector& fineExposures); - int setConversionGain(const std::vector& analogGains); - int setMultiDigitalGain(const std::vector& digitalGains); - int setMultiAnalogGain(const std::vector& analogGains); - // CRL_MODULE_E - V4L2Subdevice* mPixelArraySubdev; - // CRL_MODULE_S - V4L2Subdevice* mSensorOutputSubdev; - // CRL_MODULE_E int mCameraId; int mHorzBlank; int mVertBlank; @@ -137,9 +118,6 @@ class DummySensor : public SensorHwCtrl { // HDR_FEATURE_S virtual int setWdrMode(int mode) { return OK; } // HDR_FEATURE_E - // CRL_MODULE_S - virtual int setFrameRate(float fps) { return OK; } - // CRL_MODULE_E }; } // namespace icamera diff --git a/src/core/SwPostProcessUnit.cpp b/src/core/SwPostProcessUnit.cpp index 60ef096a..60c2d833 100644 --- a/src/core/SwPostProcessUnit.cpp +++ b/src/core/SwPostProcessUnit.cpp @@ -164,25 +164,6 @@ status_t SwPostProcessUnit::configure(const stream_t& srcStream, const stream_t& processingOrder.push_back(info); } -// JPEG_ENCODE_S - // Encode - if (dstStream.format == V4L2_PIX_FMT_JPEG && - mPostProcessorCore->isPostProcessTypeSupported(POST_PROCESS_JPEG_ENCODING)) { - mPostProcessType |= POST_PROCESS_JPEG_ENCODING; - info.type = POST_PROCESS_JPEG_ENCODING; - info.inputInfo = inputStreamInfo; - info.outputInfo.width = dstStream.width; - info.outputInfo.height = dstStream.height; - info.outputInfo.stride = dstStream.width; - info.outputInfo.format = V4L2_PIX_FMT_NV12; // should get the actual format - info.outputInfo.size = - CameraUtils::getFrameSize(info.outputInfo.format, info.outputInfo.width, - info.outputInfo.height, false, false, false); - inputStreamInfo = info.outputInfo; - processingOrder.push_back(info); - } -// JPEG_ENCODE_E - if (inputStreamInfo.width != dstStream.width || inputStreamInfo.height != dstStream.height) { //inputStreamInfo.format != diff --git a/src/core/processingUnit/IPipeManager.h b/src/core/processingUnit/IPipeManager.h index 4732f67d..3580f604 100644 --- a/src/core/processingUnit/IPipeManager.h +++ b/src/core/processingUnit/IPipeManager.h @@ -86,7 +86,7 @@ class IPipeManager : public EventListener { virtual void setControl(int64_t sequence, const PipeControl& control) {} - virtual void addTask(PipeTaskData taskParam) = 0; + virtual void addTask(const PipeTaskData& taskParam) = 0; virtual int prepareIpuParams(IspSettings* settings, int64_t sequence = 0, int streamId = VIDEO_STREAM_ID) { return OK; diff --git a/src/core/processingUnit/PipeLine.cpp b/src/core/processingUnit/PipeLine.cpp index afd82f7b..5aca942f 100644 --- a/src/core/processingUnit/PipeLine.cpp +++ b/src/core/processingUnit/PipeLine.cpp @@ -32,7 +32,8 @@ PipeLine::PipeLine(int cameraId, int streamId, std::shared_ptr gc, mGraphConfig(gc), mScheduler(scheduler), mPSysDevice(nullptr), - mPacAdaptor(nullptr) { + mPacAdaptor(nullptr), + mTuningMode(TUNING_MODE_VIDEO) { LOG1("@%s stream %d", mCameraId, __func__, mStreamId); } diff --git a/src/core/processingUnit/PipeLine.h b/src/core/processingUnit/PipeLine.h index 0f881f00..003a0545 100644 --- a/src/core/processingUnit/PipeLine.h +++ b/src/core/processingUnit/PipeLine.h @@ -76,6 +76,9 @@ class PipeLine { std::shared_ptr scheduler); virtual ~PipeLine(); + PipeLine(const PipeLine&) = delete; + PipeLine& operator=(const PipeLine&) = delete; + void deinit(); int configure(TuningMode tuningMode, IpuPacAdaptor* adaptor); int start(); diff --git a/src/core/processingUnit/PipeManager.cpp b/src/core/processingUnit/PipeManager.cpp index 5307f1f5..16ceac60 100644 --- a/src/core/processingUnit/PipeManager.cpp +++ b/src/core/processingUnit/PipeManager.cpp @@ -399,7 +399,7 @@ void PipeManager::setControl(int64_t sequence, const PipeControl& control) { } } -void PipeManager::addTask(PipeTaskData taskParam) { +void PipeManager::addTask(const PipeTaskData& taskParam) { LOG2("@%s", mCameraId, __func__); TaskInfo task = {}; @@ -437,7 +437,7 @@ void PipeManager::addTask(PipeTaskData taskParam) { TRACE_LOG_PROCESS("run PAC", __func__, MAKE_COLOR(sequence), sequence); for (const auto& id : activeStreamIds) { - (void)prepareIpuParams(&taskParam.mIspSettings, sequence, id); + (void)prepareIpuParams(&task.mTaskData.mIspSettings, sequence, id); } queueBuffers(taskParam, mInputMaps, mOutputMaps, mDefaultMainInputPort); } diff --git a/src/core/processingUnit/PipeManager.h b/src/core/processingUnit/PipeManager.h index 60fdb548..b0109f44 100644 --- a/src/core/processingUnit/PipeManager.h +++ b/src/core/processingUnit/PipeManager.h @@ -43,11 +43,14 @@ class PipeManager : public IPipeManager { virtual void setControl(int64_t sequence, const PipeControl& control); - virtual void addTask(PipeTaskData taskParam); + virtual void addTask(const PipeTaskData& taskParam); virtual int prepareIpuParams(IspSettings* settings, int64_t sequence = 0, int streamId = VIDEO_STREAM_ID); protected: + PipeManager(const PipeManager&) = delete; + PipeManager& operator=(const PipeManager&) = delete; + /** * @brief handle bufferDone and metadata event from pipeStage */ diff --git a/src/image_process/PostProcessorBase.cpp b/src/image_process/PostProcessorBase.cpp index 8143c174..5d8639c5 100644 --- a/src/image_process/PostProcessorBase.cpp +++ b/src/image_process/PostProcessorBase.cpp @@ -111,210 +111,4 @@ status_t ConvertProcess::doPostProcessing(const shared_ptr& inBuf, return OK; } -// JPEG_ENCODE_S -JpegProcess::JpegProcess(int cameraId) - : PostProcessorBase("JpegEncode"), - mCameraId(cameraId), - mCropBuf(nullptr), - mScaleBuf(nullptr), - mThumbOut(nullptr), - mExifData(nullptr) { - LOG1("@%s create jpeg encode processor", __func__); - - mProcessor = IImageProcessor::createImageProcessor(); - mJpegEncoder = IJpegEncoder::createJpegEncoder(); - mMemoryType = mJpegEncoder->getMemoryType(); - mJpegMaker = std::unique_ptr(new JpegMaker()); -} - -void JpegProcess::attachJpegBlob(const EncodePackage& package) { - LOG2("@%s, encoded data size: %d, exif data size: %d", __func__, package.encodedDataSize, - package.exifDataSize); - uint8_t* resultPtr = static_cast(package.outputData) + package.outputSize - - sizeof(struct camera3_jpeg_blob); - - // save jpeg size at the end of file - auto* blob = reinterpret_cast(resultPtr); - blob->jpeg_blob_id = CAMERA3_JPEG_BLOB_ID; - blob->jpeg_size = package.encodedDataSize + package.exifDataSize; -} - -std::shared_ptr JpegProcess::cropAndDownscaleThumbnail( - int thumbWidth, int thumbHeight, const shared_ptr& inBuf) { - LOG2("@%s, input size: %dx%d, thumbnail info: %dx%d", __func__, - inBuf->getWidth(), inBuf->getHeight(), thumbWidth, thumbHeight); - - if (thumbWidth <= 0 || thumbHeight <= 0) { - LOGW("@%s, skip, thumbWidth:%d, thumbHeight:%d", __func__, thumbWidth, thumbHeight); - return nullptr; - } - - int ret = OK; - shared_ptr tempBuffer = inBuf; - - // Do crop first if needed - if (IImageProcessor::isProcessingTypeSupported(POST_PROCESS_CROP) && - inBuf->getWidth() * thumbHeight != inBuf->getHeight() * thumbWidth) { - int width = 0, height = 0; - if (inBuf->getWidth() * thumbHeight < inBuf->getHeight() * thumbWidth) { - width = inBuf->getWidth(); - height = ALIGN(inBuf->getWidth() * thumbHeight / thumbWidth, 2); - } else { - width = ALIGN(inBuf->getHeight() * thumbWidth / thumbHeight, 2); - height = inBuf->getHeight(); - } - - if (mCropBuf && (mCropBuf->getWidth() != width || mCropBuf->getHeight() != height)) { - mCropBuf.reset(); - } - if (!mCropBuf) { - int bufSize = CameraUtils::getFrameSize(inBuf->getFormat(), width, height, - false, false, false); - mCropBuf = CameraBuffer::create(mMemoryType, bufSize, 0, inBuf->getFormat(), - width, height); - CheckAndLogError(!mCropBuf, nullptr, - "%s, Failed to allocate the internal crop buffer", __func__); - } - - LOG2("@%s, Crop the main buffer from %dx%d to %dx%d", __func__, inBuf->getWidth(), - inBuf->getHeight(), width, height); - ret = mProcessor->cropFrame(inBuf, mCropBuf); - CheckAndLogError(ret != OK, nullptr, "%s, Failed to crop the frame", __func__); - tempBuffer = mCropBuf; - } - - if (IImageProcessor::isProcessingTypeSupported(POST_PROCESS_SCALING)) { - if (mScaleBuf && - (mScaleBuf->getWidth() != thumbWidth || mScaleBuf->getHeight() != thumbHeight)) - mScaleBuf.reset(); - if (!mScaleBuf) { - int bufSize = CameraUtils::getFrameSize(inBuf->getFormat(), thumbWidth, thumbHeight, - false, false, false); - mScaleBuf = CameraBuffer::create(mMemoryType, bufSize, 0, inBuf->getFormat(), - thumbWidth, thumbHeight); - CheckAndLogError(!mScaleBuf, nullptr, - "%s, Failed to allocate the internal crop buffer", __func__); - } - - LOG2("@%s, Scale the buffer from %dx%d to %dx%d", __func__, inBuf->getWidth(), - inBuf->getHeight(), thumbWidth, thumbHeight); - ret = mProcessor->scaleFrame(tempBuffer, mScaleBuf); - CheckAndLogError(ret != OK, nullptr, "%s, Failed to crop the frame", __func__); - tempBuffer = mScaleBuf; - } - - if (tempBuffer->getWidth() != thumbWidth || tempBuffer->getHeight() != thumbHeight) { - LOGE("%s, Failed to crop & downscale the main buffer to thumbnail buffer", __func__); - return nullptr; - } - - return tempBuffer; -} - -void JpegProcess::fillEncodeInfo(const shared_ptr& inBuf, - const shared_ptr& outBuf, - EncodePackage& package) { - package.inputWidth = inBuf->getWidth(); - package.inputHeight = inBuf->getHeight(); - package.inputStride = inBuf->getStride(); - package.inputFormat = inBuf->getFormat(); - package.inputSize = inBuf->getBufferSize(); - - if (inBuf->getMemory() == V4L2_MEMORY_DMABUF && outBuf->getMemory() == V4L2_MEMORY_DMABUF) { - camera_buffer_t* uInBuf = inBuf->getUserBuffer(); - package.inputBufferHandle = &(uInBuf->privateHandle); - - camera_buffer_t* uOutBuf = outBuf->getUserBuffer(); - package.outputBufferHandle = &(uOutBuf->privateHandle); - } - - package.inputData = inBuf->getBufferAddr(); - package.outputData = outBuf->getBufferAddr(); - - package.outputWidth = outBuf->getWidth(); - package.outputHeight = outBuf->getHeight(); - package.outputSize = outBuf->getBufferSize(); -} - -status_t JpegProcess::doPostProcessing(const shared_ptr& inBuf, - shared_ptr& outBuf) { - PERF_CAMERA_ATRACE_PARAM1(mName.c_str(), 0); - LOG1("@%s processor name: %s", __func__, mName.c_str()); - - bool isEncoded = false; - - icamera::ExifMetaData exifMetadata; - status_t status = mJpegMaker->setupExifWithMetaData(inBuf->getWidth(), inBuf->getHeight(), - inBuf->getSequence(), TIMEVAL2NSECS(inBuf->getTimestamp()),mCameraId, - &exifMetadata); - CheckAndLogError(status != OK, UNKNOWN_ERROR, "@%s, Setup exif metadata failed.", __func__); - LOG2("@%s: setting exif metadata done!", __func__); - - std::shared_ptr thumbInput = cropAndDownscaleThumbnail( - exifMetadata.mJpegSetting.thumbWidth, exifMetadata.mJpegSetting.thumbHeight, inBuf); - - EncodePackage thumbnailPackage; - if (thumbInput) { - if (mThumbOut == nullptr || - mThumbOut->getWidth() != exifMetadata.mJpegSetting.thumbWidth || - mThumbOut->getHeight() != exifMetadata.mJpegSetting.thumbHeight || - mThumbOut->getFormat() != outBuf->getFormat()) { - int bufSize = CameraUtils::getFrameSize(inBuf->getFormat(), - exifMetadata.mJpegSetting.thumbWidth, - exifMetadata.mJpegSetting.thumbHeight, - false, false, false); - - mThumbOut = CameraBuffer::create(mMemoryType, bufSize, 0, V4L2_PIX_FMT_JPEG, - exifMetadata.mJpegSetting.thumbWidth, - exifMetadata.mJpegSetting.thumbHeight); - CheckAndLogError(!mThumbOut, NO_MEMORY, - "%s, Failed to allocate the internal crop buffer", __func__); - } - - // encode thumbnail image - fillEncodeInfo(thumbInput, mThumbOut, thumbnailPackage); - thumbnailPackage.quality = exifMetadata.mJpegSetting.jpegThumbnailQuality; - // the exifDataSize should be 0 for encoding thumbnail - thumbnailPackage.exifData = nullptr; - thumbnailPackage.exifDataSize = 0; - - do { - isEncoded = mJpegEncoder->doJpegEncode(&thumbnailPackage); - thumbnailPackage.quality -= 5; - } while (thumbnailPackage.encodedDataSize > THUMBNAIL_SIZE_LIMITATION && - thumbnailPackage.quality > 0); - - if (!isEncoded || thumbnailPackage.quality < 0) { - LOGW( - "Failed to generate thumbnail, isEncoded: %d, encoded thumbnail size: %d, " - "quality:%d", - isEncoded, thumbnailPackage.encodedDataSize, thumbnailPackage.quality); - } - } - - // save exif data - uint32_t exifBufSize = ENABLE_APP2_MARKER ? EXIF_SIZE_LIMITATION * 2 : EXIF_SIZE_LIMITATION; - if (mExifData == nullptr) { - mExifData = std::unique_ptr(new unsigned char[exifBufSize]); - } - uint8_t* finalExifDataPtr = static_cast(mExifData.get()); - uint32_t finalExifDataSize = 0; - status = mJpegMaker->getExif(thumbnailPackage, finalExifDataPtr, &finalExifDataSize); - CheckAndLogError(status != OK, status, "@%s, Failed to get Exif", __func__); - LOG2("%s, exifBufSize %d, finalExifDataSize %d", __func__, exifBufSize, finalExifDataSize); - - // encode main image - EncodePackage finalEncodePackage; - fillEncodeInfo(inBuf, outBuf, finalEncodePackage); - finalEncodePackage.quality = exifMetadata.mJpegSetting.jpegQuality; - finalEncodePackage.exifData = finalExifDataPtr; - finalEncodePackage.exifDataSize = finalExifDataSize; - isEncoded = mJpegEncoder->doJpegEncode(&finalEncodePackage); - CheckAndLogError(!isEncoded, UNKNOWN_ERROR, "@%s, Failed to encode main image", __func__); - mJpegMaker->writeExifData(&finalEncodePackage); - attachJpegBlob(finalEncodePackage); - - return OK; -} -// JPEG_ENCODE_E } // namespace icamera diff --git a/src/image_process/PostProcessorBase.h b/src/image_process/PostProcessorBase.h index f19833b0..b6b71e03 100644 --- a/src/image_process/PostProcessorBase.h +++ b/src/image_process/PostProcessorBase.h @@ -22,11 +22,6 @@ #include "IImageProcessor.h" #include "iutils/Errors.h" #include "iutils/Utils.h" -// JPEG_ENCODE_S -#include "EXIFMetaData.h" -#include "IJpegEncoder.h" -#include "JpegMaker.h" -// JPEG_ENCODE_E namespace icamera { @@ -88,34 +83,4 @@ class ConvertProcess : public PostProcessorBase { std::shared_ptr& outBuf); }; -// JPEG_ENCODE_S -class JpegProcess : public PostProcessorBase { - public: - JpegProcess(int cameraId); - ~JpegProcess(){} - - virtual status_t doPostProcessing(const std::shared_ptr& inBuf, - std::shared_ptr& outBuf); - - private: - void attachJpegBlob(const EncodePackage& package); - - std::shared_ptr cropAndDownscaleThumbnail( - int thumbWidth, int thumbHeight, const std::shared_ptr& inBuf); - void fillEncodeInfo(const std::shared_ptr& inBuf, - const std::shared_ptr& outBuf, - EncodePackage& package); - - private: - int mCameraId; - - std::shared_ptr mCropBuf; - std::shared_ptr mScaleBuf; - std::shared_ptr mThumbOut; - - std::unique_ptr mJpegMaker; - std::unique_ptr mJpegEncoder; - std::unique_ptr mExifData; -}; -// JPEG_ENCODE_E } // namespace icamera diff --git a/src/image_process/PostProcessorCore.cpp b/src/image_process/PostProcessorCore.cpp index bc5bb372..41e12824 100644 --- a/src/image_process/PostProcessorCore.cpp +++ b/src/image_process/PostProcessorCore.cpp @@ -49,11 +49,6 @@ status_t PostProcessorCore::createProcessor() { case POST_PROCESS_CONVERT: processor = std::make_shared(); break; -// JPEG_ENCODE_S - case POST_PROCESS_JPEG_ENCODING: - processor = std::make_shared(mCameraId); - break; -// JPEG_ENCODE_E case POST_PROCESS_NONE: break; default: diff --git a/src/iutils/CameraLog.h b/src/iutils/CameraLog.h index 79d316eb..e2f48f80 100644 --- a/src/iutils/CameraLog.h +++ b/src/iutils/CameraLog.h @@ -204,6 +204,10 @@ class ScopedTrace { } } + // Prevent copying (RAII class should not be copied) + ScopedTrace(const ScopedTrace&) = delete; + ScopedTrace& operator=(const ScopedTrace&) = delete; + private: int mLevel; const char* mName; diff --git a/src/iutils/CameraShm.cpp b/src/iutils/CameraShm.cpp index f766318d..13ac8d91 100644 --- a/src/iutils/CameraShm.cpp +++ b/src/iutils/CameraShm.cpp @@ -92,9 +92,9 @@ void CameraSharedMemory::acquireSharedMemory() { CheckAndLogError(lock() != OK, VOID_VALUE, "Fail to lock shared memory!"); // get the shared memory ID, create shared memory if not exist - mSharedMemId = shmget(CAMERA_IPCKEY, CAMERA_SM_SIZE, 0640); + mSharedMemId = shmget(CAMERA_IPCKEY, CAMERA_SM_SIZE, S_IRUSR | S_IWUSR | S_IRGRP); if (mSharedMemId == -1) { - mSharedMemId = shmget(CAMERA_IPCKEY, CAMERA_SM_SIZE, IPC_CREAT | 0640); + mSharedMemId = shmget(CAMERA_IPCKEY, CAMERA_SM_SIZE, IPC_CREAT | S_IRUSR | S_IWUSR | S_IRGRP); if (mSharedMemId < 0) { LOGE("Fail to allocate shared memory by shmget."); unlock(); @@ -213,7 +213,7 @@ bool CameraSharedMemory::processExist(pid_t pid, const char* storedName) { } void CameraSharedMemory::openSemLock() { - mSemLock = sem_open(SEM_NAME, O_CREAT | O_EXCL, 0644, 1); + mSemLock = sem_open(SEM_NAME, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, 1); if (mSemLock == SEM_FAILED) { mSemLock = sem_open(SEM_NAME, O_RDWR); if (mSemLock == SEM_FAILED) { @@ -223,7 +223,9 @@ void CameraSharedMemory::openSemLock() { LOG1("Open the sem lock"); } } else { - chmod(SEM_FD_NAME, 0666); + if(chmod(SEM_FD_NAME, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) != 0){ + LOGW("Failed to chmod, errno: %s", strerror(errno)); + } LOG1("Create the sem lock"); return; } @@ -246,11 +248,13 @@ void CameraSharedMemory::openSemLock() { LOG1("Lock timed out, process holding it may have crashed. Re-create the semaphore."); sem_close(mSemLock); sem_unlink(SEM_NAME); - mSemLock = sem_open(SEM_NAME, O_CREAT | O_EXCL, 0644, 1); + mSemLock = sem_open(SEM_NAME, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, 1); if (mSemLock == SEM_FAILED) { LOGE("failed to re-create sem lock, errno: %s\n", strerror(errno)); } else { - chmod(SEM_FD_NAME, 0666); + if(chmod(SEM_FD_NAME, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) != 0){ + LOGW("Failed to chmod, errno: %s", strerror(errno)); + } } } } diff --git a/src/iutils/LogSink.cpp b/src/iutils/LogSink.cpp index cc63959c..16b81732 100644 --- a/src/iutils/LogSink.cpp +++ b/src/iutils/LogSink.cpp @@ -114,6 +114,13 @@ FileLogSink::FileLogSink() { mFp = fopen(filePath, "w"); } +FileLogSink::~FileLogSink() { + if (mFp != nullptr) { + (void)fclose(mFp); + mFp = nullptr; + } +} + void FileLogSink::sendOffLog(LogItem logItem) { char timeInfo[TIME_BUF_SIZE]; LogOutputSink::setLogTime(timeInfo); diff --git a/src/iutils/LogSink.h b/src/iutils/LogSink.h index 72e96f7a..623df6f4 100644 --- a/src/iutils/LogSink.h +++ b/src/iutils/LogSink.h @@ -60,6 +60,7 @@ class StdconLogSink : public LogOutputSink { class FileLogSink : public LogOutputSink { public: FileLogSink(); + ~FileLogSink(); void sendOffLog(LogItem logItem) override; private: diff --git a/src/iutils/RWLock.h b/src/iutils/RWLock.h index daa254ae..c48d110e 100644 --- a/src/iutils/RWLock.h +++ b/src/iutils/RWLock.h @@ -48,16 +48,26 @@ class RWLock { class AutoRLock { public: - inline AutoRLock(RWLock& rwlock) : mLock(rwlock) { mLock.readLock(); } + inline explicit AutoRLock(RWLock& rwlock) : mLock(rwlock) { mLock.readLock(); } inline ~AutoRLock() { mLock.unlock(); } + + // Prevent copying (RAII lock guard should not be copied) + AutoRLock(const AutoRLock&) = delete; + AutoRLock& operator=(const AutoRLock&) = delete; + private: RWLock& mLock; }; class AutoWLock { public: - inline AutoWLock(RWLock& rwlock) : mLock(rwlock) { mLock.writeLock(); } + inline explicit AutoWLock(RWLock& rwlock) : mLock(rwlock) { mLock.writeLock(); } inline ~AutoWLock() { mLock.unlock(); } + + // Prevent copying (RAII lock guard should not be copied) + AutoWLock(const AutoWLock&) = delete; + AutoWLock& operator=(const AutoWLock&) = delete; + private: RWLock& mLock; }; @@ -86,7 +96,7 @@ inline status_t RWLock::tryWriteLock() { return -pthread_rwlock_trywrlock(&mRWLock); } inline void RWLock::unlock() { - pthread_rwlock_unlock(&mRWLock); + (void)pthread_rwlock_unlock(&mRWLock); } #endif // HAVE_PTHREADS diff --git a/src/iutils/SwImageConverter.cpp b/src/iutils/SwImageConverter.cpp index 2f864b66..24a20a81 100644 --- a/src/iutils/SwImageConverter.cpp +++ b/src/iutils/SwImageConverter.cpp @@ -435,13 +435,15 @@ int SwImageConverter::convertFormat(unsigned int width, unsigned int height, uns for (y = 0U; y < height; y += 2) { for (x = 0U; x < width; x += 2) { if (CameraUtils::isRaw(srcFmt)) { - if (CameraUtils::getBpp(srcFmt) == 8) { + const int bpp = CameraUtils::getBpp(srcFmt); + if (bpp == 8) { bayer_data[0] = inBuf[y * srcStride + x]; bayer_data[1] = inBuf[y * srcStride + x + 1]; bayer_data[2] = inBuf[(y + 1) * srcStride + x]; bayer_data[3] = inBuf[(y + 1) * srcStride + x + 1]; } else { - const int offset = srcStride / (CameraUtils::getBpp(srcFmt) / 8); + CheckAndLogError(bpp < 8, BAD_VALUE, "Unsupported BPP: %d", bpp); + const int offset = srcStride / (bpp / 8); bayer_data[0] = *((unsigned short*)inBuf + y * offset + x); bayer_data[1] = *((unsigned short*)inBuf + y * offset + x + 1U); bayer_data[2] = *((unsigned short*)inBuf + (y + 1U) * offset + x); diff --git a/src/iutils/Utils.cpp b/src/iutils/Utils.cpp index db9f93bb..4bba1c2a 100644 --- a/src/iutils/Utils.cpp +++ b/src/iutils/Utils.cpp @@ -620,8 +620,12 @@ void CameraUtils::getDeviceName(const char* entityName, string& deviceNodeName, subDeviceName += dirp->d_name; subDeviceName += "/name"; const int fd = open(subDeviceName.c_str(), O_RDONLY); - CheckAndLogError((fd < 0), VOID_VALUE, "@%s, open file %s failed. err: %s", __func__, - subDeviceName.c_str(), strerror(errno)); + if (fd < 0) { + LOGE("@%s, open file %s failed. err: %s", __func__, + subDeviceName.c_str(), strerror(errno)); + closedir(dp); + return; + } char buf[128] = {'\0'}; int len = read(fd, buf, sizeof(buf)); diff --git a/src/metadata/CameraMetadata.cpp b/src/metadata/CameraMetadata.cpp index 7950db96..388471d3 100644 --- a/src/metadata/CameraMetadata.cpp +++ b/src/metadata/CameraMetadata.cpp @@ -19,6 +19,8 @@ #include "CameraMetadata.h" +#include + #include "iutils/CameraLog.h" #include "iutils/Utils.h" @@ -39,7 +41,10 @@ CameraMetadata::CameraMetadata(icamera_metadata_t* buffer) : mBuffer(nullptr), m } CameraMetadata& CameraMetadata::operator=(const CameraMetadata& other) { - return operator=(other.mBuffer); + if(this != &other) { + acquire(other.mBuffer); + } + return *this; } CameraMetadata& CameraMetadata::operator=(const icamera_metadata_t* buffer) { @@ -228,9 +233,10 @@ status_t CameraMetadata::updateImpl(uint32_t tag, const void* data, size_t data_ } if (res != OK) { + const int errCode = (res == INT_MIN) ? INT_MAX : -res; LOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)", __func__, get_icamera_metadata_section_name(tag), get_icamera_metadata_tag_name(tag), tag, - strerror(-res), res); + strerror(errCode), res); } if (validate_icamera_metadata_structure(mBuffer, /*size*/ nullptr) != OK) { @@ -281,15 +287,19 @@ status_t CameraMetadata::erase(uint32_t tag) { if (res == NAME_NOT_FOUND) { return OK; } else if (res != OK) { + const int errCode = (res == INT_MIN) ? INT_MAX : -res; LOGE("%s: Error looking for entry %s.%s (%x): %s %d", __func__, get_icamera_metadata_section_name(tag), get_icamera_metadata_tag_name(tag), tag, - strerror(-res), res); + strerror(errCode), res); return res; } res = delete_icamera_metadata_entry(mBuffer, entry.index); - CheckAndLogError(res != OK, res, "%s: Error deleting entry %s.%s (%x): %s %d", __func__, - get_icamera_metadata_section_name(tag), get_icamera_metadata_tag_name(tag), - tag, strerror(-res), res); + if (res != OK) { + const int errCode = (res == INT_MIN) ? INT_MAX : -res; + LOGE("%s: Error deleting entry %s.%s (%x): %s %d", __func__, + get_icamera_metadata_section_name(tag), get_icamera_metadata_tag_name(tag), + tag, strerror(errCode), res); + } return res; } diff --git a/src/metadata/ParameterHelper.h b/src/metadata/ParameterHelper.h index 09e0fb45..0250232b 100644 --- a/src/metadata/ParameterHelper.h +++ b/src/metadata/ParameterHelper.h @@ -99,6 +99,8 @@ class ParameterHelper { public: AutoRLock(void* data) : mLock(getInternalData(data).mRwLock) { mLock.readLock(); } ~AutoRLock() { mLock.unlock(); } + AutoRLock(const AutoRLock&) = delete; + AutoRLock& operator=(const AutoRLock&) = delete; private: RWLock& mLock; }; @@ -107,6 +109,8 @@ class ParameterHelper { public: AutoWLock(void* data) : mLock(getInternalData(data).mRwLock) { mLock.writeLock(); } ~AutoWLock() { mLock.unlock(); } + AutoWLock(const AutoWLock&) = delete; + AutoWLock& operator=(const AutoWLock&) = delete; private: RWLock& mLock; }; diff --git a/src/metadata/icamera_metadata_base.cpp b/src/metadata/icamera_metadata_base.cpp index 1db972d2..782176f0 100644 --- a/src/metadata/icamera_metadata_base.cpp +++ b/src/metadata/icamera_metadata_base.cpp @@ -187,9 +187,13 @@ icamera_metadata_t *allocate_icamera_metadata(size_t entry_capacity, const size_t memory_needed = calculate_icamera_metadata_size(entry_capacity, data_capacity); void *buffer = malloc(memory_needed); - return place_icamera_metadata(buffer, memory_needed, + icamera_metadata_t *metadata = place_icamera_metadata(buffer, memory_needed, entry_capacity, data_capacity); + if(metadata == nullptr) { + free(buffer); + } + return metadata; } icamera_metadata_t *place_icamera_metadata(void *dst, diff --git a/src/platformdata/AiqInitData.cpp b/src/platformdata/AiqInitData.cpp index 0009a2a0..922cf0e2 100644 --- a/src/platformdata/AiqInitData.cpp +++ b/src/platformdata/AiqInitData.cpp @@ -19,7 +19,9 @@ #include "AiqInitData.h" #include +#include #include +#include #include @@ -65,30 +67,37 @@ void AiqData::loadFile(const std::string& fileName, ia_binary_data* data, int ma LOG1("%s, file name %s", __func__, fileName.c_str()); CheckAndLogError(data == nullptr, VOID_VALUE, "data is nullptr"); - // Get file size - struct stat fileStat; - CLEAR(fileStat); - const int ret = stat(fileName.c_str(), &fileStat); - if (ret != 0) { - LOG1("There is no file %s", fileName.c_str()); + const int fd = open(fileName.c_str(), O_RDONLY | O_CLOEXEC); + if (fd < 0) { + LOG1("Failed to open file %s, error %s", fileName.c_str(), strerror(errno)); return; } - int64_t usedFileSize = fileStat.st_size; - if ((maxSize > 0) && (maxSize < fileStat.st_size)) { + struct stat statBuf; + const int ret = fstat(fd, &statBuf); + if ((ret != 0) || (S_ISREG(statBuf.st_mode) == 0)) { + LOG1("Failed to stat file: %s!", fileName.c_str()); + close(fd); + return; + } + + int64_t usedFileSize = statBuf.st_size; + if ((maxSize > 0) && (maxSize < statBuf.st_size)) { usedFileSize = maxSize; } - // Open file - FILE* fp = fopen(fileName.c_str(), "rb"); - CheckWarning(fp == nullptr, VOID_VALUE, "Failed to open file %s, error %s", fileName.c_str(), - strerror(errno)); + FILE* file = fdopen(fd, "rb"); + if (file == nullptr) { + LOG1("Failed to fdopen file %s", fileName.c_str()); + close(fd); + return; + } std::unique_ptr dataPtr(new char[usedFileSize]); // Read data - const size_t readSize = fread(dataPtr.get(), sizeof(char), usedFileSize, fp); - (void)fclose(fp); + const size_t readSize = fread(dataPtr.get(), sizeof(char), usedFileSize, file); + (void)fclose(file); CheckWarning(readSize != (size_t)usedFileSize, VOID_VALUE, "Failed to read %s, error %s", fileName.c_str(), strerror(errno)); @@ -262,7 +271,7 @@ ia_binary_data* AiqInitData::getNvm(int cameraId, const char* overwrittenFile, i if (CameraDump::isDumpTypeEnable(DUMP_NVM_DATA)) { ia_binary_data* nvmData = mNvm->getData(); if (nvmData && nvmData->data && (nvmData->size > 0U)) { - BinParam_t bParam; + BinParam_t bParam{}; bParam.bType = BIN_TYPE_GENERAL; bParam.mType = M_NVM; bParam.sequence = 0; diff --git a/src/platformdata/CMakeLists.txt b/src/platformdata/CMakeLists.txt index 39b624ee..40df9ab8 100644 --- a/src/platformdata/CMakeLists.txt +++ b/src/platformdata/CMakeLists.txt @@ -29,12 +29,12 @@ set(PLATFORMDATA_SRCS ${PLATFORMDATA_SRCS} ) # IPU7_SOURCE_FILE_E - set(PLATFORMDATA_SRCS - ${PLATFORMDATA_SRCS} - ${PLATFORMDATA_DIR}/AiqInitData.cpp - ${PLATFORMDATA_DIR}/gc/GraphUtils.cpp - ${PLATFORMDATA_DIR}/gc/GraphConfigManager.cpp - ${PLATFORMDATA_DIR}/gc/GraphConfig.cpp - CACHE INTERNAL "platformdata sources" - ) +set(PLATFORMDATA_SRCS + ${PLATFORMDATA_SRCS} + ${PLATFORMDATA_DIR}/AiqInitData.cpp + ${PLATFORMDATA_DIR}/gc/GraphUtils.cpp + ${PLATFORMDATA_DIR}/gc/GraphConfigManager.cpp + ${PLATFORMDATA_DIR}/gc/GraphConfig.cpp + CACHE INTERNAL "platformdata sources" + ) diff --git a/src/platformdata/CameraSensorsParser.cpp b/src/platformdata/CameraSensorsParser.cpp index 4212ae49..8b197119 100644 --- a/src/platformdata/CameraSensorsParser.cpp +++ b/src/platformdata/CameraSensorsParser.cpp @@ -23,10 +23,6 @@ #include #include -// CRL_MODULE_S -#include - -// CRL_MODULE_E #include "iutils/CameraLog.h" namespace icamera { @@ -161,13 +157,6 @@ std::map ctlCmdMapTable = { // HDR_FEATURE_S {"V4L2_CID_WDR_MODE", V4L2_CID_WDR_MODE}, // HDR_FEATURE_E -// CRL_MODULE_S - {"V4L2_CID_LINE_LENGTH_PIXELS", V4L2_CID_LINE_LENGTH_PIXELS}, - {"V4L2_CID_FRAME_LENGTH_LINES", V4L2_CID_FRAME_LENGTH_LINES}, - {"CRL_CID_SENSOR_MODE", CRL_CID_SENSOR_MODE}, - {"CRL_CID_EXPOSURE_MODE", CRL_CID_EXPOSURE_MODE}, - {"CRL_CID_EXPOSURE_HDR_RATIO", CRL_CID_EXPOSURE_HDR_RATIO}, -// CRL_MODULE_E }; void CameraSensorsParser::parseMediaCtlControlObject(const Json::Value& node, MediaCtlConf* conf) { for (Json::Value::ArrayIndex i = 0; i < node.size(); ++i) { @@ -1051,6 +1040,11 @@ void CameraSensorsParser::updateNVMDir() { } if (readSize > 0) { for (auto& nvm : mNVMDeviceInfo) { + /* STRING_NULL: String not null terminated warning */ + /* False Positive: Buffer allocated with size+1 bytes and explicitly null-terminated */ + /* (readSize < size) and (readSize >= size) address the null-termination */ + /* Waive by deviation: False Positive */ + //coverity[string_null : FALSE] if (strstr(ptr.get(), nvm.nodeName.c_str()) != nullptr) { std::string nvmPath(NVM_DATA_PATH); nvmPath.append("i2c-"); diff --git a/src/platformdata/JsonParserBase.h b/src/platformdata/JsonParserBase.h index c1d7d227..10fa6eac 100644 --- a/src/platformdata/JsonParserBase.h +++ b/src/platformdata/JsonParserBase.h @@ -22,6 +22,15 @@ namespace icamera { +/* Rule of Three: All special functions should be defined defined */ +/* Destructor: Explicitly declared as virtual ~JsonParserBase() = default */ +/* Copy constructor: Deleted by DISALLOW_COPY_AND_ASSIGN macro expansion in Utils.h */ +/* Copy assignment: Deleted by DISALLOW_COPY_AND_ASSIGN macro expansion in Utils.h */ +/* The macro expands to: TypeName(const TypeName&) = delete; */ +/* TypeName& operator=(const TypeName&) = delete; */ +/* All three (destructor, copy constructor, copy assignment) are defined */ +/* Waive by deviation: False Positive */ +//coverity[rule_of_three_violation : FALSE] */ class JsonParserBase { public: JsonParserBase() = default; diff --git a/src/platformdata/PlatformData.h b/src/platformdata/PlatformData.h index 8f1f84d6..959c3be1 100644 --- a/src/platformdata/PlatformData.h +++ b/src/platformdata/PlatformData.h @@ -155,6 +155,10 @@ class StaticMetadata { class PlatformData { private: + + PlatformData(const PlatformData&) = delete; + PlatformData& operator=(const PlatformData&) = delete; + // Prevent to create multiple instances PlatformData(); ~PlatformData(); diff --git a/src/platformdata/gc/GraphConfig.cpp b/src/platformdata/gc/GraphConfig.cpp index e4f2a001..6b9900e6 100644 --- a/src/platformdata/gc/GraphConfig.cpp +++ b/src/platformdata/gc/GraphConfig.cpp @@ -18,6 +18,10 @@ #include "src/platformdata/gc/GraphConfig.h" +#include +#include +#include + #include "PlatformData.h" #include "iutils/CameraLog.h" #include "GraphUtils.h" @@ -58,7 +62,7 @@ GraphConfig::GraphConfig(int32_t camId, ConfigMode mode) : mCameraId(camId), mSe "%s: failed to init graph reader", __func__); } -GraphConfig::GraphConfig() : mCameraId(-1) { } +GraphConfig::GraphConfig() : mCameraId(-1), mSensorRatio(0.0f) { } GraphConfig::~GraphConfig() { for (auto& graph : mStaticGraphs) graph.second.clear(); @@ -600,12 +604,26 @@ int32_t GraphConfig::loadPipeConfig(const string& fileName) { int32_t GraphConfig::loadStaticGraphConfig(const std::string& name) { const char* fileName = name.c_str(); + + const int fd = open(fileName, O_RDONLY | O_CLOEXEC); + CheckAndLogError(fd < 0, NAME_NOT_FOUND, "%s, Failed to open file: %s", __func__, fileName); + struct stat statBuf; - int32_t ret = stat(fileName, &statBuf); - CheckAndLogError(ret != OK, ret, "Failed to query the size of file: %s!", fileName); + const int ret = fstat(fd, &statBuf); + if ((ret != 0) || (S_ISREG(statBuf.st_mode) == 0)) { + close(fd); + if (ret != 0) { + CheckAndLogError(true, ret, "%s, Failed to get file stats for: %s", __func__, fileName); + } else { + CheckAndLogError(true, BAD_VALUE, "%s, Invalid file type (directory, link, or device): %s", __func__, fileName); + } + } - FILE* file = fopen(fileName, "rb"); - CheckAndLogError(!file, NAME_NOT_FOUND, "%s, Failed to open file: %s", __func__, fileName); + FILE* file = fdopen(fd, "rb"); + if (file == nullptr) { + close(fd); + CheckAndLogError(true, NAME_NOT_FOUND, "%s, Failed to create file stream for: %s", __func__, fileName); + } StaticReaderBinaryData binData; binData.size = static_cast(statBuf.st_size); @@ -616,7 +634,7 @@ int32_t GraphConfig::loadStaticGraphConfig(const std::string& name) { return NO_MEMORY; } - size_t len = fread(binData.data, 1, binData.size, file); + const size_t len = fread(binData.data, 1, binData.size, file); (void)fclose(file); if (len != binData.size) { LOGE("%s, read data %zu from file %s, should be %u", __func__, len, fileName, binData.size); @@ -1011,10 +1029,13 @@ status_t GraphConfig::pipelineGetConnections(int32_t streamId, if (!conn.portFormatSettings.enabled) { continue; } - checkAndUpdatePostConnection(streamId, &conn, &postVector, mGPUStageInfos); + if (conn.stream != nullptr) { + checkAndUpdatePostConnection(streamId, &conn, &postVector, mGPUStageInfos); + } IGraphType::PipelineConnection* connPtr = postVector.size() > 0 ? &(postVector[postVector.size() - 1]) : &conn; - checkAndUpdatePostConnection(streamId, connPtr, &postVector, mPostStageInfos); + if (connPtr->stream) + checkAndUpdatePostConnection(streamId, connPtr, &postVector, mPostStageInfos); } confVector->insert(confVector->end(), postVector.begin(), postVector.end()); LOG3("%s dump for stream %d ++", __func__, streamId); @@ -1027,10 +1048,10 @@ void GraphConfig::checkAndUpdatePostConnection(int32_t streamId, IGraphType::PipelineConnection* conn, vector* postVector, std::map& postStageInfos) { - if (!conn || !conn->stream || !postVector) { + + if (conn->stream == nullptr) { return; } - int32_t useStreamId = conn->stream->streamId(); if (postStageInfos.find(useStreamId) == postStageInfos.end()) { diff --git a/src/v4l2/MediaControl.cpp b/src/v4l2/MediaControl.cpp index 0b2cc334..3afdd107 100644 --- a/src/v4l2/MediaControl.cpp +++ b/src/v4l2/MediaControl.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2011 The Android Open Source Project - * Copyright (C) 2015-2026 Intel Corporation + * Copyright (C) 2015-2022 Intel Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -128,6 +128,10 @@ void MediaControl::releaseInstance() { MediaControl::MediaControl(const char* devName) : mDevName(devName) { LOG1("@%s device: %s", __func__, devName); +// VIRTUAL_CHANNEL_S + + mIsMediaCtlSetup = false; +// VIRTUAL_CHANNEL_E int ret = initEntities(); CheckAndLogError(ret, VOID_VALUE, "Failed to init entities"); @@ -360,8 +364,8 @@ void MediaControl::closeDevice(int fd) { } void MediaControl::dumpInfo(media_device_info& devInfo) { - LOGI("Media controller API version %u.%u.%u\n\n", (devInfo.media_version << 16) & 0xff, - (devInfo.media_version << 8) & 0xff, (devInfo.media_version << 0) & 0xff); + LOGI("Media controller API version %u.%u.%u\n\n", (devInfo.media_version >> 16) & 0xffU, + (devInfo.media_version >> 8) & 0xffU, (devInfo.media_version >> 0) & 0xffU); LOGI("Media device information\n" "------------------------\n" @@ -372,11 +376,12 @@ void MediaControl::dumpInfo(media_device_info& devInfo) { "hw revision 0x%x\n" "driver version %u.%u.%u\n\n", devInfo.driver, devInfo.model, devInfo.serial, devInfo.bus_info, devInfo.hw_revision, - (devInfo.driver_version << 16) & 0xff, (devInfo.driver_version << 8) & 0xff, - (devInfo.driver_version << 0) & 0xff); + (devInfo.driver_version >> 16) & 0xffU, (devInfo.driver_version >> 8) & 0xffU, + (devInfo.driver_version >> 0) & 0xffU); - for (uint32_t i = 0U; i < sizeof(devInfo.reserved) / sizeof(uint32_t); i++) + for (uint32_t i = 0U; i < sizeof(devInfo.reserved) / sizeof(uint32_t); i++) { LOGI("reserved[%u] %d", i, devInfo.reserved[i]); + } } int MediaControl::enumInfo() { @@ -601,22 +606,32 @@ int MediaControl::enumLinks(int fd) { source = getEntityById(link->source.entity); sink = getEntityById(link->sink.entity); - if ((source == nullptr) || (sink == nullptr)) { + if ((source == nullptr) || (sink == nullptr)) { LOG1("WARNING entity %u link %u src %u/%u to %u/%u is invalid!", entity.info.id, i, - link->source.entity, link->source.index, link->sink.entity, link->sink.index); + link->source.entity, link->source.index, link->sink.entity, link->sink.index); ret = -EINVAL; } else { + const uint16_t sourceIndex = link->source.index; + const uint16_t sinkIndex = link->sink.index; + const uint16_t sourcePads = source->info.pads; + const uint16_t sinkPads = sink->info.pads; + + if ((sourceIndex >= sourcePads) || (sinkIndex >= sinkPads)) { + LOG1("WARNING entity %u link %u pad index out of bounds (src %u/%u, sink %u/%u)!", + entity.info.id, i, sourceIndex, sourcePads, sinkIndex, sinkPads); + ret = -EINVAL; + } else { fwdlink = entityAddLink(source); if (fwdlink != nullptr) { - fwdlink->source = &source->pads[link->source.index]; - fwdlink->sink = &sink->pads[link->sink.index]; + fwdlink->source = &source->pads[sourceIndex]; + fwdlink->sink = &sink->pads[sinkIndex]; fwdlink->flags = link->flags; } backlink = entityAddLink(sink); if (backlink != nullptr) { - backlink->source = &source->pads[link->source.index]; - backlink->sink = &sink->pads[link->sink.index]; + backlink->source = &source->pads[sourceIndex]; + backlink->sink = &sink->pads[sinkIndex]; backlink->flags = link->flags; } @@ -628,6 +643,7 @@ int MediaControl::enumLinks(int fd) { } } } + } delete[] links.pads; delete[] links.links; @@ -849,39 +865,6 @@ int MediaControl::setRouting(int cameraId, MediaCtlConf* mc, bool enableRouting) routes[i] = r; } - - // When enabling routes, compare current hardware state with the desired configuration. - // VIDIOC_SUBDEV_S_ROUTING resets all stream states on the subdev, which can disrupt - // other processes or camera instances sharing the same subdev. Skip SetRouting when - // the hardware already reflects the exact routes we need. - if (enableRouting) { - uint32_t numCurrentRoutes = static_cast(num); - v4l2_subdev_route* currentRoutes = new v4l2_subdev_route[numCurrentRoutes](); - int gret = subDev->GetRouting(currentRoutes, &numCurrentRoutes); - bool skip = (gret == 0 && numCurrentRoutes == static_cast(num)); - for (int i = 0; i < num && skip; i++) { - bool found = false; - for (uint32_t j = 0; j < numCurrentRoutes; j++) { - if (routes[i].sink_pad == currentRoutes[j].sink_pad && - routes[i].sink_stream == currentRoutes[j].sink_stream && - routes[i].source_pad == currentRoutes[j].source_pad && - routes[i].source_stream == currentRoutes[j].source_stream && - routes[i].flags == currentRoutes[j].flags) { - found = true; - break; - } - } - if (!found) skip = false; - } - delete[] currentRoutes; - if (skip) { - LOG1(" Routes already match for entity:%s, skipping SetRouting", - cameraId, routing.first.c_str()); - delete[] routes; - continue; - } - } - int ret = subDev->SetRouting(routes, num); delete[] routes; CheckAndLogError(ret != 0, ret, "setRouting fail, ret:%d", ret); @@ -894,7 +877,7 @@ int MediaControl::setRouting(int cameraId, MediaCtlConf* mc, bool enableRouting) int MediaControl::setVideoNodeFormat(struct V4L2VideoNode* device, const stream_t* config) { PERF_CAMERA_ATRACE(); - struct v4l2_format v4l2fmt; + struct v4l2_format v4l2fmt = {}; v4l2fmt.fmt.pix_mp.field = config->field; v4l2fmt.fmt.pix.width = config->width; @@ -941,15 +924,6 @@ int MediaControl::setVideoNodesFormat(MediaCtlConf* mc, int field) { return ret; } -const std::string MediaControl::getVideoIsysReceiverName(const MediaCtlConf* mc) { - for (const auto& videoNode : mc->videoNodes) { - if (videoNode.videoNodeType == VIDEO_ISYS_RECEIVER) { - return videoNode.name; - } - } - return std::string(); -} - // VIRTUAL_CHANNEL_E int MediaControl::mediaCtlSetup(int cameraId, MediaCtlConf* mc, int width, int height, int field) { LOG1(" %s", cameraId, __func__); @@ -960,11 +934,11 @@ int MediaControl::mediaCtlSetup(int cameraId, MediaCtlConf* mc, int width, int h AutoMutex lock(sLock); if (!mc->routings.empty()) { - if (mIsysReceiverNamesConfigured.find(getVideoIsysReceiverName(mc)) != - mIsysReceiverNamesConfigured.end()) + if (mIsMediaCtlSetup) { return OK; - else - mIsysReceiverNamesConfigured.insert(getVideoIsysReceiverName(mc)); + } else { + mIsMediaCtlSetup = true; + } } // VIRTUAL_CHANNEL_E @@ -1018,14 +992,7 @@ void MediaControl::mediaCtlClear(int cameraId, MediaCtlConf* mc) { LOG1(" %s", cameraId, __func__); // VIRTUAL_CHANNEL_S - /* Do not disable routes on close. VIDIOC_SUBDEV_S_ROUTING resets stream states, so - * clearing routes here would disrupt other processes or camera instances that share the - * same subdev and are still streaming. Routes are left active on the hardware; the next - * open() will skip SetRouting if the routes already match (see setRouting). - * Remove the receiver from the in-process tracking set so that a subsequent open() in - * this process re-evaluates the full setup (formats, links), even though SetRouting itself - * will be skipped when routes are still correctly configured. - */ + (void)setRouting(cameraId, mc, false); // VIRTUAL_CHANNEL_E } @@ -1361,7 +1328,11 @@ void MediaControl::setSensorOrientation(int cameraId) { } std::string subDevName; - PlatformData::getDevNameByType(cameraId, VIDEO_PIXEL_ARRAY, subDevName); + const int ret = PlatformData::getDevNameByType(cameraId, VIDEO_PIXEL_ARRAY, subDevName); + if (ret != OK) { + LOGE("@%s, failed to get device name for VIDEO_PIXEL_ARRAY, cameraId: %d", __func__, cameraId); + return; + } LOG1("@%s, sub-dev name is %s", __func__, subDevName.c_str()); V4L2Subdevice* subDev = V4l2DeviceFactory::getSubDev(cameraId, subDevName); if ((subDev->SetControl(V4L2_CID_HFLIP, 1) == OK) && diff --git a/src/v4l2/MediaControl.h b/src/v4l2/MediaControl.h index 83957210..70599a9d 100644 --- a/src/v4l2/MediaControl.h +++ b/src/v4l2/MediaControl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2026 Intel Corporation. + * Copyright (C) 2015-2021 Intel Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,9 +31,6 @@ #include #include -// VIRTUAL_CHANNEL_S -#include -// VIRTUAL_CHANNEL_E #include #include "CameraTypes.h" @@ -270,7 +267,8 @@ class MediaControl { std::string* i2cBus); private: - MediaControl& operator=(const MediaControl&); + MediaControl(const MediaControl&) = delete; + MediaControl& operator=(const MediaControl&) = delete; MediaControl(const char* devName); ~MediaControl(); @@ -304,11 +302,10 @@ class MediaControl { int setMediaMcLink(std::vector links); int setFormat(int cameraId, const McFormat* format, int targetWidth, int targetHeight, int field); - // VIRTUAL_CHANNEL_S +// VIRTUAL_CHANNEL_S int setVideoNodeFormat(struct V4L2VideoNode *device, const stream_t* format); int setVideoNodesFormat(MediaCtlConf* mc, int field); - const std::string getVideoIsysReceiverName(const MediaCtlConf *mc); - // VIRTUAL_CHANNEL_E +// VIRTUAL_CHANNEL_E int setSelection(int cameraId, const McFormat* format, int targetWidth, int targetHeight); int setRouting(int cameraId, MediaCtlConf* mc, bool enableRouting); /* Dump functions */ @@ -327,12 +324,13 @@ class MediaControl { std::string mDevName; std::vector mEntities; - // VIRTUAL_CHANNEL_S - std::unordered_set mIsysReceiverNamesConfigured; - // VIRTUAL_CHANNEL_E static MediaControl* sInstance; static Mutex sLock; +// VIRTUAL_CHANNEL_S + + bool mIsMediaCtlSetup; +// VIRTUAL_CHANNEL_E }; } // namespace icamera diff --git a/src/v4l2/V4l2DeviceFactory.h b/src/v4l2/V4l2DeviceFactory.h index 2a911064..7c27e025 100644 --- a/src/v4l2/V4l2DeviceFactory.h +++ b/src/v4l2/V4l2DeviceFactory.h @@ -41,6 +41,10 @@ class V4l2DeviceFactory { static void releaseSubDev(int cameraId, const std::string& devName); private: + + V4l2DeviceFactory(const V4l2DeviceFactory&) = delete; + V4l2DeviceFactory& operator=(const V4l2DeviceFactory&) = delete; + V4l2DeviceFactory(int cameraId); ~V4l2DeviceFactory();