@@ -1531,4 +1531,88 @@ void CameraData::fillRequestMetadata(const ControlList &bufferControls, Request
15311531 }
15321532}
15331533
1534+ static bool isControlDelayed (unsigned int id)
1535+ {
1536+ return id == controls::ExposureTime ||
1537+ id == controls::AnalogueGain ||
1538+ id == controls::FrameDurationLimits ||
1539+ id == controls::AeEnable ||
1540+ id == controls::ExposureTimeMode ||
1541+ id == controls::AnalogueGainMode;
1542+ }
1543+
1544+ void CameraData::handleControlLists (uint32_t delayContext)
1545+ {
1546+ /*
1547+ * If any control lists have been queued for us, merge them into the
1548+ * next request that we're going to process. This route saves controls
1549+ * from being queued always with the last request, meaning they get
1550+ * picked up here more quickly.
1551+ */
1552+ Request *request = requestQueue_.front ();
1553+ if (!controlsQueue_.empty ()) {
1554+ request->controls ().merge (std::move (controlsQueue_.front ()),
1555+ ControlList::MergePolicy::OverwriteExisting);
1556+ controlsQueue_.pop ();
1557+ controlListId_++;
1558+ LOG (RPI, Debug) << " Popped control list " << controlListId_ << " from queue" ;
1559+ }
1560+
1561+ /*
1562+ * Record which control list corresponds to this ipaCookie. Because setDelayedControls
1563+ * now gets called by the IPA from the start of the following frame, we must record
1564+ * the previous control list id.
1565+ */
1566+ syncTable_.emplace (SyncTableEntry{ request->sequence (), controlListId_ });
1567+ LOG (RPI, Debug) << " Add sync table entry: sequence " << request->sequence ()
1568+ << " control list id " << controlListId_;
1569+
1570+ /*
1571+ * We know we that we added an entry for every delayContext, so we can
1572+ * find the one for this Bayer frame, and this links us to the correct
1573+ * control list. Anything ahead of "our" entry in the queue is old, so
1574+ * can be dropped.
1575+ */
1576+ while (!syncTable_.empty () &&
1577+ syncTable_.front ().ipaCookie != delayContext) {
1578+ LOG (RPI, Debug) << " Pop sync entry: ipa cookie "
1579+ << syncTable_.front ().ipaCookie << " control id "
1580+ << syncTable_.front ().controlListId << " for job "
1581+ << delayContext;
1582+ syncTable_.pop ();
1583+ }
1584+
1585+ if (syncTable_.empty ())
1586+ LOG (RPI, Warning) << " Unable to find ipa cookie for PFC" ;
1587+ else {
1588+ LOG (RPI, Debug) << " Using sync control id " << syncTable_.front ().controlListId ;
1589+ requestControlId_ = syncTable_.front ().controlListId ;
1590+ }
1591+
1592+ /* The control list id is reported as the "ControlListSequence" in the metadata. */
1593+ request->_d ()->metadata ().set (controls::rpi::ControlListSequence, requestControlId_);
1594+
1595+ /*
1596+ * Controls that take effect immediately (typically ISP controls) have to be
1597+ * delayed so as to synchronise with those controls that do get delayed. So we
1598+ * must remove them from the current request, and push them onto a queue so
1599+ * that they can be used later.
1600+ */
1601+ ControlList controls = std::move (request->controls ());
1602+ immediateControls_.push ({ controlListId_, request->controls () });
1603+ for (const auto &ctrl : controls) {
1604+ if (isControlDelayed (ctrl.first ))
1605+ request->controls ().set (ctrl.first , ctrl.second );
1606+ else
1607+ immediateControls_.back ().controls .set (ctrl.first , ctrl.second );
1608+ }
1609+ /* "Immediate" controls that have become due are now merged back into this request. */
1610+ while (!immediateControls_.empty () &&
1611+ immediateControls_.front ().controlListId <= requestControlId_) {
1612+ request->controls ().merge (immediateControls_.front ().controls ,
1613+ ControlList::MergePolicy::OverwriteExisting);
1614+ immediateControls_.pop ();
1615+ }
1616+ }
1617+
15341618} /* namespace libcamera */
0 commit comments