summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Plowman <david.plowman@raspberrypi.com>2022-11-22 11:30:49 +0000
committerJacopo Mondi <jacopo@jmondi.org>2022-12-01 11:26:44 +0100
commita2ccaf661694fe9f309dc3d48babd4239dda2bc9 (patch)
tree24c886b4d004aa71d13eb1e96a40ada6be147ad9
parentd2f9c1f0c344f884a8a4296ee77fc0c47655df7a (diff)
libcamera: camera_sensor: Do not clear camera flips when listing formats
Previously the code used to clear the camnera's h and v flip bits when enumerating the supported formats so as to obtain any Bayer formats in the sensor's native (untransformed) orientation. However this fails when the camera is already in use elsewhere. Instead, we query the current state of the flip bits and transform the formats - which we obtain in their flipped orientation - back into their native orientation to be stored. Signed-off-by: David Plowman <david.plowman@raspberrypi.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
-rw-r--r--src/libcamera/camera_sensor.cpp49
1 files changed, 39 insertions, 10 deletions
diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
index ae3127d6..e4a3684a 100644
--- a/src/libcamera/camera_sensor.cpp
+++ b/src/libcamera/camera_sensor.cpp
@@ -19,6 +19,8 @@
#include <libcamera/base/utils.h>
+#include <libcamera/transform.h>
+
#include "libcamera/internal/bayer_format.h"
#include "libcamera/internal/camera_lens.h"
#include "libcamera/internal/camera_sensor_properties.h"
@@ -108,18 +110,45 @@ int CameraSensor::init()
return ret;
/*
- * Clear any flips to be sure we get the "native" Bayer order. This is
- * harmless for sensors where the flips don't affect the Bayer order.
+ * We want to get the native mbus codes for the sensor, without any flips.
+ * We can't clear any flips here, so we have to read the current values
+ * (if the flip controls exist), decide whether they actually modify any
+ * output Bayer pattern, and finally undo their effect on the formats.
+ *
+ * First, check if the flip controls exist and if so read them.
*/
- ControlList ctrls(subdev_->controls());
- if (subdev_->controls().find(V4L2_CID_HFLIP) != subdev_->controls().end())
- ctrls.set(V4L2_CID_HFLIP, 0);
- if (subdev_->controls().find(V4L2_CID_VFLIP) != subdev_->controls().end())
- ctrls.set(V4L2_CID_VFLIP, 0);
- subdev_->setControls(&ctrls);
+ std::vector<uint32_t> flipCtrlIds;
+ const struct v4l2_query_ext_ctrl *hflipInfo = subdev_->controlInfo(V4L2_CID_HFLIP);
+ const struct v4l2_query_ext_ctrl *vflipInfo = subdev_->controlInfo(V4L2_CID_VFLIP);
+ if (hflipInfo)
+ flipCtrlIds.push_back(V4L2_CID_HFLIP);
+ if (vflipInfo)
+ flipCtrlIds.push_back(V4L2_CID_VFLIP);
+ ControlList flipCtrls = subdev_->getControls(flipCtrlIds);
+
+ /* Now construct a transform that would undo any flips. */
+ Transform transform = Transform::Identity;
+ if (hflipInfo && flipCtrls.get(V4L2_CID_HFLIP).get<int>() &&
+ (hflipInfo->flags & V4L2_CTRL_FLAG_MODIFY_LAYOUT))
+ transform |= Transform::HFlip;
+ if (vflipInfo && flipCtrls.get(V4L2_CID_VFLIP).get<int>() &&
+ (vflipInfo->flags & V4L2_CTRL_FLAG_MODIFY_LAYOUT))
+ transform |= Transform::VFlip;
+
+ /* Finally get the formats, and apply the transform to the mbus codes. */
+ auto formats = subdev_->formats(pad_);
+ for (const auto &format : formats) {
+ unsigned int mbusCode = format.first;
+ BayerFormat bayerFormat = BayerFormat::fromMbusCode(mbusCode);
+
+ if (bayerFormat.isValid())
+ mbusCode = bayerFormat.transform(transform).toMbusCode();
+
+ if (mbusCode)
+ formats_[mbusCode] = std::move(format.second);
+ }
/* Enumerate, sort and cache media bus codes and sizes. */
- formats_ = subdev_->formats(pad_);
if (formats_.empty()) {
LOG(CameraSensor, Error) << "No image format found";
return -EINVAL;
@@ -194,7 +223,7 @@ int CameraSensor::init()
* \todo The control API ought to have a flag to specify if a control
* is read-only which could be used below.
*/
- const ControlInfo hblank = ctrls.infoMap()->at(V4L2_CID_HBLANK);
+ const ControlInfo hblank = subdev_->controls().at(V4L2_CID_HBLANK);
const int32_t hblankMin = hblank.min().get<int32_t>();
const int32_t hblankMax = hblank.max().get<int32_t>();