libcamera: raspberrypi: Plumb user transform through to IPA

This commit plumbs the user transform from the Raspberry Pi pipeline
handler through to the IPA. Note that the transform is actually
handled in the sensor (by setting the h/v flip bits), so the IPAs need
to understand the orientation of the image they receive.

Once in the IPA we add it to the CameraMode description, so that it
becomes automatically available to all the individual control
algorithms.

The IPA configure method has to be reordered just a little so as to
fill in the transform in the camera mode before calling SwitchMode.

Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
David Plowman 2020-09-07 08:16:02 +01:00 committed by Kieran Bingham
parent 4cff3937e1
commit 5c32a0daf5
3 changed files with 35 additions and 22 deletions

View file

@ -6,6 +6,8 @@
*/ */
#pragma once #pragma once
#include <libcamera/transform.h>
// Description of a "camera mode", holding enough information for control // Description of a "camera mode", holding enough information for control
// algorithms to adapt their behaviour to the different modes of the camera, // algorithms to adapt their behaviour to the different modes of the camera,
// including binning, scaling, cropping etc. // including binning, scaling, cropping etc.
@ -33,6 +35,8 @@ struct CameraMode {
double noise_factor; double noise_factor;
// line time in nanoseconds // line time in nanoseconds
double line_length; double line_length;
// any camera transform *not* reflected already in the camera tuning
libcamera::Transform transform;
}; };
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -230,6 +230,33 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,
/* Re-assemble camera mode using the sensor info. */ /* Re-assemble camera mode using the sensor info. */
setMode(sensorInfo); setMode(sensorInfo);
/*
* The ipaConfig.data always gives us the user transform first. Note that
* this will always make the LS table pointer (if present) element 1.
*/
mode_.transform = static_cast<libcamera::Transform>(ipaConfig.data[0]);
/* Store the lens shading table pointer and handle if available. */
if (ipaConfig.operation & RPI_IPA_CONFIG_LS_TABLE) {
/* Remove any previous table, if there was one. */
if (lsTable_) {
munmap(lsTable_, MAX_LS_GRID_SIZE);
lsTable_ = nullptr;
}
/* Map the LS table buffer into user space (now element 1). */
lsTableHandle_ = FileDescriptor(ipaConfig.data[1]);
if (lsTableHandle_.isValid()) {
lsTable_ = mmap(nullptr, MAX_LS_GRID_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED, lsTableHandle_.fd(), 0);
if (lsTable_ == MAP_FAILED) {
LOG(IPARPI, Error) << "dmaHeap mmap failure for LS table.";
lsTable_ = nullptr;
}
}
}
/* Pass the camera mode to the CamHelper to setup algorithms. */ /* Pass the camera mode to the CamHelper to setup algorithms. */
helper_->SetCameraMode(mode_); helper_->SetCameraMode(mode_);
@ -282,27 +309,6 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,
} }
lastMode_ = mode_; lastMode_ = mode_;
/* Store the lens shading table pointer and handle if available. */
if (ipaConfig.operation & RPI_IPA_CONFIG_LS_TABLE) {
/* Remove any previous table, if there was one. */
if (lsTable_) {
munmap(lsTable_, MAX_LS_GRID_SIZE);
lsTable_ = nullptr;
}
/* Map the LS table buffer into user space. */
lsTableHandle_ = FileDescriptor(ipaConfig.data[0]);
if (lsTableHandle_.isValid()) {
lsTable_ = mmap(nullptr, MAX_LS_GRID_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED, lsTableHandle_.fd(), 0);
if (lsTable_ == MAP_FAILED) {
LOG(IPARPI, Error) << "dmaHeap mmap failure for LS table.";
lsTable_ = nullptr;
}
}
}
} }
void IPARPi::mapBuffers(const std::vector<IPABuffer> &buffers) void IPARPi::mapBuffers(const std::vector<IPABuffer> &buffers)

View file

@ -1133,6 +1133,9 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config)
entityControls.emplace(0, unicam_[Unicam::Image].dev()->controls()); entityControls.emplace(0, unicam_[Unicam::Image].dev()->controls());
entityControls.emplace(1, isp_[Isp::Input].dev()->controls()); entityControls.emplace(1, isp_[Isp::Input].dev()->controls());
/* Always send the user transform to the IPA. */
ipaConfig.data = { static_cast<unsigned int>(config->transform) };
/* Allocate the lens shading table via dmaHeap and pass to the IPA. */ /* Allocate the lens shading table via dmaHeap and pass to the IPA. */
if (!lsTable_.isValid()) { if (!lsTable_.isValid()) {
lsTable_ = dmaHeap_.alloc("ls_grid", MAX_LS_GRID_SIZE); lsTable_ = dmaHeap_.alloc("ls_grid", MAX_LS_GRID_SIZE);
@ -1141,7 +1144,7 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config)
/* Allow the IPA to mmap the LS table via the file descriptor. */ /* Allow the IPA to mmap the LS table via the file descriptor. */
ipaConfig.operation = RPI_IPA_CONFIG_LS_TABLE; ipaConfig.operation = RPI_IPA_CONFIG_LS_TABLE;
ipaConfig.data = { static_cast<unsigned int>(lsTable_.fd()) }; ipaConfig.data.push_back(static_cast<unsigned int>(lsTable_.fd()));
} }
CameraSensorInfo sensorInfo = {}; CameraSensorInfo sensorInfo = {};