28
28
#include " controller/lux_status.h"
29
29
#include " controller/sharpen_algorithm.h"
30
30
#include " controller/statistics.h"
31
+ #include " controller/sync_algorithm.h"
32
+ #include " controller/sync_status.h"
31
33
32
34
namespace libcamera {
33
35
@@ -72,6 +74,8 @@ const ControlInfoMap::Map ipaControls{
72
74
{ &controls::Sharpness, ControlInfo (0 .0f , 16 .0f , 1 .0f ) },
73
75
{ &controls::ScalerCrop, ControlInfo (Rectangle{}, Rectangle (65535 , 65535 , 65535 , 65535 ), Rectangle{}) },
74
76
{ &controls::FrameDurationLimits, ControlInfo (INT64_C (33333 ), INT64_C (120000 )) },
77
+ { &controls::rpi::SyncMode, ControlInfo (controls::rpi::SyncModeValues) },
78
+ { &controls::rpi::SyncFrames, ControlInfo (1 , 1000000 , 100 ) },
75
79
{ &controls::draft::NoiseReductionMode, ControlInfo (controls::draft::NoiseReductionModeValues) },
76
80
{ &controls::rpi::StatsOutputEnable, ControlInfo (false , true , false ) },
77
81
{ &controls::rpi::CnnEnableInputTensor, ControlInfo (false , true , false ) },
@@ -391,6 +395,7 @@ void IpaBase::prepareIsp(const PrepareParams ¶ms)
391
395
392
396
rpiMetadata.clear ();
393
397
fillDeviceStatus (params.sensorControls , ipaContext);
398
+ fillSyncParams (params, ipaContext);
394
399
395
400
if (params.buffers .embedded ) {
396
401
/*
@@ -489,10 +494,24 @@ void IpaBase::processStats(const ProcessParams ¶ms)
489
494
helper_->process (statistics, rpiMetadata);
490
495
controller_.process (statistics, &rpiMetadata);
491
496
497
+ /* Send any sync algorithm outputs back to the pipeline handler */
498
+ Duration offset (0s);
499
+ struct SyncStatus syncStatus;
500
+ if (rpiMetadata.get (" sync.status" , syncStatus) == 0 ) {
501
+ if (minFrameDuration_ != maxFrameDuration_)
502
+ LOG (IPARPI, Error) << " Sync algorithm enabled with variable framerate. "
503
+ << minFrameDuration_ << " " << maxFrameDuration_;
504
+ offset = syncStatus.frameDurationOffset ;
505
+
506
+ libcameraMetadata_.set (controls::rpi::SyncReady, syncStatus.ready );
507
+ if (syncStatus.timerKnown )
508
+ libcameraMetadata_.set (controls::rpi::SyncTimer, syncStatus.timerValue );
509
+ }
510
+
492
511
struct AgcStatus agcStatus;
493
512
if (rpiMetadata.get (" agc.status" , agcStatus) == 0 ) {
494
513
ControlList ctrls (sensorCtrls_);
495
- applyAGC (&agcStatus, ctrls);
514
+ applyAGC (&agcStatus, ctrls, offset );
496
515
setDelayedControls.emit (ctrls, ipaContext);
497
516
setCameraTimeoutValue ();
498
517
}
@@ -729,6 +748,7 @@ void IpaBase::applyControls(const ControlList &controls)
729
748
using RPiController::ContrastAlgorithm;
730
749
using RPiController::DenoiseAlgorithm;
731
750
using RPiController::HdrAlgorithm;
751
+ using RPiController::SyncAlgorithm;
732
752
733
753
/* Clear the return metadata buffer. */
734
754
libcameraMetadata_.clear ();
@@ -1279,6 +1299,35 @@ void IpaBase::applyControls(const ControlList &controls)
1279
1299
cnnEnableInputTensor_ = ctrl.second .get <bool >();
1280
1300
break ;
1281
1301
1302
+ case controls::rpi::SYNC_MODE: {
1303
+ SyncAlgorithm *sync = dynamic_cast <SyncAlgorithm *>(controller_.getAlgorithm (" sync" ));
1304
+
1305
+ if (sync) {
1306
+ int mode = ctrl.second .get <int32_t >();
1307
+ SyncAlgorithm::Mode m = SyncAlgorithm::Mode::Off;
1308
+ if (mode == controls::rpi::SyncModeServer) {
1309
+ m = SyncAlgorithm::Mode::Server;
1310
+ LOG (IPARPI, Info) << " Sync mode set to server" ;
1311
+ } else if (mode == controls::rpi::SyncModeClient) {
1312
+ m = SyncAlgorithm::Mode::Client;
1313
+ LOG (IPARPI, Info) << " Sync mode set to client" ;
1314
+ }
1315
+ sync->setMode (m);
1316
+ }
1317
+ break ;
1318
+ }
1319
+
1320
+ case controls::rpi::SYNC_FRAMES: {
1321
+ SyncAlgorithm *sync = dynamic_cast <SyncAlgorithm *>(controller_.getAlgorithm (" sync" ));
1322
+
1323
+ if (sync) {
1324
+ int frames = ctrl.second .get <int32_t >();
1325
+ if (frames > 0 )
1326
+ sync->setReadyFrame (frames);
1327
+ }
1328
+ break ;
1329
+ }
1330
+
1282
1331
default :
1283
1332
LOG (IPARPI, Warning)
1284
1333
<< " Ctrl " << controls::controls.at (ctrl.first )->name ()
@@ -1315,6 +1364,19 @@ void IpaBase::fillDeviceStatus(const ControlList &sensorControls, unsigned int i
1315
1364
rpiMetadata_[ipaContext].set (" device.status" , deviceStatus);
1316
1365
}
1317
1366
1367
+ void IpaBase::fillSyncParams (const PrepareParams ¶ms, unsigned int ipaContext)
1368
+ {
1369
+ RPiController::SyncAlgorithm *sync = dynamic_cast <RPiController::SyncAlgorithm *>(
1370
+ controller_.getAlgorithm (" sync" ));
1371
+ if (!sync)
1372
+ return ;
1373
+
1374
+ SyncParams syncParams;
1375
+ syncParams.wallClock = *params.sensorControls .get (controls::FrameWallClock);
1376
+ syncParams.sensorTimestamp = *params.sensorControls .get (controls::SensorTimestamp);
1377
+ rpiMetadata_[ipaContext].set (" sync.params" , syncParams);
1378
+ }
1379
+
1318
1380
void IpaBase::reportMetadata (unsigned int ipaContext)
1319
1381
{
1320
1382
RPiController::Metadata &rpiMetadata = rpiMetadata_[ipaContext];
@@ -1528,14 +1590,22 @@ void IpaBase::applyFrameDurations(Duration minFrameDuration, Duration maxFrameDu
1528
1590
* value possible.
1529
1591
*/
1530
1592
Duration maxExposureTime = Duration::max ();
1531
- helper_->getBlanking (maxExposureTime, minFrameDuration_, maxFrameDuration_);
1593
+ auto [vblank, hblank] = helper_->getBlanking (maxExposureTime, minFrameDuration_, maxFrameDuration_);
1532
1594
1533
1595
RPiController::AgcAlgorithm *agc = dynamic_cast <RPiController::AgcAlgorithm *>(
1534
1596
controller_.getAlgorithm (" agc" ));
1535
1597
agc->setMaxExposureTime (maxExposureTime);
1598
+
1599
+ RPiController::SyncAlgorithm *sync = dynamic_cast <RPiController::SyncAlgorithm *>(
1600
+ controller_.getAlgorithm (" sync" ));
1601
+ if (sync) {
1602
+ Duration duration = (mode_.height + vblank) * ((mode_.width + hblank) * 1 .0s / mode_.pixelRate );
1603
+ LOG (IPARPI, Debug) << " setting sync frame duration to " << duration;
1604
+ sync->setFrameDuration (duration);
1605
+ }
1536
1606
}
1537
1607
1538
- void IpaBase::applyAGC (const struct AgcStatus *agcStatus, ControlList &ctrls)
1608
+ void IpaBase::applyAGC (const struct AgcStatus *agcStatus, ControlList &ctrls, Duration frameDurationOffset )
1539
1609
{
1540
1610
const int32_t minGainCode = helper_->gainCode (mode_.minAnalogueGain );
1541
1611
const int32_t maxGainCode = helper_->gainCode (mode_.maxAnalogueGain );
@@ -1550,7 +1620,8 @@ void IpaBase::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)
1550
1620
1551
1621
/* getBlanking might clip exposure time to the fps limits. */
1552
1622
Duration exposure = agcStatus->exposureTime ;
1553
- auto [vblank, hblank] = helper_->getBlanking (exposure, minFrameDuration_, maxFrameDuration_);
1623
+ auto [vblank, hblank] = helper_->getBlanking (exposure, minFrameDuration_ - frameDurationOffset,
1624
+ maxFrameDuration_ - frameDurationOffset);
1554
1625
int32_t exposureLines = helper_->exposureLines (exposure,
1555
1626
helper_->hblankToLineLength (hblank));
1556
1627
0 commit comments