mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-21 15:53:54 +03:00
libcamera: pipeline: ipu3: Implement capture support
Replace the buffer allocation, capture start/stop and request queue stubs with real implementations. Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
7da6b95283
commit
edfdace1d5
1 changed files with 114 additions and 9 deletions
|
@ -9,6 +9,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <libcamera/camera.h>
|
#include <libcamera/camera.h>
|
||||||
|
#include <libcamera/request.h>
|
||||||
#include <libcamera/stream.h>
|
#include <libcamera/stream.h>
|
||||||
|
|
||||||
#include "device_enumerator.h"
|
#include "device_enumerator.h"
|
||||||
|
@ -97,12 +98,23 @@ PipelineHandlerIPU3::streamConfiguration(Camera *camera,
|
||||||
std::vector<Stream *> &streams)
|
std::vector<Stream *> &streams)
|
||||||
{
|
{
|
||||||
IPU3CameraData *data = cameraData(camera);
|
IPU3CameraData *data = cameraData(camera);
|
||||||
|
|
||||||
std::map<Stream *, StreamConfiguration> configs;
|
std::map<Stream *, StreamConfiguration> configs;
|
||||||
|
V4L2SubdeviceFormat format = {};
|
||||||
|
|
||||||
StreamConfiguration config{};
|
/*
|
||||||
|
* FIXME: As of now, return the image format reported by the sensor.
|
||||||
|
* In future good defaults should be provided for each stream.
|
||||||
|
*/
|
||||||
|
if (data->sensor_->getFormat(0, &format)) {
|
||||||
|
LOG(IPU3, Error) << "Failed to create stream configurations";
|
||||||
|
return configs;
|
||||||
|
}
|
||||||
|
|
||||||
LOG(IPU3, Info) << "TODO: Return a good default format";
|
StreamConfiguration config = {};
|
||||||
|
config.width = format.width;
|
||||||
|
config.height = format.height;
|
||||||
|
config.pixelFormat = V4L2_PIX_FMT_IPU3_SGRBG10;
|
||||||
|
config.bufferCount = 4;
|
||||||
|
|
||||||
configs[&data->stream_] = config;
|
configs[&data->stream_] = config;
|
||||||
|
|
||||||
|
@ -113,38 +125,131 @@ int PipelineHandlerIPU3::configureStreams(Camera *camera,
|
||||||
std::map<Stream *, StreamConfiguration> &config)
|
std::map<Stream *, StreamConfiguration> &config)
|
||||||
{
|
{
|
||||||
IPU3CameraData *data = cameraData(camera);
|
IPU3CameraData *data = cameraData(camera);
|
||||||
|
|
||||||
StreamConfiguration *cfg = &config[&data->stream_];
|
StreamConfiguration *cfg = &config[&data->stream_];
|
||||||
|
V4L2Subdevice *sensor = data->sensor_;
|
||||||
|
V4L2Subdevice *csi2 = data->csi2_;
|
||||||
|
V4L2Device *cio2 = data->cio2_;
|
||||||
|
V4L2SubdeviceFormat subdevFormat = {};
|
||||||
|
V4L2DeviceFormat devFormat = {};
|
||||||
|
int ret;
|
||||||
|
|
||||||
LOG(IPU3, Info) << "TODO: Configure the camera for resolution "
|
/*
|
||||||
<< cfg->width << "x" << cfg->height;
|
* FIXME: as of now, the format gets applied to the sensor and is
|
||||||
|
* propagated along the pipeline. It should instead be applied on the
|
||||||
|
* capture device and the sensor format calculated accordingly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = sensor->getFormat(0, &subdevFormat);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
subdevFormat.width = cfg->width;
|
||||||
|
subdevFormat.height = cfg->height;
|
||||||
|
ret = sensor->setFormat(0, &subdevFormat);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Return error if the requested format cannot be applied to sensor. */
|
||||||
|
if (subdevFormat.width != cfg->width ||
|
||||||
|
subdevFormat.height != cfg->height) {
|
||||||
|
LOG(IPU3, Error)
|
||||||
|
<< "Failed to apply image format "
|
||||||
|
<< subdevFormat.width << "x" << subdevFormat.height
|
||||||
|
<< " - got: " << cfg->width << "x" << cfg->height;
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = csi2->setFormat(0, &subdevFormat);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = cio2->getFormat(&devFormat);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
devFormat.width = subdevFormat.width;
|
||||||
|
devFormat.height = subdevFormat.height;
|
||||||
|
devFormat.fourcc = cfg->pixelFormat;
|
||||||
|
|
||||||
|
ret = cio2->setFormat(&devFormat);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
LOG(IPU3, Info) << cio2->driverName() << ": "
|
||||||
|
<< devFormat.width << "x" << devFormat.height
|
||||||
|
<< "- 0x" << std::hex << devFormat.fourcc << " planes: "
|
||||||
|
<< devFormat.planes;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PipelineHandlerIPU3::allocateBuffers(Camera *camera, Stream *stream)
|
int PipelineHandlerIPU3::allocateBuffers(Camera *camera, Stream *stream)
|
||||||
{
|
{
|
||||||
return -ENOTRECOVERABLE;
|
IPU3CameraData *data = cameraData(camera);
|
||||||
|
const StreamConfiguration &cfg = stream->configuration();
|
||||||
|
|
||||||
|
if (!cfg.bufferCount)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
int ret = data->cio2_->exportBuffers(cfg.bufferCount,
|
||||||
|
&stream->bufferPool());
|
||||||
|
if (ret) {
|
||||||
|
LOG(IPU3, Error) << "Failed to request memory";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PipelineHandlerIPU3::freeBuffers(Camera *camera, Stream *stream)
|
int PipelineHandlerIPU3::freeBuffers(Camera *camera, Stream *stream)
|
||||||
{
|
{
|
||||||
|
IPU3CameraData *data = cameraData(camera);
|
||||||
|
|
||||||
|
int ret = data->cio2_->releaseBuffers();
|
||||||
|
if (ret) {
|
||||||
|
LOG(IPU3, Error) << "Failed to release memory";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PipelineHandlerIPU3::start(const Camera *camera)
|
int PipelineHandlerIPU3::start(const Camera *camera)
|
||||||
{
|
{
|
||||||
LOG(IPU3, Error) << "TODO: start camera";
|
IPU3CameraData *data = cameraData(camera);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = data->cio2_->streamOn();
|
||||||
|
if (ret) {
|
||||||
|
LOG(IPU3, Info) << "Failed to start camera " << camera->name();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PipelineHandlerIPU3::stop(const Camera *camera)
|
void PipelineHandlerIPU3::stop(const Camera *camera)
|
||||||
{
|
{
|
||||||
LOG(IPU3, Error) << "TODO: stop camera";
|
IPU3CameraData *data = cameraData(camera);
|
||||||
|
|
||||||
|
if (data->cio2_->streamOff())
|
||||||
|
LOG(IPU3, Info) << "Failed to stop camera " << camera->name();
|
||||||
}
|
}
|
||||||
|
|
||||||
int PipelineHandlerIPU3::queueRequest(const Camera *camera, Request *request)
|
int PipelineHandlerIPU3::queueRequest(const Camera *camera, Request *request)
|
||||||
{
|
{
|
||||||
|
IPU3CameraData *data = cameraData(camera);
|
||||||
|
Stream *stream = &data->stream_;
|
||||||
|
|
||||||
|
Buffer *buffer = request->findBuffer(stream);
|
||||||
|
if (!buffer) {
|
||||||
|
LOG(IPU3, Error)
|
||||||
|
<< "Attempt to queue request with invalid stream";
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->cio2_->queueBuffer(buffer);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue