@@ -83,12 +83,14 @@ public:
Signal<FrameBuffer *> inputBufferReady;
Signal<FrameBuffer *> outputBufferReady;
Signal<uint32_t, uint32_t> ispStatsReady;
+ Signal<uint32_t, const ControlList &> metadataReady;
Signal<const ControlList &> setSensorControls;
private:
void saveIspParams();
void setSensorCtrls(const ControlList &sensorControls);
void statsReady(uint32_t frame, uint32_t bufferId);
+ void saveMetadata(uint32_t frame, const ControlList &metadata);
void inputReady(FrameBuffer *input);
void outputReady(FrameBuffer *output);
@@ -33,4 +33,5 @@ interface IPASoftInterface {
interface IPASoftEventInterface {
setSensorControls(libcamera.ControlList sensorControls);
setIspParams();
+ metadataReady(uint32 frame, libcamera.ControlList metadata);
};
@@ -295,15 +295,10 @@ void IPASoftSimple::processStats(const uint32_t frame,
int32_t again = sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>();
frameContext.sensor.gain = camHelper_ ? camHelper_->gain(again) : again;
- /*
- * Software ISP currently does not produce any metadata. Use an empty
- * ControlList for now.
- *
- * \todo Implement proper metadata handling
- */
ControlList metadata(controls::controls);
for (auto const &algo : algorithms())
algo->process(context_, frame, frameContext, stats_, metadata);
+ metadataReady.emit(frame, metadata);
/* Sanity check */
if (!sensorControls.contains(V4L2_CID_EXPOSURE) ||
@@ -184,6 +184,7 @@ class SimplePipelineHandler;
struct SimpleFrameInfo {
uint32_t frame;
Request *request;
+ bool metadataProcessed;
};
class SimpleFrames
@@ -207,6 +208,7 @@ void SimpleFrames::create(Request *request)
ASSERT(inserted);
it->second.frame = frame;
it->second.request = request;
+ it->second.metadataProcessed = false;
}
void SimpleFrames::destroy(uint32_t frame)
@@ -357,11 +359,13 @@ private:
void tryPipeline(unsigned int code, const Size &size);
static std::vector<const MediaPad *> routedSourcePads(MediaPad *sink);
+ void tryCompleteRequest(Request *request);
void completeRequest(Request *request);
void conversionInputDone(FrameBuffer *buffer);
void conversionOutputDone(FrameBuffer *buffer);
void ispStatsReady(uint32_t frame, uint32_t bufferId);
+ void metadataReady(uint32_t frame, const ControlList &metadata);
void setSensorControls(const ControlList &sensorControls);
};
@@ -614,6 +618,7 @@ int SimpleCameraData::init()
});
swIsp_->outputBufferReady.connect(this, &SimpleCameraData::conversionOutputDone);
swIsp_->ispStatsReady.connect(this, &SimpleCameraData::ispStatsReady);
+ swIsp_->metadataReady.connect(this, &SimpleCameraData::metadataReady);
swIsp_->setSensorControls.connect(this, &SimpleCameraData::setSensorControls);
}
}
@@ -946,6 +951,21 @@ void SimpleCameraData::clearIncompleteRequests()
}
}
+void SimpleCameraData::tryCompleteRequest(Request *request)
+{
+ if (request->hasPendingBuffers())
+ return;
+
+ SimpleFrameInfo *info = frameInfo_.find(request);
+ if (!info)
+ return;
+
+ if (!info->metadataProcessed)
+ return;
+
+ completeRequest(request);
+}
+
void SimpleCameraData::completeRequest(Request *request)
{
SimpleFrameInfo *info = frameInfo_.find(request);
@@ -971,7 +991,7 @@ void SimpleCameraData::conversionOutputDone(FrameBuffer *buffer)
/* Complete the buffer and the request. */
Request *request = buffer->request();
if (pipe->completeBuffer(request, buffer))
- completeRequest(request);
+ tryCompleteRequest(request);
}
void SimpleCameraData::ispStatsReady(uint32_t frame, uint32_t bufferId)
@@ -980,6 +1000,17 @@ void SimpleCameraData::ispStatsReady(uint32_t frame, uint32_t bufferId)
delayedCtrls_->get(frame));
}
+void SimpleCameraData::metadataReady(uint32_t frame, const ControlList &metadata)
+{
+ SimpleFrameInfo *info = frameInfo_.find(frame);
+ if (!info)
+ return;
+
+ info->request->metadata().merge(metadata);
+ info->metadataProcessed = true;
+ tryCompleteRequest(info->request);
+}
+
void SimpleCameraData::setSensorControls(const ControlList &sensorControls)
{
delayedCtrls_->push(sensorControls);
@@ -51,6 +51,11 @@ LOG_DEFINE_CATEGORY(SoftwareIsp)
* \brief A signal emitted when the statistics for IPA are ready
*/
+/**
+ * \var SoftwareIsp::metadataReady
+ * \brief A signal emitted when the metadata for IPA is ready
+ */
+
/**
* \var SoftwareIsp::setSensorControls
* \brief A signal emitted when the values to write to the sensor controls are
@@ -136,6 +141,10 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor,
}
ipa_->setIspParams.connect(this, &SoftwareIsp::saveIspParams);
+ ipa_->metadataReady.connect(this,
+ [this](uint32_t frame, const ControlList &metadata) {
+ metadataReady.emit(frame, metadata);
+ });
ipa_->setSensorControls.connect(this, &SoftwareIsp::setSensorCtrls);
debayer_->moveToThread(&ispWorkerThread_);