summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libcamera/pipeline/ipu3/ipu3.cpp156
1 files changed, 119 insertions, 37 deletions
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 092db638..c3763507 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -29,6 +29,7 @@
#include "libcamera/internal/v4l2_controls.h"
#include "cio2.h"
+#include "frames.h"
#include "imgu.h"
namespace libcamera {
@@ -61,6 +62,8 @@ public:
void imguOutputBufferReady(FrameBuffer *buffer);
void cio2BufferReady(FrameBuffer *buffer);
+ void paramBufferReady(FrameBuffer *buffer);
+ void statBufferReady(FrameBuffer *buffer);
CIO2Device cio2_;
ImgUDevice *imgu_;
@@ -71,6 +74,7 @@ public:
uint32_t exposureTime_;
std::unique_ptr<DelayedControls> delayedCtrls_;
+ IPU3Frames frameInfos_;
private:
void queueFrameAction(unsigned int id, const IPAOperationData &op);
@@ -609,6 +613,8 @@ int PipelineHandlerIPU3::allocateBuffers(Camera *camera)
data->ipa_->mapBuffers(ipaBuffers_);
+ data->frameInfos_.init(imgu->paramBuffers_, imgu->statBuffers_);
+
return 0;
}
@@ -616,6 +622,8 @@ int PipelineHandlerIPU3::freeBuffers(Camera *camera)
{
IPU3CameraData *data = cameraData(camera);
+ data->frameInfos_.clear();
+
std::vector<unsigned int> ids;
for (IPABuffer &ipabuf : ipaBuffers_)
ids.push_back(ipabuf.id);
@@ -713,7 +721,10 @@ void PipelineHandlerIPU3::stop(Camera *camera)
int PipelineHandlerIPU3::queueRequestDevice(Camera *camera, Request *request)
{
IPU3CameraData *data = cameraData(camera);
- int error = 0;
+
+ IPU3Frames::Info *info = data->frameInfos_.create(request);
+ if (!info)
+ return -ENOBUFS;
/*
* Queue a buffer on the CIO2, using the raw stream buffer provided in
@@ -721,27 +732,20 @@ int PipelineHandlerIPU3::queueRequestDevice(Camera *camera, Request *request)
*/
FrameBuffer *reqRawBuffer = request->findBuffer(&data->rawStream_);
FrameBuffer *rawBuffer = data->cio2_.queueBuffer(request, reqRawBuffer);
- if (!rawBuffer)
+ if (!rawBuffer) {
+ data->frameInfos_.remove(info);
return -ENOMEM;
+ }
- /* Queue all buffers from the request aimed for the ImgU. */
- for (auto it : request->buffers()) {
- const Stream *stream = it.first;
- FrameBuffer *buffer = it.second;
- int ret;
-
- if (stream == &data->outStream_)
- ret = data->imgu_->output_->queueBuffer(buffer);
- else if (stream == &data->vfStream_)
- ret = data->imgu_->viewfinder_->queueBuffer(buffer);
- else
- continue;
+ info->rawBuffer = rawBuffer;
- if (ret < 0)
- error = ret;
- }
+ IPAOperationData op;
+ op.operation = IPU3_IPA_EVENT_PROCESS_CONTROLS;
+ op.data = { info->id };
+ op.controls = { request->controls() };
+ data->ipa_->processEvent(op);
- return error;
+ return 0;
}
bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)
@@ -1007,6 +1011,10 @@ int PipelineHandlerIPU3::registerCameras()
&IPU3CameraData::imguOutputBufferReady);
data->imgu_->viewfinder_->bufferReady.connect(data.get(),
&IPU3CameraData::imguOutputBufferReady);
+ data->imgu_->param_->bufferReady.connect(data.get(),
+ &IPU3CameraData::paramBufferReady);
+ data->imgu_->stat_->bufferReady.connect(data.get(),
+ &IPU3CameraData::statBufferReady);
/* Create and register the Camera instance. */
std::string cameraId = cio2->sensor()->id();
@@ -1039,7 +1047,7 @@ int IPU3CameraData::loadIPA()
return 0;
}
-void IPU3CameraData::queueFrameAction([[maybe_unused]] unsigned int id,
+void IPU3CameraData::queueFrameAction(unsigned int id,
const IPAOperationData &action)
{
switch (action.operation) {
@@ -1048,6 +1056,41 @@ void IPU3CameraData::queueFrameAction([[maybe_unused]] unsigned int id,
delayedCtrls_->push(controls);
break;
}
+ case IPU3_IPA_ACTION_PARAM_FILLED: {
+ IPU3Frames::Info *info = frameInfos_.find(id);
+ if (!info)
+ break;
+
+ /* Queue all buffers from the request aimed for the ImgU. */
+ for (auto it : info->request->buffers()) {
+ const Stream *stream = it.first;
+ FrameBuffer *outbuffer = it.second;
+
+ if (stream == &outStream_)
+ imgu_->output_->queueBuffer(outbuffer);
+ else if (stream == &vfStream_)
+ imgu_->viewfinder_->queueBuffer(outbuffer);
+ }
+
+ imgu_->param_->queueBuffer(info->paramBuffer);
+ imgu_->stat_->queueBuffer(info->statBuffer);
+ imgu_->input_->queueBuffer(info->rawBuffer);
+
+ break;
+ }
+ case IPU3_IPA_ACTION_METADATA_READY: {
+ IPU3Frames::Info *info = frameInfos_.find(id);
+ if (!info)
+ break;
+
+ Request *request = info->request;
+ request->metadata() = action.controls[0];
+ info->metadataProcessed = true;
+ if (frameInfos_.tryComplete(info))
+ pipe_->completeRequest(request);
+
+ break;
+ }
default:
LOG(IPU3, Error) << "Unknown action " << action.operation;
break;
@@ -1068,11 +1111,12 @@ void IPU3CameraData::imguOutputBufferReady(FrameBuffer *buffer)
{
Request *request = buffer->request();
- if (!pipe_->completeBuffer(request, buffer))
- /* Request not completed yet, return here. */
+ pipe_->completeBuffer(request, buffer);
+
+ IPU3Frames::Info *info = frameInfos_.find(buffer);
+ if (!info)
return;
- /* Mark the request as complete. */
request->metadata().set(controls::draft::PipelineDepth, 3);
/* \todo Move the ExposureTime control to the IPA. */
request->metadata().set(controls::ExposureTime, exposureTime_);
@@ -1081,7 +1125,12 @@ void IPU3CameraData::imguOutputBufferReady(FrameBuffer *buffer)
Rectangle cropRegion = request->controls().get(controls::ScalerCrop);
request->metadata().set(controls::ScalerCrop, cropRegion);
}
- pipe_->completeRequest(request);
+
+ if (buffer->metadata().status == FrameMetadata::FrameCancelled)
+ info->metadataProcessed = true;
+
+ if (frameInfos_.tryComplete(info))
+ pipe_->completeRequest(request);
}
/**
@@ -1093,26 +1142,59 @@ void IPU3CameraData::imguOutputBufferReady(FrameBuffer *buffer)
*/
void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer)
{
- /* \todo Handle buffer failures when state is set to BufferError. */
- if (buffer->metadata().status == FrameMetadata::FrameCancelled)
+ IPU3Frames::Info *info = frameInfos_.find(buffer);
+ if (!info)
return;
Request *request = buffer->request();
- /*
- * If the request contains a buffer for the RAW stream only, complete it
- * now as there's no need for ImgU processing.
- */
- if (request->findBuffer(&rawStream_)) {
- bool isComplete = pipe_->completeBuffer(request, buffer);
- if (isComplete) {
- request->metadata().set(controls::draft::PipelineDepth, 2);
- pipe_->completeRequest(request);
- return;
- }
+ /* If the buffer is cancelled force a complete of the whole request. */
+ if (buffer->metadata().status == FrameMetadata::FrameCancelled) {
+ for (auto it : request->buffers())
+ pipe_->completeBuffer(request, it.second);
+
+ frameInfos_.remove(info);
+ pipe_->completeRequest(request);
+ return;
+ }
+
+ if (request->findBuffer(&rawStream_))
+ pipe_->completeBuffer(request, buffer);
+
+ IPAOperationData op;
+ op.operation = IPU3_IPA_EVENT_FILL_PARAMS;
+ op.data = { info->id, info->paramBuffer->cookie() };
+ ipa_->processEvent(op);
+}
+
+void IPU3CameraData::paramBufferReady(FrameBuffer *buffer)
+{
+ IPU3Frames::Info *info = frameInfos_.find(buffer);
+ if (!info)
+ return;
+
+ info->paramDequeued = true;
+ if (frameInfos_.tryComplete(info))
+ pipe_->completeRequest(buffer->request());
+}
+
+void IPU3CameraData::statBufferReady(FrameBuffer *buffer)
+{
+ IPU3Frames::Info *info = frameInfos_.find(buffer);
+ if (!info)
+ return;
+
+ if (buffer->metadata().status == FrameMetadata::FrameCancelled) {
+ info->metadataProcessed = true;
+ if (frameInfos_.tryComplete(info))
+ pipe_->completeRequest(buffer->request());
+ return;
}
- imgu_->input_->queueBuffer(buffer);
+ IPAOperationData op;
+ op.operation = IPU3_IPA_EVENT_STAT_READY;
+ op.data = { info->id, info->statBuffer->cookie() };
+ ipa_->processEvent(op);
}
REGISTER_PIPELINE_HANDLER(PipelineHandlerIPU3)