<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, 3 Nov 2022 at 11:02, Dave Stevenson via libcamera-devel <<a href="mailto:libcamera-devel@lists.libcamera.org">libcamera-devel@lists.libcamera.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi David<br>
<br>
On Thu, 3 Nov 2022 at 10:40, David Plowman via libcamera-devel<br>
<<a href="mailto:libcamera-devel@lists.libcamera.org" target="_blank">libcamera-devel@lists.libcamera.org</a>> wrote:<br>
><br>
> Previously the code used to clear the camnera's h and v flip bits when<br>
> enumerating the supported formats so as to obtain any Bayer formats in<br>
> the sensor's native (untransformed) orientation. However this fails<br>
> when the camera is already in use elsewhere.<br>
><br>
> Instead, we query the current state of the flip bits and transform the<br>
> formats - which we obtain in their flipped orientation - back into<br>
> their native orientation to be stored.<br>
<br>
I don't believe that libcamera knows for definite whether the sensor<br>
changes the Bayer order or not. Several of the OnSemi sensors I have<br>
seen do not change, presumably as they shift their crop by 1 pixel.<br></blockquote><div><br></div><div>There is a flag associated with the H/V flips that can tell us if the sensor changes the bayer order:</div><div><br></div><div>const struct v4l2_query_ext_ctrl *hflipCtrl = sensor->controlInfo(V4L2_CID_HFLIP);<br></div><div>data->flipsAlterBayerOrder_ = hflipCtrl->flags & V4L2_CTRL_FLAG_MODIFY_LAYOUT;<br></div><div> </div><div>This ought to help here.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
The original comment mentioned that scenario:<br>
"This is harmless for sensors where the flips don't affect the Bayer order"<br>
<br>
  Dave<br>
<br>
> Signed-off-by: David Plowman <<a href="mailto:david.plowman@raspberrypi.com" target="_blank">david.plowman@raspberrypi.com</a>><br>
> ---<br>
>  src/libcamera/camera_sensor.cpp | 51 +++++++++++++++++++++++++++------<br>
>  1 file changed, 43 insertions(+), 8 deletions(-)<br>
><br>
> diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp<br>
> index 572a313a..6670dfb9 100644<br>
> --- a/src/libcamera/camera_sensor.cpp<br>
> +++ b/src/libcamera/camera_sensor.cpp<br>
> @@ -19,6 +19,8 @@<br>
><br>
>  #include <libcamera/base/utils.h><br>
><br>
> +#include <libcamera/transform.h><br>
> +<br>
>  #include "libcamera/internal/bayer_format.h"<br>
>  #include "libcamera/internal/camera_lens.h"<br>
>  #include "libcamera/internal/camera_sensor_properties.h"<br>
> @@ -108,18 +110,51 @@ int CameraSensor::init()<br>
>  Â  Â  Â  Â  Â  Â  Â  Â return ret;<br>
><br>
>  Â  Â  Â  Â /*<br>
> -  Â  Â  Â  * Clear any flips to be sure we get the "native" Bayer order. This is<br>
> -  Â  Â  Â  * harmless for sensors where the flips don't affect the Bayer order.<br>
> +  Â  Â  Â  * We want to get the native mbus codes for the sensor, without any flips.<br>
> +  Â  Â  Â  * We can't clear any flips here, so we have to read the current values<br>
> +  Â  Â  Â  * (if the flip controls exist), decide whether they actually modify any<br>
> +  Â  Â  Â  * output Bayer pattern, and finally undo their effect on the formats.<br>
> +  Â  Â  Â  *<br>
> +  Â  Â  Â  * First, check if the flip controls exist and if so read them.<br>
>  Â  Â  Â  Â  */<br>
>  Â  Â  Â  Â ControlList ctrls(subdev_->controls());<br>
> -  Â  Â  Â if (subdev_->controls().find(V4L2_CID_HFLIP) != subdev_->controls().end())<br>
> -  Â  Â  Â  Â  Â  Â  Â ctrls.set(V4L2_CID_HFLIP, 0);<br>
> -  Â  Â  Â if (subdev_->controls().find(V4L2_CID_VFLIP) != subdev_->controls().end())<br>
> -  Â  Â  Â  Â  Â  Â  Â ctrls.set(V4L2_CID_VFLIP, 0);<br>
> -  Â  Â  Â subdev_->setControls(&ctrls);<br>
> +  Â  Â  Â std::vector<uint32_t> flipCtrlIds;<br>
> +  Â  Â  Â bool hasHflip = subdev_->controls().find(V4L2_CID_HFLIP) != subdev_->controls().end();<br>
> +  Â  Â  Â bool hasVflip = subdev_->controls().find(V4L2_CID_VFLIP) != subdev_->controls().end();<br>
> +  Â  Â  Â if (hasHflip)<br>
> +  Â  Â  Â  Â  Â  Â  Â flipCtrlIds.push_back(V4L2_CID_HFLIP);<br>
> +  Â  Â  Â if (hasVflip)<br>
> +  Â  Â  Â  Â  Â  Â  Â flipCtrlIds.push_back(V4L2_CID_VFLIP);<br>
> +  Â  Â  Â ControlList flipCtrls = subdev_->getControls(flipCtrlIds);<br>
> +<br>
> +  Â  Â  Â /* Now construct a transform that would undo any flips. */<br>
> +  Â  Â  Â Transform transform = Transform::Identity;<br>
> +  Â  Â  Â if (hasHflip && flipCtrls.get(V4L2_CID_HFLIP).get<int>()) {<br>
> +  Â  Â  Â  Â  Â  Â  Â const struct v4l2_query_ext_ctrl *extCtrl = subdev_->controlInfo(V4L2_CID_HFLIP);<br>
> +  Â  Â  Â  Â  Â  Â  Â if (extCtrl->flags & V4L2_CTRL_FLAG_MODIFY_LAYOUT)<br>
> +  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â transform |= Transform::HFlip;<br>
> +  Â  Â  Â }<br>
> +  Â  Â  Â if (hasVflip && flipCtrls.get(V4L2_CID_VFLIP).get<int>()) {<br>
> +  Â  Â  Â  Â  Â  Â  Â const struct v4l2_query_ext_ctrl *extCtrl = subdev_->controlInfo(V4L2_CID_VFLIP);<br>
> +  Â  Â  Â  Â  Â  Â  Â if (extCtrl->flags & V4L2_CTRL_FLAG_MODIFY_LAYOUT)<br>
> +  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â transform |= Transform::VFlip;<br>
> +  Â  Â  Â }<br>
> +<br>
> +  Â  Â  Â /* Finally get the formats, and apply the transform to the mbus codes. */<br>
> +  Â  Â  Â auto formats = subdev_->formats(pad_);<br>
> +  Â  Â  Â for (const auto &format : formats) {<br>
> +  Â  Â  Â  Â  Â  Â  Â unsigned int mbusCode = format.first;<br>
> +  Â  Â  Â  Â  Â  Â  Â BayerFormat bayerFormat = BayerFormat::fromMbusCode(mbusCode);<br>
> +  Â  Â  Â  Â  Â  Â  Â bool valid = true;<br>
> +<br>
> +  Â  Â  Â  Â  Â  Â  Â if (bayerFormat.isValid())<br>
> +  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â mbusCode = bayerFormat.transform(transform).toMbusCode(valid);<br>
> +<br>
> +  Â  Â  Â  Â  Â  Â  Â if (valid)<br>
> +  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â formats_[mbusCode] = std::move(format.second);<br>
> +  Â  Â  Â }<br>
><br>
>  Â  Â  Â  Â /* Enumerate, sort and cache media bus codes and sizes. */<br>
> -  Â  Â  Â formats_ = subdev_->formats(pad_);<br>
>  Â  Â  Â  Â if (formats_.empty()) {<br>
>  Â  Â  Â  Â  Â  Â  Â  Â LOG(CameraSensor, Error) << "No image format found";<br>
>  Â  Â  Â  Â  Â  Â  Â  Â return -EINVAL;<br>
> --<br>
> 2.30.2<br>
><br>
</blockquote></div></div>