@@ -22,7 +22,6 @@
#include <libcamera/orientation.h>
#include <libcamera/request.h>
#include <libcamera/stream.h>
-#include <libcamera/transform.h>
namespace libcamera {
@@ -67,7 +66,6 @@ public:
bool empty() const;
std::size_t size() const;
- Transform transform;
Orientation orientation;
protected:
@@ -32,6 +32,8 @@ class MediaEntity;
struct CameraSensorProperties;
+enum class Orientation;
+
class CameraSensor : protected Loggable
{
public:
@@ -71,7 +73,7 @@ public:
CameraLens *focusLens() { return focusLens_.get(); }
- Transform validateTransform(Transform *transform) const;
+ Transform computeTransform(Orientation *orientation) const;
protected:
std::string logPrefix() const override;
@@ -160,8 +160,7 @@ LOG_DECLARE_CATEGORY(Camera)
* \brief Create an empty camera configuration
*/
CameraConfiguration::CameraConfiguration()
- : transform(Transform::Identity), orientation(Orientation::rotate0),
- config_({})
+ : orientation(Orientation::rotate0), config_({})
{
}
@@ -392,19 +391,6 @@ CameraConfiguration::Status CameraConfiguration::validateColorSpaces(ColorSpaceF
return status;
}
-/**
- * \var CameraConfiguration::transform
- * \brief User-specified transform to be applied to the image
- *
- * The transform is a user-specified 2D plane transform that will be applied
- * to the camera images by the processing pipeline before being handed to
- * the application.
- *
- * The usual 2D plane transforms are allowed here (horizontal/vertical
- * flips, multiple of 90-degree rotations etc.), but the validate() function
- * may adjust this field at its discretion if the selection is not supported.
- */
-
/**
* \var CameraConfiguration::orientation
* \brief The desired orientation of the images produced by the camera
@@ -15,6 +15,7 @@
#include <math.h>
#include <string.h>
+#include <libcamera/orientation.h>
#include <libcamera/property_ids.h>
#include <libcamera/base/utils.h>
@@ -465,7 +466,7 @@ int CameraSensor::initProperties()
/*
* Cache the Transform associated with the camera mounting
- * rotation for later use in validateTransform().
+ * rotation for later use in computeTransform().
*/
bool success;
rotationTransform_ = transformFromRotation(propertyValue, &success);
@@ -1024,69 +1025,64 @@ void CameraSensor::updateControlInfo()
*/
/**
- * \brief Validate a transform request against the sensor capabilities
- * \param[inout] transform The requested transformation, updated to match
- * the sensor capabilities
+ * \brief Compute the Transform that gives the requested \a orientation
+ * \param[inout] orientation The desired image orientation
*
- * The input \a transform is the transform that the caller wants, and it is
- * adjusted according to the capabilities of the sensor to represent the
- * "nearest" transform that can actually be delivered.
+ * This function computes the Transform that the pipeline handler should apply
+ * to the CameraSensor to obtain the requested \a orientation.
*
- * The returned Transform is the transform applied to the sensor in order to
- * produce the input \a transform, It is also validated against the sensor's
- * ability to perform horizontal and vertical flips.
+ * The intended caller of this function is the validate() implementation of
+ * pipeline handlers, that pass in the application requested
+ * CameraConfiguration::orientation and obtain a Transform to apply to the
+ * camera sensor, likely at configure() time.
*
- * For example, if the requested \a transform is Transform::Identity and the
- * sensor rotation is 180 degrees, the output transform will be
- * Transform::Rot180 to correct the images so that they appear to have
- * Transform::Identity, but only if the sensor can apply horizontal and vertical
- * flips.
+ * If the requested \a orientation cannot be obtained, the \a orientation
+ * parameter is adjusted to report the current image orientation and
+ * Transform::Identity is returned.
*
- * \return A Transform instance that represents which transformation has been
- * applied to the camera sensor
+ * If the requested \a orientation can be obtained, the function computes a
+ * Transform and does not adjust \a orientation.
+ *
+ * Pipeline handlers are expected to verify if \a orientation has been
+ * adjusted by this function and set the CameraConfiguration::status to
+ * Adjusted accordingly.
+ *
+ * \return A Transform instance that applied to the CameraSensor produces images
+ * with \a orientation
*/
-Transform CameraSensor::validateTransform(Transform *transform) const
+Transform CameraSensor::computeTransform(Orientation *orientation) const
{
+ Orientation mountingOrientation = transformToOrientation(rotationTransform_);
+
/*
- * Combine the requested transform to compensate the sensor mounting
- * rotation.
+ * We cannot do any flips: we cannot change the native camera mounting
+ * orientation.
*/
- Transform combined = rotationTransform_ * *transform;
+ if (!supportFlips_) {
+ *orientation = mountingOrientation;
+ return Transform::Identity;
+ }
/*
- * We combine the platform and user transform, but must "adjust away"
- * any combined result that includes a transposition, as we can't do
- * those. In this case, flipping only the transpose bit is helpful to
- * applications - they either get the transform they requested, or have
- * to do a simple transpose themselves (they don't have to worry about
- * the other possible cases).
+ * Now compute the required transform to obtain 'orientation' starting
+ * from the mounting rotation.
+ *
+ * As a note:
+ * orientation / mountingOrientation = transform
+ * mountingOrientation * transform = orientation
*/
- if (!!(combined & Transform::Transpose)) {
- /*
- * Flipping the transpose bit in "transform" flips it in the
- * combined result too (as it's the last thing that happens),
- * which is of course clearing it.
- */
- *transform ^= Transform::Transpose;
- combined &= ~Transform::Transpose;
- }
+ Transform transform = *orientation / mountingOrientation;
/*
- * We also check if the sensor doesn't do h/vflips at all, in which
- * case we clear them, and the application will have to do everything.
+ * If transform contains any Transpose we cannot do it, so adjust
+ * 'orientation' to report the image native orientation and return Identity.
*/
- if (!supportFlips_ && !!combined) {
- /*
- * If the sensor can do no transforms, then combined must be
- * changed to the identity. The only user transform that gives
- * rise to this is the inverse of the rotation. (Recall that
- * combined = rotationTransform * transform.)
- */
- *transform = -rotationTransform_;
- combined = Transform::Identity;
+ if (!!(transform & Transform::Transpose)) {
+ *orientation = mountingOrientation;
+ return Transform::Identity;
}
- return combined;
+ return transform;
}
std::string CameraSensor::logPrefix() const
@@ -187,9 +187,9 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()
* rotation and store the final combined transform that configure() will
* need to apply to the sensor to save us working it out again.
*/
- Transform requestedTransform = transform;
- combinedTransform_ = data_->cio2_.sensor()->validateTransform(&transform);
- if (transform != requestedTransform)
+ Orientation requestedOrientation = orientation;
+ combinedTransform_ = data_->cio2_.sensor()->computeTransform(&orientation);
+ if (orientation != requestedOrientation)
status = Adjusted;
/* Cap the number of entries to the available streams. */
@@ -481,9 +481,9 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
status = Adjusted;
}
- Transform requestedTransform = transform;
- Transform combined = sensor->validateTransform(&transform);
- if (transform != requestedTransform)
+ Orientation requestedOrientation = orientation;
+ combinedTransform_ = data_->sensor_->computeTransform(&orientation);
+ if (orientation != requestedOrientation)
status = Adjusted;
/*
@@ -595,8 +595,6 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
if (sensorFormat_.size.isNull())
sensorFormat_.size = sensor->resolution();
- combinedTransform_ = combined;
-
return status;
}
@@ -254,9 +254,9 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()
* rotation and store the final combined transform that configure() will
* need to apply to the sensor to save us working it out again.
*/
- Transform requestedTransform = transform;
- combinedTransform_ = data_->sensor_->validateTransform(&transform);
- if (transform != requestedTransform)
+ Orientation requestedOrientation = orientation;
+ combinedTransform_ = data_->sensor_->computeTransform(&orientation);
+ if (orientation != requestedOrientation)
status = Adjusted;
std::vector<CameraData::StreamParams> rawStreams, outStreams;
@@ -1193,7 +1193,8 @@ int CameraData::configureIPA(const CameraConfiguration *config, ipa::RPi::Config
}
/* Always send the user transform to the IPA. */
- params.transform = static_cast<unsigned int>(config->transform);
+ params.transform =
+ static_cast<unsigned int>(transformFromOrientation(config->orientation));
/* Ready the IPA - it must know about the sensor resolution. */
ret = ipa_->configure(sensorInfo_, params, result);
@@ -889,9 +889,9 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()
if (config_.empty())
return Invalid;
- Transform requestedTransform = transform;
- combinedTransform_ = sensor->validateTransform(&transform);
- if (transform != requestedTransform)
+ Orientation requestedOrientation = orientation;
+ combinedTransform_ = sensor->computeTransform(&orientation);
+ if (orientation != requestedOrientation)
status = Adjusted;
/* Cap the number of entries to the available streams. */
@@ -111,8 +111,8 @@ CameraConfiguration::Status UVCCameraConfiguration::validate()
if (config_.empty())
return Invalid;
- if (transform != Transform::Identity) {
- transform = Transform::Identity;
+ if (orientation != Orientation::rotate0) {
+ orientation = Orientation::rotate0;
status = Adjusted;
}
@@ -128,8 +128,8 @@ CameraConfiguration::Status VimcCameraConfiguration::validate()
if (config_.empty())
return Invalid;
- if (transform != Transform::Identity) {
- transform = Transform::Identity;
+ if (orientation != Orientation::rotate0) {
+ orientation = Orientation::rotate0;
status = Adjusted;
}