libcamera: pipeline: ipu3: Switch to FrameBuffer interface for cio2 and stat

The V4L2VideoDevice class can now operate using a FrameBuffer interface,
switch the IPU3 CIO2 and statistics buffer to use it. We can not convert
the application-facing buffers yet.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
Niklas Söderlund
2019-12-19 00:28:34 +01:00
parent 3109843cda
commit 6c69bf982e

View File

@@ -45,6 +45,7 @@ public:
unsigned int pad;
std::string name;
BufferPool *pool;
std::vector<std::unique_ptr<FrameBuffer>> buffers;
};
ImgUDevice()
@@ -70,7 +71,6 @@ public:
int configureOutput(ImgUOutput *output,
const StreamConfiguration &cfg);
int importInputBuffers(BufferPool *pool);
int importOutputBuffers(ImgUOutput *output, BufferPool *pool);
int exportOutputBuffers(ImgUOutput *output, BufferPool *pool);
void freeBuffers();
@@ -95,7 +95,6 @@ public:
/* \todo Add param video device for 3A tuning */
BufferPool vfPool_;
BufferPool statPool_;
BufferPool outPool_;
};
@@ -120,10 +119,10 @@ public:
int configure(const Size &size,
V4L2DeviceFormat *outputFormat);
BufferPool *exportBuffers();
int allocateBuffers();
void freeBuffers();
int start(std::vector<std::unique_ptr<Buffer>> *buffers);
int start();
int stop();
static int mediaBusToFormat(unsigned int code);
@@ -132,7 +131,8 @@ public:
V4L2Subdevice *csi2_;
CameraSensor *sensor_;
BufferPool pool_;
private:
std::vector<std::unique_ptr<FrameBuffer>> buffers_;
};
class IPU3Stream : public Stream
@@ -157,16 +157,14 @@ public:
}
void imguOutputBufferReady(Buffer *buffer);
void imguInputBufferReady(Buffer *buffer);
void cio2BufferReady(Buffer *buffer);
void imguInputBufferReady(FrameBuffer *buffer);
void cio2BufferReady(FrameBuffer *buffer);
CIO2Device cio2_;
ImgUDevice *imgu_;
IPU3Stream outStream_;
IPU3Stream vfStream_;
std::vector<std::unique_ptr<Buffer>> rawBuffers_;
};
class IPU3CameraConfiguration : public CameraConfiguration
@@ -638,24 +636,28 @@ int PipelineHandlerIPU3::allocateBuffers(Camera *camera,
int ret;
/* Share buffers between CIO2 output and ImgU input. */
BufferPool *pool = cio2->exportBuffers();
if (!pool)
return -ENOMEM;
ret = cio2->allocateBuffers();
if (ret < 0)
return ret;
ret = imgu->importInputBuffers(pool);
if (ret)
bufferCount = ret;
ret = imgu->input_->importBuffers(bufferCount);
if (ret) {
LOG(IPU3, Error) << "Failed to import ImgU input buffers";
goto error;
}
/*
* Use for the stat's internal pool the same number of buffer as
* for the input pool.
* Use for the stat's internal pool the same number of buffers as for
* the input pool.
* \todo To be revised when we'll actually use the stat node.
*/
bufferCount = pool->count();
imgu->stat_.pool->createBuffers(bufferCount);
ret = imgu->exportOutputBuffers(&imgu->stat_, imgu->stat_.pool);
if (ret)
ret = imgu->stat_.dev->exportBuffers(bufferCount, &imgu->stat_.buffers);
if (ret < 0) {
LOG(IPU3, Error) << "Failed to allocate ImgU stat buffers";
goto error;
}
/* Allocate buffers for each active stream. */
for (Stream *s : streams) {
@@ -722,7 +724,7 @@ int PipelineHandlerIPU3::start(Camera *camera)
* Start the ImgU video devices, buffers will be queued to the
* ImgU output and viewfinder when requests will be queued.
*/
ret = cio2->start(&data->rawBuffers_);
ret = cio2->start();
if (ret)
goto error;
@@ -738,7 +740,6 @@ int PipelineHandlerIPU3::start(Camera *camera)
error:
LOG(IPU3, Error) << "Failed to start camera " << camera->name();
data->rawBuffers_.clear();
return ret;
}
@@ -752,8 +753,6 @@ void PipelineHandlerIPU3::stop(Camera *camera)
if (ret)
LOG(IPU3, Warning) << "Failed to stop camera "
<< camera->name();
data->rawBuffers_.clear();
}
int PipelineHandlerIPU3::queueRequestDevice(Camera *camera, Request *request)
@@ -885,9 +884,9 @@ int PipelineHandlerIPU3::registerCameras()
* associated ImgU input where they get processed and
* returned through the ImgU main and secondary outputs.
*/
data->cio2_.output_->bufferReady.connect(data.get(),
data->cio2_.output_->frameBufferReady.connect(data.get(),
&IPU3CameraData::cio2BufferReady);
data->imgu_->input_->bufferReady.connect(data.get(),
data->imgu_->input_->frameBufferReady.connect(data.get(),
&IPU3CameraData::imguInputBufferReady);
data->imgu_->output_.dev->bufferReady.connect(data.get(),
&IPU3CameraData::imguOutputBufferReady);
@@ -925,7 +924,7 @@ int PipelineHandlerIPU3::registerCameras()
* Buffers completed from the ImgU input are immediately queued back to the
* CIO2 unit to continue frame capture.
*/
void IPU3CameraData::imguInputBufferReady(Buffer *buffer)
void IPU3CameraData::imguInputBufferReady(FrameBuffer *buffer)
{
/* \todo Handle buffer failures when state is set to BufferError. */
if (buffer->metadata().status == FrameMetadata::FrameCancelled)
@@ -959,7 +958,7 @@ void IPU3CameraData::imguOutputBufferReady(Buffer *buffer)
* Buffers completed from the CIO2 are immediately queued to the ImgU unit
* for further processing.
*/
void IPU3CameraData::cio2BufferReady(Buffer *buffer)
void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer)
{
/* \todo Handle buffer failures when state is set to BufferError. */
if (buffer->metadata().status == FrameMetadata::FrameCancelled)
@@ -1034,7 +1033,6 @@ int ImgUDevice::init(MediaDevice *media, unsigned int index)
stat_.pad = PAD_STAT;
stat_.name = "stat";
stat_.pool = &statPool_;
return 0;
}
@@ -1134,22 +1132,6 @@ int ImgUDevice::configureOutput(ImgUOutput *output,
return 0;
}
/**
* \brief Import buffers from \a pool into the ImgU input
* \param[in] pool The buffer pool to import
* \return 0 on success or a negative error code otherwise
*/
int ImgUDevice::importInputBuffers(BufferPool *pool)
{
int ret = input_->importBuffers(pool);
if (ret) {
LOG(IPU3, Error) << "Failed to import ImgU input buffers";
return ret;
}
return 0;
}
/**
* \brief Export buffers from \a output to the provided \a pool
* \param[in] output The ImgU output device
@@ -1448,37 +1430,40 @@ int CIO2Device::configure(const Size &size,
}
/**
* \brief Allocate CIO2 memory buffers and export them in a BufferPool
* \brief Allocate frame buffers for the CIO2 output
*
* Allocate memory buffers in the CIO2 video device and export them to
* a buffer pool that can be imported by another device.
* Allocate frame buffers in the CIO2 video device to be used to capture frames
* from the CIO2 output. The buffers are stored in the CIO2Device::buffers_
* vector.
*
* \return The buffer pool with export buffers on success or nullptr otherwise
* \return Number of buffers allocated or negative error code
*/
BufferPool *CIO2Device::exportBuffers()
int CIO2Device::allocateBuffers()
{
pool_.createBuffers(CIO2_BUFFER_COUNT);
int ret = output_->exportBuffers(&pool_);
if (ret) {
int ret = output_->exportBuffers(CIO2_BUFFER_COUNT, &buffers_);
if (ret < 0)
LOG(IPU3, Error) << "Failed to export CIO2 buffers";
return nullptr;
}
return &pool_;
return ret;
}
void CIO2Device::freeBuffers()
{
buffers_.clear();
if (output_->releaseBuffers())
LOG(IPU3, Error) << "Failed to release CIO2 buffers";
}
int CIO2Device::start(std::vector<std::unique_ptr<Buffer>> *buffers)
int CIO2Device::start()
{
*buffers = output_->queueAllBuffers();
if (buffers->empty())
return -EINVAL;
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;
}
}
return output_->streamOn();
}