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>
This commit is contained in:
parent
125be3436a
commit
5e7c5d64a6
1 changed files with 41 additions and 10 deletions
|
@ -8,6 +8,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <queue>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <linux/media-bus-format.h>
|
#include <linux/media-bus-format.h>
|
||||||
|
@ -118,6 +119,9 @@ public:
|
||||||
int allocateBuffers();
|
int allocateBuffers();
|
||||||
void freeBuffers();
|
void freeBuffers();
|
||||||
|
|
||||||
|
FrameBuffer *getBuffer();
|
||||||
|
void putBuffer(FrameBuffer *buffer);
|
||||||
|
|
||||||
int start();
|
int start();
|
||||||
int stop();
|
int stop();
|
||||||
|
|
||||||
|
@ -129,6 +133,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::unique_ptr<FrameBuffer>> buffers_;
|
std::vector<std::unique_ptr<FrameBuffer>> buffers_;
|
||||||
|
std::queue<FrameBuffer *> availableBuffers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IPU3Stream : public Stream
|
class IPU3Stream : public Stream
|
||||||
|
@ -716,11 +721,21 @@ void PipelineHandlerIPU3::stop(Camera *camera)
|
||||||
|
|
||||||
int PipelineHandlerIPU3::queueRequestDevice(Camera *camera, Request *request)
|
int PipelineHandlerIPU3::queueRequestDevice(Camera *camera, Request *request)
|
||||||
{
|
{
|
||||||
|
IPU3CameraData *data = cameraData(camera);
|
||||||
|
FrameBuffer *buffer;
|
||||||
int error = 0;
|
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()) {
|
for (auto it : request->buffers()) {
|
||||||
IPU3Stream *stream = static_cast<IPU3Stream *>(it.first);
|
IPU3Stream *stream = static_cast<IPU3Stream *>(it.first);
|
||||||
FrameBuffer *buffer = it.second;
|
buffer = it.second;
|
||||||
|
|
||||||
int ret = stream->device_->dev->queueBuffer(buffer);
|
int ret = stream->device_->dev->queueBuffer(buffer);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -892,7 +907,7 @@ void IPU3CameraData::imguInputBufferReady(FrameBuffer *buffer)
|
||||||
if (buffer->metadata().status == FrameMetadata::FrameCancelled)
|
if (buffer->metadata().status == FrameMetadata::FrameCancelled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cio2_.output_->queueBuffer(buffer);
|
cio2_.putBuffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1416,29 +1431,45 @@ int CIO2Device::allocateBuffers()
|
||||||
{
|
{
|
||||||
int ret = output_->allocateBuffers(CIO2_BUFFER_COUNT, &buffers_);
|
int ret = output_->allocateBuffers(CIO2_BUFFER_COUNT, &buffers_);
|
||||||
if (ret < 0)
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CIO2Device::freeBuffers()
|
void CIO2Device::freeBuffers()
|
||||||
{
|
{
|
||||||
|
availableBuffers_ = {};
|
||||||
|
|
||||||
buffers_.clear();
|
buffers_.clear();
|
||||||
|
|
||||||
if (output_->releaseBuffers())
|
if (output_->releaseBuffers())
|
||||||
LOG(IPU3, Error) << "Failed to release CIO2 buffers";
|
LOG(IPU3, Error) << "Failed to release CIO2 buffers";
|
||||||
}
|
}
|
||||||
|
|
||||||
int CIO2Device::start()
|
FrameBuffer *CIO2Device::getBuffer()
|
||||||
{
|
{
|
||||||
for (const std::unique_ptr<FrameBuffer> &buffer : buffers_) {
|
if (availableBuffers_.empty()) {
|
||||||
int ret = output_->queueBuffer(buffer.get());
|
LOG(IPU3, Error) << "CIO2 buffer underrun";
|
||||||
if (ret) {
|
return nullptr;
|
||||||
LOG(IPU3, Error) << "Failed to queue CIO2 buffer";
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FrameBuffer *buffer = availableBuffers_.front();
|
||||||
|
|
||||||
|
availableBuffers_.pop();
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO2Device::putBuffer(FrameBuffer *buffer)
|
||||||
|
{
|
||||||
|
availableBuffers_.push(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CIO2Device::start()
|
||||||
|
{
|
||||||
return output_->streamOn();
|
return output_->streamOn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue