libcamera: ipu3: cio2: Move the CIO2Device class to separate files
In preparation of refactoring the IPU3 pipeline handler breakout the CIO2Device into its own .cpp and .h file, no functional change. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
2cd9556021
commit
6bd3d7259f
4 changed files with 294 additions and 247 deletions
236
src/libcamera/pipeline/ipu3/cio2.cpp
Normal file
236
src/libcamera/pipeline/ipu3/cio2.cpp
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019, Google Inc.
|
||||||
|
*
|
||||||
|
* cio2.cpp - Intel IPU3 CIO2
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cio2.h"
|
||||||
|
|
||||||
|
#include <linux/media-bus-format.h>
|
||||||
|
|
||||||
|
#include "libcamera/internal/camera_sensor.h"
|
||||||
|
#include "libcamera/internal/media_device.h"
|
||||||
|
#include "libcamera/internal/v4l2_subdevice.h"
|
||||||
|
#include "libcamera/internal/v4l2_videodevice.h"
|
||||||
|
|
||||||
|
namespace libcamera {
|
||||||
|
|
||||||
|
LOG_DECLARE_CATEGORY(IPU3)
|
||||||
|
|
||||||
|
CIO2Device::CIO2Device()
|
||||||
|
: output_(nullptr), csi2_(nullptr), sensor_(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CIO2Device::~CIO2Device()
|
||||||
|
{
|
||||||
|
delete output_;
|
||||||
|
delete csi2_;
|
||||||
|
delete sensor_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initialize components of the CIO2 device with \a index
|
||||||
|
* \param[in] media The CIO2 media device
|
||||||
|
* \param[in] index The CIO2 device index
|
||||||
|
*
|
||||||
|
* Create and open the video device and subdevices in the CIO2 instance at \a
|
||||||
|
* index, if a supported image sensor is connected to the CSI-2 receiver of
|
||||||
|
* this CIO2 instance. Enable the media links connecting the CIO2 components
|
||||||
|
* to prepare for capture operations and cached the sensor maximum size.
|
||||||
|
*
|
||||||
|
* \return 0 on success or a negative error code otherwise
|
||||||
|
* \retval -ENODEV No supported image sensor is connected to this CIO2 instance
|
||||||
|
*/
|
||||||
|
int CIO2Device::init(const MediaDevice *media, unsigned int index)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify that a sensor subdevice is connected to this CIO2 instance
|
||||||
|
* and enable the media link between the two.
|
||||||
|
*/
|
||||||
|
std::string csi2Name = "ipu3-csi2 " + std::to_string(index);
|
||||||
|
MediaEntity *csi2Entity = media->getEntityByName(csi2Name);
|
||||||
|
const std::vector<MediaPad *> &pads = csi2Entity->pads();
|
||||||
|
if (pads.empty())
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
/* IPU3 CSI-2 receivers have a single sink pad at index 0. */
|
||||||
|
MediaPad *sink = pads[0];
|
||||||
|
const std::vector<MediaLink *> &links = sink->links();
|
||||||
|
if (links.empty())
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
MediaLink *link = links[0];
|
||||||
|
MediaEntity *sensorEntity = link->source()->entity();
|
||||||
|
sensor_ = new CameraSensor(sensorEntity);
|
||||||
|
ret = sensor_->init();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = link->setEnabled(true);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure the sensor produces at least one format compatible with
|
||||||
|
* the CIO2 requirements.
|
||||||
|
*
|
||||||
|
* utils::set_overlap requires the ranges to be sorted, keep the
|
||||||
|
* cio2Codes vector sorted in ascending order.
|
||||||
|
*/
|
||||||
|
const std::vector<unsigned int> cio2Codes{ MEDIA_BUS_FMT_SBGGR10_1X10,
|
||||||
|
MEDIA_BUS_FMT_SGRBG10_1X10,
|
||||||
|
MEDIA_BUS_FMT_SGBRG10_1X10,
|
||||||
|
MEDIA_BUS_FMT_SRGGB10_1X10 };
|
||||||
|
const std::vector<unsigned int> &sensorCodes = sensor_->mbusCodes();
|
||||||
|
if (!utils::set_overlap(sensorCodes.begin(), sensorCodes.end(),
|
||||||
|
cio2Codes.begin(), cio2Codes.end())) {
|
||||||
|
LOG(IPU3, Error)
|
||||||
|
<< "Sensor " << sensor_->entity()->name()
|
||||||
|
<< " has not format compatible with the IPU3";
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* \todo Define when to open and close video device nodes, as they
|
||||||
|
* might impact on power consumption.
|
||||||
|
*/
|
||||||
|
|
||||||
|
csi2_ = new V4L2Subdevice(csi2Entity);
|
||||||
|
ret = csi2_->open();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
std::string cio2Name = "ipu3-cio2 " + std::to_string(index);
|
||||||
|
output_ = V4L2VideoDevice::fromEntityName(media, cio2Name);
|
||||||
|
ret = output_->open();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Configure the CIO2 unit
|
||||||
|
* \param[in] size The requested CIO2 output frame size
|
||||||
|
* \param[out] outputFormat The CIO2 unit output image format
|
||||||
|
* \return 0 on success or a negative error code otherwise
|
||||||
|
*/
|
||||||
|
int CIO2Device::configure(const Size &size, V4L2DeviceFormat *outputFormat)
|
||||||
|
{
|
||||||
|
V4L2SubdeviceFormat sensorFormat;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Apply the selected format to the sensor, the CSI-2 receiver and
|
||||||
|
* the CIO2 output device.
|
||||||
|
*/
|
||||||
|
sensorFormat = sensor_->getFormat({ MEDIA_BUS_FMT_SBGGR10_1X10,
|
||||||
|
MEDIA_BUS_FMT_SGBRG10_1X10,
|
||||||
|
MEDIA_BUS_FMT_SGRBG10_1X10,
|
||||||
|
MEDIA_BUS_FMT_SRGGB10_1X10 },
|
||||||
|
size);
|
||||||
|
ret = sensor_->setFormat(&sensorFormat);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = csi2_->setFormat(0, &sensorFormat);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
V4L2PixelFormat v4l2Format;
|
||||||
|
switch (sensorFormat.mbus_code) {
|
||||||
|
case MEDIA_BUS_FMT_SBGGR10_1X10:
|
||||||
|
v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SBGGR10);
|
||||||
|
break;
|
||||||
|
case MEDIA_BUS_FMT_SGBRG10_1X10:
|
||||||
|
v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SGBRG10);
|
||||||
|
break;
|
||||||
|
case MEDIA_BUS_FMT_SGRBG10_1X10:
|
||||||
|
v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SGRBG10);
|
||||||
|
break;
|
||||||
|
case MEDIA_BUS_FMT_SRGGB10_1X10:
|
||||||
|
v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SRGGB10);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
outputFormat->fourcc = v4l2Format;
|
||||||
|
outputFormat->size = sensorFormat.size;
|
||||||
|
outputFormat->planesCount = 1;
|
||||||
|
|
||||||
|
ret = output_->setFormat(outputFormat);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
LOG(IPU3, Debug) << "CIO2 output format " << outputFormat->toString();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Allocate frame buffers for the CIO2 output
|
||||||
|
*
|
||||||
|
* 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 Number of buffers allocated or negative error code
|
||||||
|
*/
|
||||||
|
int CIO2Device::allocateBuffers()
|
||||||
|
{
|
||||||
|
int ret = output_->allocateBuffers(CIO2_BUFFER_COUNT, &buffers_);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
for (std::unique_ptr<FrameBuffer> &buffer : buffers_)
|
||||||
|
availableBuffers_.push(buffer.get());
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO2Device::freeBuffers()
|
||||||
|
{
|
||||||
|
/* The default std::queue constructor is explicit with gcc 5 and 6. */
|
||||||
|
availableBuffers_ = std::queue<FrameBuffer *>{};
|
||||||
|
|
||||||
|
buffers_.clear();
|
||||||
|
|
||||||
|
if (output_->releaseBuffers())
|
||||||
|
LOG(IPU3, Error) << "Failed to release CIO2 buffers";
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameBuffer *CIO2Device::getBuffer()
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
int CIO2Device::stop()
|
||||||
|
{
|
||||||
|
return output_->streamOff();
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace libcamera */
|
55
src/libcamera/pipeline/ipu3/cio2.h
Normal file
55
src/libcamera/pipeline/ipu3/cio2.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019, Google Inc.
|
||||||
|
*
|
||||||
|
* cio2.h - Intel IPU3 CIO2
|
||||||
|
*/
|
||||||
|
#ifndef __LIBCAMERA_PIPELINE_IPU3_CIO2_H__
|
||||||
|
#define __LIBCAMERA_PIPELINE_IPU3_CIO2_H__
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <queue>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace libcamera {
|
||||||
|
|
||||||
|
class CameraSensor;
|
||||||
|
class FrameBuffer;
|
||||||
|
class MediaDevice;
|
||||||
|
class V4L2DeviceFormat;
|
||||||
|
class V4L2Subdevice;
|
||||||
|
class V4L2VideoDevice;
|
||||||
|
struct Size;
|
||||||
|
|
||||||
|
class CIO2Device
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr unsigned int CIO2_BUFFER_COUNT = 4;
|
||||||
|
|
||||||
|
CIO2Device();
|
||||||
|
~CIO2Device();
|
||||||
|
|
||||||
|
int init(const MediaDevice *media, unsigned int index);
|
||||||
|
int configure(const Size &size, V4L2DeviceFormat *outputFormat);
|
||||||
|
|
||||||
|
int allocateBuffers();
|
||||||
|
void freeBuffers();
|
||||||
|
|
||||||
|
FrameBuffer *getBuffer();
|
||||||
|
void putBuffer(FrameBuffer *buffer);
|
||||||
|
|
||||||
|
int start();
|
||||||
|
int stop();
|
||||||
|
|
||||||
|
V4L2VideoDevice *output_;
|
||||||
|
V4L2Subdevice *csi2_;
|
||||||
|
CameraSensor *sensor_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::unique_ptr<FrameBuffer>> buffers_;
|
||||||
|
std::queue<FrameBuffer *> availableBuffers_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace libcamera */
|
||||||
|
|
||||||
|
#endif /* __LIBCAMERA_PIPELINE_IPU3_CIO2_H__ */
|
|
@ -28,6 +28,8 @@
|
||||||
#include "libcamera/internal/v4l2_subdevice.h"
|
#include "libcamera/internal/v4l2_subdevice.h"
|
||||||
#include "libcamera/internal/v4l2_videodevice.h"
|
#include "libcamera/internal/v4l2_videodevice.h"
|
||||||
|
|
||||||
|
#include "cio2.h"
|
||||||
|
|
||||||
namespace libcamera {
|
namespace libcamera {
|
||||||
|
|
||||||
LOG_DEFINE_CATEGORY(IPU3)
|
LOG_DEFINE_CATEGORY(IPU3)
|
||||||
|
@ -104,45 +106,6 @@ public:
|
||||||
/* \todo Add param video device for 3A tuning */
|
/* \todo Add param video device for 3A tuning */
|
||||||
};
|
};
|
||||||
|
|
||||||
class CIO2Device
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static constexpr unsigned int CIO2_BUFFER_COUNT = 4;
|
|
||||||
|
|
||||||
CIO2Device()
|
|
||||||
: output_(nullptr), csi2_(nullptr), sensor_(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~CIO2Device()
|
|
||||||
{
|
|
||||||
delete output_;
|
|
||||||
delete csi2_;
|
|
||||||
delete sensor_;
|
|
||||||
}
|
|
||||||
|
|
||||||
int init(const MediaDevice *media, unsigned int index);
|
|
||||||
int configure(const Size &size,
|
|
||||||
V4L2DeviceFormat *outputFormat);
|
|
||||||
|
|
||||||
int allocateBuffers();
|
|
||||||
void freeBuffers();
|
|
||||||
|
|
||||||
FrameBuffer *getBuffer();
|
|
||||||
void putBuffer(FrameBuffer *buffer);
|
|
||||||
|
|
||||||
int start();
|
|
||||||
int stop();
|
|
||||||
|
|
||||||
V4L2VideoDevice *output_;
|
|
||||||
V4L2Subdevice *csi2_;
|
|
||||||
CameraSensor *sensor_;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<std::unique_ptr<FrameBuffer>> buffers_;
|
|
||||||
std::queue<FrameBuffer *> availableBuffers_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IPU3Stream : public Stream
|
class IPU3Stream : public Stream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -1408,214 +1371,6 @@ int ImgUDevice::enableLinks(bool enable)
|
||||||
return linkSetup(name_, PAD_STAT, statName, 0, enable);
|
return linkSetup(name_, PAD_STAT, statName, 0, enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
|
||||||
* CIO2 Device
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Initialize components of the CIO2 device with \a index
|
|
||||||
* \param[in] media The CIO2 media device
|
|
||||||
* \param[in] index The CIO2 device index
|
|
||||||
*
|
|
||||||
* Create and open the video device and subdevices in the CIO2 instance at \a
|
|
||||||
* index, if a supported image sensor is connected to the CSI-2 receiver of
|
|
||||||
* this CIO2 instance. Enable the media links connecting the CIO2 components
|
|
||||||
* to prepare for capture operations and cached the sensor maximum size.
|
|
||||||
*
|
|
||||||
* \return 0 on success or a negative error code otherwise
|
|
||||||
* \retval -ENODEV No supported image sensor is connected to this CIO2 instance
|
|
||||||
*/
|
|
||||||
int CIO2Device::init(const MediaDevice *media, unsigned int index)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Verify that a sensor subdevice is connected to this CIO2 instance
|
|
||||||
* and enable the media link between the two.
|
|
||||||
*/
|
|
||||||
std::string csi2Name = "ipu3-csi2 " + std::to_string(index);
|
|
||||||
MediaEntity *csi2Entity = media->getEntityByName(csi2Name);
|
|
||||||
const std::vector<MediaPad *> &pads = csi2Entity->pads();
|
|
||||||
if (pads.empty())
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
/* IPU3 CSI-2 receivers have a single sink pad at index 0. */
|
|
||||||
MediaPad *sink = pads[0];
|
|
||||||
const std::vector<MediaLink *> &links = sink->links();
|
|
||||||
if (links.empty())
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
MediaLink *link = links[0];
|
|
||||||
MediaEntity *sensorEntity = link->source()->entity();
|
|
||||||
sensor_ = new CameraSensor(sensorEntity);
|
|
||||||
ret = sensor_->init();
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = link->setEnabled(true);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure the sensor produces at least one format compatible with
|
|
||||||
* the CIO2 requirements.
|
|
||||||
*
|
|
||||||
* utils::set_overlap requires the ranges to be sorted, keep the
|
|
||||||
* cio2Codes vector sorted in ascending order.
|
|
||||||
*/
|
|
||||||
const std::vector<unsigned int> cio2Codes{ MEDIA_BUS_FMT_SBGGR10_1X10,
|
|
||||||
MEDIA_BUS_FMT_SGRBG10_1X10,
|
|
||||||
MEDIA_BUS_FMT_SGBRG10_1X10,
|
|
||||||
MEDIA_BUS_FMT_SRGGB10_1X10 };
|
|
||||||
const std::vector<unsigned int> &sensorCodes = sensor_->mbusCodes();
|
|
||||||
if (!utils::set_overlap(sensorCodes.begin(), sensorCodes.end(),
|
|
||||||
cio2Codes.begin(), cio2Codes.end())) {
|
|
||||||
LOG(IPU3, Error)
|
|
||||||
<< "Sensor " << sensor_->entity()->name()
|
|
||||||
<< " has not format compatible with the IPU3";
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* \todo Define when to open and close video device nodes, as they
|
|
||||||
* might impact on power consumption.
|
|
||||||
*/
|
|
||||||
|
|
||||||
csi2_ = new V4L2Subdevice(csi2Entity);
|
|
||||||
ret = csi2_->open();
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
std::string cio2Name = "ipu3-cio2 " + std::to_string(index);
|
|
||||||
output_ = V4L2VideoDevice::fromEntityName(media, cio2Name);
|
|
||||||
ret = output_->open();
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Configure the CIO2 unit
|
|
||||||
* \param[in] size The requested CIO2 output frame size
|
|
||||||
* \param[out] outputFormat The CIO2 unit output image format
|
|
||||||
* \return 0 on success or a negative error code otherwise
|
|
||||||
*/
|
|
||||||
int CIO2Device::configure(const Size &size,
|
|
||||||
V4L2DeviceFormat *outputFormat)
|
|
||||||
{
|
|
||||||
V4L2SubdeviceFormat sensorFormat;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Apply the selected format to the sensor, the CSI-2 receiver and
|
|
||||||
* the CIO2 output device.
|
|
||||||
*/
|
|
||||||
sensorFormat = sensor_->getFormat({ MEDIA_BUS_FMT_SBGGR10_1X10,
|
|
||||||
MEDIA_BUS_FMT_SGBRG10_1X10,
|
|
||||||
MEDIA_BUS_FMT_SGRBG10_1X10,
|
|
||||||
MEDIA_BUS_FMT_SRGGB10_1X10 },
|
|
||||||
size);
|
|
||||||
ret = sensor_->setFormat(&sensorFormat);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = csi2_->setFormat(0, &sensorFormat);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
V4L2PixelFormat v4l2Format;
|
|
||||||
switch (sensorFormat.mbus_code) {
|
|
||||||
case MEDIA_BUS_FMT_SBGGR10_1X10:
|
|
||||||
v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SBGGR10);
|
|
||||||
break;
|
|
||||||
case MEDIA_BUS_FMT_SGBRG10_1X10:
|
|
||||||
v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SGBRG10);
|
|
||||||
break;
|
|
||||||
case MEDIA_BUS_FMT_SGRBG10_1X10:
|
|
||||||
v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SGRBG10);
|
|
||||||
break;
|
|
||||||
case MEDIA_BUS_FMT_SRGGB10_1X10:
|
|
||||||
v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SRGGB10);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
outputFormat->fourcc = v4l2Format;
|
|
||||||
outputFormat->size = sensorFormat.size;
|
|
||||||
outputFormat->planesCount = 1;
|
|
||||||
|
|
||||||
ret = output_->setFormat(outputFormat);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
LOG(IPU3, Debug) << "CIO2 output format " << outputFormat->toString();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Allocate frame buffers for the CIO2 output
|
|
||||||
*
|
|
||||||
* 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 Number of buffers allocated or negative error code
|
|
||||||
*/
|
|
||||||
int CIO2Device::allocateBuffers()
|
|
||||||
{
|
|
||||||
int ret = output_->allocateBuffers(CIO2_BUFFER_COUNT, &buffers_);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
for (std::unique_ptr<FrameBuffer> &buffer : buffers_)
|
|
||||||
availableBuffers_.push(buffer.get());
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CIO2Device::freeBuffers()
|
|
||||||
{
|
|
||||||
/* The default std::queue constructor is explicit with gcc 5 and 6. */
|
|
||||||
availableBuffers_ = std::queue<FrameBuffer *>{};
|
|
||||||
|
|
||||||
buffers_.clear();
|
|
||||||
|
|
||||||
if (output_->releaseBuffers())
|
|
||||||
LOG(IPU3, Error) << "Failed to release CIO2 buffers";
|
|
||||||
}
|
|
||||||
|
|
||||||
FrameBuffer *CIO2Device::getBuffer()
|
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
int CIO2Device::stop()
|
|
||||||
{
|
|
||||||
return output_->streamOff();
|
|
||||||
}
|
|
||||||
|
|
||||||
REGISTER_PIPELINE_HANDLER(PipelineHandlerIPU3);
|
REGISTER_PIPELINE_HANDLER(PipelineHandlerIPU3);
|
||||||
|
|
||||||
} /* namespace libcamera */
|
} /* namespace libcamera */
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# SPDX-License-Identifier: CC0-1.0
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
libcamera_sources += files([
|
libcamera_sources += files([
|
||||||
|
'cio2.cpp',
|
||||||
'ipu3.cpp',
|
'ipu3.cpp',
|
||||||
])
|
])
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue