@@ -94,6 +94,7 @@ const ControlInfoMap::Map ipaColourControls{
9494 { &controls::AwbEnable, ControlInfo (false , true ) },
9595 { &controls::AwbMode, ControlInfo (controls::AwbModeValues) },
9696 { &controls::ColourGains, ControlInfo (0 .0f , 32 .0f ) },
97+ { &controls::ColourCorrectionMatrix, ControlInfo (0 .0f , 8 .0f ) },
9798 { &controls::ColourTemperature, ControlInfo (100 , 100000 ) },
9899 { &controls::Saturation, ControlInfo (0 .0f , 32 .0f , 1 .0f ) },
99100};
@@ -126,7 +127,7 @@ namespace ipa::RPi {
126127IpaBase::IpaBase ()
127128 : controller_(), frameLengths_(FrameLengthsQueueSize, 0s), statsMetadataOutput_(false ),
128129 stitchSwapBuffers_ (false ), frameCount_(0 ), mistrustCount_(0 ), lastRunTimestamp_(0 ),
129- firstStart_(true ), flickerState_({ 0 , 0s })
130+ firstStart_(true ), flickerState_({ 0 , 0s }), awbEnabled_( true )
130131{
131132}
132133
@@ -821,6 +822,102 @@ void IpaBase::applyControls(const ControlList &controls)
821822 }
822823 }
823824
825+ /*
826+ * We must also handle any AWB on/off changes first, so that the CCM algorithm
827+ * knows its state correctly.
828+ */
829+ const auto awbEnable = controls.get (controls::AwbEnable);
830+ if (awbEnable)
831+ do {
832+ /* Silently ignore this control for a mono sensor. */
833+ if (monoSensor_)
834+ break ;
835+
836+ RPiController::AwbAlgorithm *awb = dynamic_cast <RPiController::AwbAlgorithm *>(
837+ controller_.getAlgorithm (" awb" ));
838+ if (!awb) {
839+ LOG (IPARPI, Warning)
840+ << " Could not set AWB_ENABLE - no AWB algorithm" ;
841+ break ;
842+ }
843+
844+ awbEnabled_ = *awbEnable;
845+
846+ if (!awbEnabled_)
847+ awb->disableAuto ();
848+ else {
849+ awb->enableAuto ();
850+
851+ /* The CCM algorithm must go back to auto as well. */
852+ RPiController::CcmAlgorithm *ccm = dynamic_cast <RPiController::CcmAlgorithm *>(
853+ controller_.getAlgorithm (" ccm" ));
854+ if (ccm)
855+ ccm->enableAuto ();
856+ }
857+
858+ libcameraMetadata_.set (controls::AwbEnable, awbEnabled_);
859+ } while (false );
860+
861+ const auto colourGains = controls.get (controls::ColourGains);
862+ if (colourGains)
863+ do {
864+ /* Silently ignore this control for a mono sensor. */
865+ if (monoSensor_)
866+ break ;
867+
868+ auto gains = *colourGains;
869+ RPiController::AwbAlgorithm *awb = dynamic_cast <RPiController::AwbAlgorithm *>(
870+ controller_.getAlgorithm (" awb" ));
871+ if (!awb) {
872+ LOG (IPARPI, Warning)
873+ << " Could not set COLOUR_GAINS - no AWB algorithm" ;
874+ break ;
875+ }
876+
877+ awb->setManualGains (gains[0 ], gains[1 ]);
878+ if (gains[0 ] != 0 .0f && gains[1 ] != 0 .0f ) {
879+ /* A gain of 0.0f will switch back to auto mode. */
880+ libcameraMetadata_.set (controls::ColourGains,
881+ { gains[0 ], gains[1 ] });
882+
883+ awbEnabled_ = false ; /* doing this puts AWB into manual mode */
884+ } else {
885+ awbEnabled_ = true ; /* doing this puts AWB into auto mode */
886+
887+ /* The CCM algorithm must go back to auto as well. */
888+ RPiController::CcmAlgorithm *ccm = dynamic_cast <RPiController::CcmAlgorithm *>(
889+ controller_.getAlgorithm (" ccm" ));
890+ if (ccm)
891+ ccm->enableAuto ();
892+ }
893+
894+ /* This metadata will get reported back automatically. */
895+ break ;
896+ } while (false );
897+
898+ const auto colourTemperature = controls.get (controls::ColourTemperature);
899+ if (colourTemperature)
900+ do {
901+ /* Silently ignore this control for a mono sensor. */
902+ if (monoSensor_)
903+ break ;
904+
905+ auto temperatureK = *colourTemperature;
906+ RPiController::AwbAlgorithm *awb = dynamic_cast <RPiController::AwbAlgorithm *>(
907+ controller_.getAlgorithm (" awb" ));
908+ if (!awb) {
909+ LOG (IPARPI, Warning)
910+ << " Could not set COLOUR_TEMPERATURE - no AWB algorithm" ;
911+ break ;
912+ }
913+
914+ awb->setColourTemperature (temperatureK);
915+ awbEnabled_ = false ; /* doing this puts AWB into manual mode */
916+
917+ /* This metadata will get reported back automatically. */
918+ break ;
919+ } while (false );
920+
824921 /* Iterate over controls */
825922 for (auto const &ctrl : controls) {
826923 LOG (IPARPI, Debug) << " Request ctrl: "
@@ -1037,25 +1134,7 @@ void IpaBase::applyControls(const ControlList &controls)
10371134 }
10381135
10391136 case controls::AWB_ENABLE: {
1040- /* Silently ignore this control for a mono sensor. */
1041- if (monoSensor_)
1042- break ;
1043-
1044- RPiController::AwbAlgorithm *awb = dynamic_cast <RPiController::AwbAlgorithm *>(
1045- controller_.getAlgorithm (" awb" ));
1046- if (!awb) {
1047- LOG (IPARPI, Warning)
1048- << " Could not set AWB_ENABLE - no AWB algorithm" ;
1049- break ;
1050- }
1051-
1052- if (ctrl.second .get <bool >() == false )
1053- awb->disableAuto ();
1054- else
1055- awb->enableAuto ();
1056-
1057- libcameraMetadata_.set (controls::AwbEnable,
1058- ctrl.second .get <bool >());
1137+ /* We handled this one above. */
10591138 break ;
10601139 }
10611140
@@ -1080,47 +1159,60 @@ void IpaBase::applyControls(const ControlList &controls)
10801159 LOG (IPARPI, Error) << " AWB mode " << idx
10811160 << " not recognised" ;
10821161 }
1162+
10831163 break ;
10841164 }
10851165
10861166 case controls::COLOUR_GAINS: {
1087- /* Silently ignore this control for a mono sensor. */
1088- if (monoSensor_)
1089- break ;
1090-
1091- auto gains = ctrl.second .get <Span<const float >>();
1092- RPiController::AwbAlgorithm *awb = dynamic_cast <RPiController::AwbAlgorithm *>(
1093- controller_.getAlgorithm (" awb" ));
1094- if (!awb) {
1095- LOG (IPARPI, Warning)
1096- << " Could not set COLOUR_GAINS - no AWB algorithm" ;
1097- break ;
1098- }
1099-
1100- awb->setManualGains (gains[0 ], gains[1 ]);
1101- if (gains[0 ] != 0 .0f && gains[1 ] != 0 .0f )
1102- /* A gain of 0.0f will switch back to auto mode. */
1103- libcameraMetadata_.set (controls::ColourGains,
1104- { gains[0 ], gains[1 ] });
1167+ /* We handled this one above. */
11051168 break ;
11061169 }
11071170
11081171 case controls::COLOUR_TEMPERATURE: {
1109- /* Silently ignore this control for a mono sensor. */
1172+ /* We handled this one above. */
1173+ break ;
1174+ }
1175+
1176+ case controls::COLOUR_CORRECTION_MATRIX: {
11101177 if (monoSensor_)
11111178 break ;
11121179
1113- auto temperatureK = ctrl.second .get <int32_t >();
1180+ auto floats = ctrl.second .get <Span<const float >>();
1181+ RPiController::CcmAlgorithm *ccm = dynamic_cast <RPiController::CcmAlgorithm *>(
1182+ controller_.getAlgorithm (" ccm" ));
1183+ if (!ccm) {
1184+ LOG (IPARPI, Warning)
1185+ << " Could not set COLOUR_CORRECTION_MATRIX - no CCM algorithm" ;
1186+ break ;
1187+ }
1188+
11141189 RPiController::AwbAlgorithm *awb = dynamic_cast <RPiController::AwbAlgorithm *>(
11151190 controller_.getAlgorithm (" awb" ));
1116- if (! awb) {
1191+ if (awb && awbEnabled_ ) {
11171192 LOG (IPARPI, Warning)
1118- << " Could not set COLOUR_TEMPERATURE - no AWB algorithm " ;
1193+ << " Could not set COLOUR_CORRECTION_MATRIX - AWB is active " ;
11191194 break ;
11201195 }
11211196
1122- awb->setColourTemperature (temperatureK);
1123- /* This metadata will get reported back automatically. */
1197+ /* We are guaranteed this control contains 9 values. Nevertheless: */
1198+ assert (floats.size () == 9 );
1199+
1200+ Matrix<double , 3 , 3 > matrix;
1201+ for (std::size_t i = 0 ; i < 3 ; ++i)
1202+ for (std::size_t j = 0 ; j < 3 ; ++j)
1203+ matrix[i][j] = static_cast <double >(floats[i * 3 + j]);
1204+
1205+ ccm->setCcm (matrix);
1206+
1207+ /*
1208+ * But if AWB is running, go back to auto mode. The CCM gets remembered,
1209+ * which avoids the race between setting the CCM and disabling AWB in
1210+ * the same set of controls.
1211+ */
1212+ if (awbEnabled_)
1213+ ccm->enableAuto ();
1214+
1215+ /* This metadata will be reported back automatically. */
11241216 break ;
11251217 }
11261218
0 commit comments