summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNiklas Söderlund <niklas.soderlund@ragnatech.se>2020-03-16 00:47:45 +0100
committerNiklas Söderlund <niklas.soderlund@ragnatech.se>2020-03-27 16:27:28 +0100
commit5e7c5d64a67f5821d3dbb75c093626df514ee029 (patch)
tree7233f563ab6fffd935ce54b88f14c427a888fccb /src
parent125be3436ae095413b90f00c7516efba8964d061 (diff)
libcamera: ipu3: Do not unconditionally queue buffers to CIO2
Instead of unconditionally cycling buffers between the CIO2 and IMGU pick a buffer when a request is queued to the pipeline. This is needed if operations are to be applied to the buffer coming from CIO2 with parameters coming from a Request. The approach to pick a CIO2 buffer when a request is queued is similar to other pipelines, where parameters and statistic buffers are picked this way. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'src')
-rw-r--r--src/libcamera/pipeline/ipu3/ipu3.cpp51
1 files changed, 41 insertions, 10 deletions
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 1b44460e..0933a03c 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -8,6 +8,7 @@
#include <algorithm>
#include <iomanip>
#include <memory>
+#include <queue>
#include <vector>
#include <linux/media-bus-format.h>
@@ -118,6 +119,9 @@ public:
int allocateBuffers();
void freeBuffers();
+ FrameBuffer *getBuffer();
+ void putBuffer(FrameBuffer *buffer);
+
int start();
int stop();
@@ -129,6 +133,7 @@ public:
private:
std::vector<std::unique_ptr<FrameBuffer>> buffers_;
+ std::queue<FrameBuffer *> availableBuffers_;
};
class IPU3Stream : public Stream
@@ -716,11 +721,21 @@ void PipelineHandlerIPU3::stop(Camera *camera)
int PipelineHandlerIPU3::queueRequestDevice(Camera *camera, Request *request)
{
+ IPU3CameraData *data = cameraData(camera);
+ FrameBuffer *buffer;
int error = 0;
+ /* Get a CIO2 buffer, associate it with the request and queue it. */
+ buffer = data->cio2_.getBuffer();
+ if (!buffer)
+ return -EINVAL;
+
+ buffer->setRequest(request);
+ data->cio2_.output_->queueBuffer(buffer);
+
for (auto it : request->buffers()) {
IPU3Stream *stream = static_cast<IPU3Stream *>(it.first);
- FrameBuffer *buffer = it.second;
+ buffer = it.second;
int ret = stream->device_->dev->queueBuffer(buffer);
if (ret < 0)
@@ -892,7 +907,7 @@ void IPU3CameraData::imguInputBufferReady(FrameBuffer *buffer)
if (buffer->metadata().status == FrameMetadata::FrameCancelled)
return;
- cio2_.output_->queueBuffer(buffer);
+ cio2_.putBuffer(buffer);
}
/**
@@ -1416,29 +1431,45 @@ int CIO2Device::allocateBuffers()
{
int ret = output_->allocateBuffers(CIO2_BUFFER_COUNT, &buffers_);
if (ret < 0)
- LOG(IPU3, Error) << "Failed to allocate CIO2 buffers";
+ return ret;
+
+ for (std::unique_ptr<FrameBuffer> &buffer : buffers_)
+ availableBuffers_.push(buffer.get());
return ret;
}
void CIO2Device::freeBuffers()
{
+ availableBuffers_ = {};
+
buffers_.clear();
if (output_->releaseBuffers())
LOG(IPU3, Error) << "Failed to release CIO2 buffers";
}
-int CIO2Device::start()
+FrameBuffer *CIO2Device::getBuffer()
{
- for (const std::unique_ptr<FrameBuffer> &buffer : buffers_) {
- int ret = output_->queueBuffer(buffer.get());
- if (ret) {
- LOG(IPU3, Error) << "Failed to queue CIO2 buffer";
- return ret;
- }
+ if (availableBuffers_.empty()) {
+ LOG(IPU3, Error) << "CIO2 buffer underrun";
+ return nullptr;
}
+ FrameBuffer *buffer = availableBuffers_.front();
+
+ availableBuffers_.pop();
+
+ return buffer;
+}
+
+void CIO2Device::putBuffer(FrameBuffer *buffer)
+{
+ availableBuffers_.push(buffer);
+}
+
+int CIO2Device::start()
+{
return output_->streamOn();
}