Message ID | 20250303134234.699293-2-barnabas.pocze@ideasonboard.com |
---|---|
State | Superseded |
Headers | show |
Series |
|
Related | show |
Hi Barnabás On Mon, Mar 03, 2025 at 02:42:33PM +0100, Barnabás Pőcze wrote: > `ControlInfo(Span<const int32_t>{...})` calls the incorrect constructor > of `ControlInfo`. The intended constructor to be called is > `ControlInfo(Span<const ControlValue>, ...)` however that is not called > because a span of `const int32_t` is passed. Instead, the constructor > `ControlInfo(const ControlValue &min, const ControlValue &max, ...)` > will be called. > > Furthermore, since `values.back()` is used, only the last element of > the array is actually set. > > To fix this, convert the array to contain `ControlValue` objects and use > a separate variable to keep track of which element to set next. > > For each of `ExposureTimeMode{Auto,Manual}` save the V4L2 control value > that is to be used when the libcamera control is set. > > Fixes: bad8d591f8acfa ("libcamera: uvcvideo: Register ExposureTimeMode control") > Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> > --- > src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 61 ++++++++++++++------ > 1 file changed, 42 insertions(+), 19 deletions(-) > > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp > index 7470b5627..a6cc37366 100644 > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp > @@ -6,6 +6,7 @@ > */ > > #include <algorithm> > +#include <bitset> > #include <cmath> > #include <fstream> > #include <map> > @@ -56,6 +57,9 @@ public: > Stream stream_; > std::map<PixelFormat, std::vector<SizeRange>> formats_; > > + std::optional<v4l2_exposure_auto_type> autoExposureMode_; > + std::optional<v4l2_exposure_auto_type> manualExposureMode_; > + > private: > bool generateId(); > > @@ -723,25 +727,44 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info, > * ExposureTimeModeManual = { V4L2_EXPOSURE_MANUAL, > * V4L2_EXPOSURE_SHUTTER_PRIORITY } > */ > - std::array<int32_t, 2> values{}; > - > - auto it = std::find_if(v4l2Values.begin(), v4l2Values.end(), > - [&](const ControlValue &val) { > - return (val.get<int32_t>() == V4L2_EXPOSURE_APERTURE_PRIORITY || > - val.get<int32_t>() == V4L2_EXPOSURE_AUTO) ? true : false; > - }); > - if (it != v4l2Values.end()) > - values.back() = static_cast<int32_t>(controls::ExposureTimeModeAuto); > - > - it = std::find_if(v4l2Values.begin(), v4l2Values.end(), > - [&](const ControlValue &val) { > - return (val.get<int32_t>() == V4L2_EXPOSURE_SHUTTER_PRIORITY || > - val.get<int32_t>() == V4L2_EXPOSURE_MANUAL) ? true : false; > - }); > - if (it != v4l2Values.end()) > - values.back() = static_cast<int32_t>(controls::ExposureTimeModeManual); > - > - info = ControlInfo{Span<int32_t>{values}, values[0]}; > + > + std::bitset< > + std::max(V4L2_EXPOSURE_AUTO, > + std::max(V4L2_EXPOSURE_APERTURE_PRIORITY, > + std::max(V4L2_EXPOSURE_MANUAL, > + V4L2_EXPOSURE_SHUTTER_PRIORITY))) + 1 > + > exposureModes; > + > + for (const ControlValue &value : v4l2Values) { > + auto x = value.get<int32_t>(); > + > + if (0 <= x && static_cast<std::size_t>(x) < exposureModes.size()) > + exposureModes[x] = true; > + } > + > + if (exposureModes[V4L2_EXPOSURE_AUTO]) > + autoExposureMode_ = V4L2_EXPOSURE_AUTO; > + else if (exposureModes[V4L2_EXPOSURE_APERTURE_PRIORITY]) > + autoExposureMode_ = V4L2_EXPOSURE_APERTURE_PRIORITY; As we control exposure time and analogue gain modes separately, to actually implement V4L2_EXPOSURE_APERTURE_PRIORITY (or V4L2_EXPOSURE_SHUTTER_PRIORITY) one would have to match the right ExposureTimeMode and AnalogueGainMode combinations (auto exp + manual gain = APERTURE_PRIORITY, manual exp + auto gain = SHUTTER_PRIORITY). I'm not sure how many uvc devices support this advanced combinations, and this is not worse than before for sure. Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Thanks j > + > + if (exposureModes[V4L2_EXPOSURE_MANUAL]) > + manualExposureMode_ = V4L2_EXPOSURE_MANUAL; > + else if (exposureModes[V4L2_EXPOSURE_SHUTTER_PRIORITY]) > + manualExposureMode_ = V4L2_EXPOSURE_SHUTTER_PRIORITY; > + > + std::array<ControlValue, 2> values; > + std::size_t count = 0; > + > + if (autoExposureMode_) > + values[count++] = controls::ExposureTimeModeAuto; > + > + if (manualExposureMode_) > + values[count++] = controls::ExposureTimeModeManual; > + > + if (count == 0) > + return; > + > + info = ControlInfo{ Span<const ControlValue>{ values.data(), count }, values[0] }; Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Thanks j > break; > } > case V4L2_CID_EXPOSURE_ABSOLUTE: > -- > 2.48.1 >
diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index 7470b5627..a6cc37366 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -6,6 +6,7 @@ */ #include <algorithm> +#include <bitset> #include <cmath> #include <fstream> #include <map> @@ -56,6 +57,9 @@ public: Stream stream_; std::map<PixelFormat, std::vector<SizeRange>> formats_; + std::optional<v4l2_exposure_auto_type> autoExposureMode_; + std::optional<v4l2_exposure_auto_type> manualExposureMode_; + private: bool generateId(); @@ -723,25 +727,44 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info, * ExposureTimeModeManual = { V4L2_EXPOSURE_MANUAL, * V4L2_EXPOSURE_SHUTTER_PRIORITY } */ - std::array<int32_t, 2> values{}; - - auto it = std::find_if(v4l2Values.begin(), v4l2Values.end(), - [&](const ControlValue &val) { - return (val.get<int32_t>() == V4L2_EXPOSURE_APERTURE_PRIORITY || - val.get<int32_t>() == V4L2_EXPOSURE_AUTO) ? true : false; - }); - if (it != v4l2Values.end()) - values.back() = static_cast<int32_t>(controls::ExposureTimeModeAuto); - - it = std::find_if(v4l2Values.begin(), v4l2Values.end(), - [&](const ControlValue &val) { - return (val.get<int32_t>() == V4L2_EXPOSURE_SHUTTER_PRIORITY || - val.get<int32_t>() == V4L2_EXPOSURE_MANUAL) ? true : false; - }); - if (it != v4l2Values.end()) - values.back() = static_cast<int32_t>(controls::ExposureTimeModeManual); - - info = ControlInfo{Span<int32_t>{values}, values[0]}; + + std::bitset< + std::max(V4L2_EXPOSURE_AUTO, + std::max(V4L2_EXPOSURE_APERTURE_PRIORITY, + std::max(V4L2_EXPOSURE_MANUAL, + V4L2_EXPOSURE_SHUTTER_PRIORITY))) + 1 + > exposureModes; + + for (const ControlValue &value : v4l2Values) { + auto x = value.get<int32_t>(); + + if (0 <= x && static_cast<std::size_t>(x) < exposureModes.size()) + exposureModes[x] = true; + } + + if (exposureModes[V4L2_EXPOSURE_AUTO]) + autoExposureMode_ = V4L2_EXPOSURE_AUTO; + else if (exposureModes[V4L2_EXPOSURE_APERTURE_PRIORITY]) + autoExposureMode_ = V4L2_EXPOSURE_APERTURE_PRIORITY; + + if (exposureModes[V4L2_EXPOSURE_MANUAL]) + manualExposureMode_ = V4L2_EXPOSURE_MANUAL; + else if (exposureModes[V4L2_EXPOSURE_SHUTTER_PRIORITY]) + manualExposureMode_ = V4L2_EXPOSURE_SHUTTER_PRIORITY; + + std::array<ControlValue, 2> values; + std::size_t count = 0; + + if (autoExposureMode_) + values[count++] = controls::ExposureTimeModeAuto; + + if (manualExposureMode_) + values[count++] = controls::ExposureTimeModeManual; + + if (count == 0) + return; + + info = ControlInfo{ Span<const ControlValue>{ values.data(), count }, values[0] }; break; } case V4L2_CID_EXPOSURE_ABSOLUTE:
`ControlInfo(Span<const int32_t>{...})` calls the incorrect constructor of `ControlInfo`. The intended constructor to be called is `ControlInfo(Span<const ControlValue>, ...)` however that is not called because a span of `const int32_t` is passed. Instead, the constructor `ControlInfo(const ControlValue &min, const ControlValue &max, ...)` will be called. Furthermore, since `values.back()` is used, only the last element of the array is actually set. To fix this, convert the array to contain `ControlValue` objects and use a separate variable to keep track of which element to set next. For each of `ExposureTimeMode{Auto,Manual}` save the V4L2 control value that is to be used when the libcamera control is set. Fixes: bad8d591f8acfa ("libcamera: uvcvideo: Register ExposureTimeMode control") Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> --- src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 61 ++++++++++++++------ 1 file changed, 42 insertions(+), 19 deletions(-)