summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libcamera/internal/software_isp/software_isp.h1
-rw-r--r--include/libcamera/ipa/soft.mojom1
-rw-r--r--src/ipa/simple/soft_simple.cpp7
-rw-r--r--src/libcamera/pipeline/simple/simple.cpp48
-rw-r--r--src/libcamera/software_isp/software_isp.cpp9
5 files changed, 48 insertions, 18 deletions
diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h
index 0026cec2..78624659 100644
--- a/include/libcamera/internal/software_isp/software_isp.h
+++ b/include/libcamera/internal/software_isp/software_isp.h
@@ -85,6 +85,7 @@ public:
Signal<FrameBuffer *> inputBufferReady;
Signal<FrameBuffer *> outputBufferReady;
Signal<uint32_t, uint32_t> ispStatsReady;
+ Signal<uint32_t, const ControlList &> metadataReady;
Signal<const ControlList &> setSensorControls;
private:
diff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom
index ede74413..a8e6ecda 100644
--- a/include/libcamera/ipa/soft.mojom
+++ b/include/libcamera/ipa/soft.mojom
@@ -33,4 +33,5 @@ interface IPASoftInterface {
interface IPASoftEventInterface {
setSensorControls(libcamera.ControlList sensorControls);
setIspParams();
+ metadataReady(uint32 frame, libcamera.ControlList metadata);
};
diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp
index a87c6cdd..4ef67c43 100644
--- a/src/ipa/simple/soft_simple.cpp
+++ b/src/ipa/simple/soft_simple.cpp
@@ -299,15 +299,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) ||
diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
index 004a8d53..fd0ccdca 100644
--- a/src/libcamera/pipeline/simple/simple.cpp
+++ b/src/libcamera/pipeline/simple/simple.cpp
@@ -182,19 +182,21 @@ LOG_DEFINE_CATEGORY(SimplePipeline)
class SimplePipelineHandler;
struct SimpleFrameInfo {
- SimpleFrameInfo(uint32_t f, Request *r)
- : frame(f), request(r)
+ SimpleFrameInfo(uint32_t f, Request *r, bool m)
+ : frame(f), request(r), metadataRequired(m), metadataProcessed(false)
{
}
uint32_t frame;
Request *request;
+ bool metadataRequired;
+ bool metadataProcessed;
};
class SimpleFrames
{
public:
- void create(Request *request);
+ void create(Request *request, bool metadataRequested);
void destroy(uint32_t frame);
void clear();
@@ -204,10 +206,10 @@ private:
std::map<uint32_t, SimpleFrameInfo> frameInfo_;
};
-void SimpleFrames::create(Request *request)
+void SimpleFrames::create(Request *request, bool metadataRequired)
{
const uint32_t frame = request->sequence();
- auto [it, inserted] = frameInfo_.try_emplace(frame, frame, request);
+ auto [it, inserted] = frameInfo_.try_emplace(frame, frame, request, metadataRequired);
ASSERT(inserted);
}
@@ -347,11 +349,12 @@ private:
void tryPipeline(unsigned int code, const Size &size);
static std::vector<const MediaPad *> routedSourcePads(MediaPad *sink);
- void completeRequest(Request *request);
+ void tryCompleteRequest(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);
};
@@ -590,6 +593,7 @@ int SimpleCameraData::init()
swIsp_->inputBufferReady.connect(this, &SimpleCameraData::conversionInputDone);
swIsp_->outputBufferReady.connect(this, &SimpleCameraData::conversionOutputDone);
swIsp_->ispStatsReady.connect(this, &SimpleCameraData::ispStatsReady);
+ swIsp_->metadataReady.connect(this, &SimpleCameraData::metadataReady);
swIsp_->setSensorControls.connect(this, &SimpleCameraData::setSensorControls);
}
}
@@ -835,7 +839,7 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)
/* No conversion, just complete the request. */
Request *request = buffer->request();
pipe->completeBuffer(request, buffer);
- completeRequest(request);
+ tryCompleteRequest(request);
return;
}
@@ -853,7 +857,10 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)
const RequestOutputs &outputs = conversionQueue_.front();
for (auto &[stream, buf] : outputs.outputs)
pipe->completeBuffer(outputs.request, buf);
- completeRequest(outputs.request);
+ SimpleFrameInfo *info = frameInfo_.find(outputs.request->sequence());
+ if (info)
+ info->metadataRequired = false;
+ tryCompleteRequest(outputs.request);
conversionQueue_.pop();
return;
@@ -911,7 +918,7 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)
/* Otherwise simply complete the request. */
pipe->completeBuffer(request, buffer);
- completeRequest(request);
+ tryCompleteRequest(request);
}
void SimpleCameraData::clearIncompleteRequests()
@@ -922,14 +929,20 @@ void SimpleCameraData::clearIncompleteRequests()
}
}
-void SimpleCameraData::completeRequest(Request *request)
+void SimpleCameraData::tryCompleteRequest(Request *request)
{
+ if (request->hasPendingBuffers())
+ return;
+
SimpleFrameInfo *info = frameInfo_.find(request->sequence());
if (!info) {
/* Something is really wrong, let's return. */
return;
}
+ if (info->metadataRequired && !info->metadataProcessed)
+ return;
+
frameInfo_.destroy(info->frame);
pipe()->completeRequest(request);
}
@@ -947,7 +960,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)
@@ -956,6 +969,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);
@@ -1489,7 +1513,7 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request)
}
}
- data->frameInfo_.create(request);
+ data->frameInfo_.create(request, !!data->swIsp_);
if (data->useConversion_) {
data->conversionQueue_.push({ request, std::move(buffers) });
if (data->swIsp_)
diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp
index 4a74dcb6..6baa3fec 100644
--- a/src/libcamera/software_isp/software_isp.cpp
+++ b/src/libcamera/software_isp/software_isp.cpp
@@ -56,6 +56,11 @@ LOG_DEFINE_CATEGORY(SoftwareIsp)
*/
/**
+ * \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
* ready
@@ -141,6 +146,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_);