[libcamera-devel,RFC,v2,2/5] libcamera: camera_sensor: Enable to set a test pattern mode
diff mbox series

Message ID 20210622023654.969162-2-hiroh@chromium.org
State Superseded
Headers show
Series
  • [libcamera-devel,RFC,v2,1/5] libcamera: camera_sensor: Reverse the key and value of test pattern mode map
Related show

Commit Message

Hirokazu Honda June 22, 2021, 2:36 a.m. UTC
Provides a function to set the camera sensor a test pattern mode.

Signed-off-by: Hirokazu Honda <hiroh@chromium.org>
---
 include/libcamera/internal/camera_sensor.h |  1 +
 src/libcamera/camera_sensor.cpp            | 39 ++++++++++++++++++++++
 2 files changed, 40 insertions(+)

Comments

Jacopo Mondi June 22, 2021, 10:31 a.m. UTC | #1
Hi Hiro,

On Tue, Jun 22, 2021 at 11:36:51AM +0900, Hirokazu Honda wrote:
> Provides a function to set the camera sensor a test pattern mode.
>
> Signed-off-by: Hirokazu Honda <hiroh@chromium.org>
> ---
>  include/libcamera/internal/camera_sensor.h |  1 +
>  src/libcamera/camera_sensor.cpp            | 39 ++++++++++++++++++++++
>  2 files changed, 40 insertions(+)
>
> diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
> index e133ebf4..8b9f84c9 100644
> --- a/include/libcamera/internal/camera_sensor.h
> +++ b/include/libcamera/internal/camera_sensor.h
> @@ -43,6 +43,7 @@ public:
>  	{
>  		return testPatternModes_;
>  	}
> +	int setTestPatternMode(uint8_t testPatternMode);
>
>  	V4L2SubdeviceFormat getFormat(const std::vector<unsigned int> &mbusCodes,
>  				      const Size &size) const;
> diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
> index 70bbd97a..ce8ff274 100644
> --- a/src/libcamera/camera_sensor.cpp
> +++ b/src/libcamera/camera_sensor.cpp
> @@ -507,6 +507,45 @@ Size CameraSensor::resolution() const
>   * \return The list of test pattern modes
>   */
>
> +/**
> + * \brief Set the camera sensor a specified controls::TestPatternMode

Doxygen is puzzling me recently... the testPatternMode paramter is not
documented but I don't get a warning :/

Also, I'm a bit debated about where to actually place this function
(or better, it's initTestPatternModes which is misplaced)
if we have to respect the declaration order or the way you sorted them
here (which is more logical) is better.

> + *
> + * \return 0 on success or a negative error code otherwise
> + */
> +int CameraSensor::setTestPatternMode(uint8_t testPatternMode)
> +{
> +	if (std::find(testPatternModes_.begin(), testPatternModes_.end(),
> +		      testPatternMode) == testPatternModes_.end()) {
> +		LOG(CameraSensor, Error) << "Unsupported test pattern mode: "
> +					 << testPatternMode;
> +		return -EINVAL;
> +	}

Do we need this ? The testPatternModes_ map is constructed using the
camera sensor properties, the below find() on the props->testPatternModes
map should gurantee that is supported. Also, if a test pattern mode is
not reported as part of testPatternModes_ applications shouldn't set
it...

> +
> +	const CameraSensorProperties *props = CameraSensorProperties::get(model_);
> +	if (!props)
> +		return -EINVAL;
> +
> +	auto it = props->testPatternModes.find(testPatternMode);
> +	ASSERT(it != props->testPatternModes.end());

Yeah, I think the assertion here is more than enough..

> +	const uint8_t index = it->second;
> +
> +	ControlList ctrls = getControls({ V4L2_CID_TEST_PATTERN });
> +	if (ctrls.empty()) {
> +		LOG(CameraSensor, Error)
> +			<< "Failed to retrieve test pattern control";
> +		return -EINVAL;
> +	}

We won't register the TestPatternMode control in first place the V4L2
control is not supported..

> +
> +	ControlValue value = ctrls.get(V4L2_CID_TEST_PATTERN);
> +	if (value.get<int32_t>() == index)
> +		return 0;

The V4L2 control framework should take care of this by itself, I think
we can set the control regardless

> +
> +	value.set<int32_t>(index);
> +	ctrls.set(V4L2_CID_TEST_PATTERN, value);
> +
> +	return setControls(&ctrls);
> +}
> +
>  /**
>   * \brief Retrieve the best sensor format for a desired output
>   * \param[in] mbusCodes The list of acceptable media bus codes
> --
> 2.32.0.288.g62a8d224e6-goog
>
Hirokazu Honda June 23, 2021, 7:49 a.m. UTC | #2
Hi Jacopo, thank you for reviewing.

On Tue, Jun 22, 2021 at 7:30 PM Jacopo Mondi <jacopo@jmondi.org> wrote:
>
> Hi Hiro,
>
> On Tue, Jun 22, 2021 at 11:36:51AM +0900, Hirokazu Honda wrote:
> > Provides a function to set the camera sensor a test pattern mode.
> >
> > Signed-off-by: Hirokazu Honda <hiroh@chromium.org>
> > ---
> >  include/libcamera/internal/camera_sensor.h |  1 +
> >  src/libcamera/camera_sensor.cpp            | 39 ++++++++++++++++++++++
> >  2 files changed, 40 insertions(+)
> >
> > diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
> > index e133ebf4..8b9f84c9 100644
> > --- a/include/libcamera/internal/camera_sensor.h
> > +++ b/include/libcamera/internal/camera_sensor.h
> > @@ -43,6 +43,7 @@ public:
> >       {
> >               return testPatternModes_;
> >       }
> > +     int setTestPatternMode(uint8_t testPatternMode);
> >
> >       V4L2SubdeviceFormat getFormat(const std::vector<unsigned int> &mbusCodes,
> >                                     const Size &size) const;
> > diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
> > index 70bbd97a..ce8ff274 100644
> > --- a/src/libcamera/camera_sensor.cpp
> > +++ b/src/libcamera/camera_sensor.cpp
> > @@ -507,6 +507,45 @@ Size CameraSensor::resolution() const
> >   * \return The list of test pattern modes
> >   */
> >
> > +/**
> > + * \brief Set the camera sensor a specified controls::TestPatternMode
>
> Doxygen is puzzling me recently... the testPatternMode paramter is not
> documented but I don't get a warning :/
>
> Also, I'm a bit debated about where to actually place this function
> (or better, it's initTestPatternModes which is misplaced)
> if we have to respect the declaration order or the way you sorted them
> here (which is more logical) is better.
>
> > + *
> > + * \return 0 on success or a negative error code otherwise
> > + */
> > +int CameraSensor::setTestPatternMode(uint8_t testPatternMode)
> > +{
> > +     if (std::find(testPatternModes_.begin(), testPatternModes_.end(),
> > +                   testPatternMode) == testPatternModes_.end()) {
> > +             LOG(CameraSensor, Error) << "Unsupported test pattern mode: "
> > +                                      << testPatternMode;
> > +             return -EINVAL;
> > +     }
>
> Do we need this ? The testPatternModes_ map is constructed using the
> camera sensor properties, the below find() on the props->testPatternModes
> map should gurantee that is supported. Also, if a test pattern mode is
> not reported as part of testPatternModes_ applications shouldn't set
> it...
>
> > +
> > +     const CameraSensorProperties *props = CameraSensorProperties::get(model_);
> > +     if (!props)
> > +             return -EINVAL;
> > +
> > +     auto it = props->testPatternModes.find(testPatternMode);
> > +     ASSERT(it != props->testPatternModes.end());
>
> Yeah, I think the assertion here is more than enough..
>
> > +     const uint8_t index = it->second;
> > +
> > +     ControlList ctrls = getControls({ V4L2_CID_TEST_PATTERN });
> > +     if (ctrls.empty()) {
> > +             LOG(CameraSensor, Error)
> > +                     << "Failed to retrieve test pattern control";
> > +             return -EINVAL;
> > +     }
>
> We won't register the TestPatternMode control in first place the V4L2
> control is not supported..

Replace this with ASSERT.

>
> > +
> > +     ControlValue value = ctrls.get(V4L2_CID_TEST_PATTERN);
> > +     if (value.get<int32_t>() == index)
> > +             return 0;
>
> The V4L2 control framework should take care of this by itself, I think
> we can set the control regardless
>

Yes, I put this in order to save a redundant Ioctl call.
Do you want to remove that?

-Hiro
> > +
> > +     value.set<int32_t>(index);
> > +     ctrls.set(V4L2_CID_TEST_PATTERN, value);
> > +
> > +     return setControls(&ctrls);
> > +}
> > +
> >  /**
> >   * \brief Retrieve the best sensor format for a desired output
> >   * \param[in] mbusCodes The list of acceptable media bus codes
> > --
> > 2.32.0.288.g62a8d224e6-goog
> >
Jacopo Mondi June 23, 2021, 8:07 a.m. UTC | #3
Hi Hiro,

On Wed, Jun 23, 2021 at 04:49:46PM +0900, Hirokazu Honda wrote:
> Hi Jacopo, thank you for reviewing.
>
> On Tue, Jun 22, 2021 at 7:30 PM Jacopo Mondi <jacopo@jmondi.org> wrote:
> >
> > Hi Hiro,
> >
> > On Tue, Jun 22, 2021 at 11:36:51AM +0900, Hirokazu Honda wrote:
> > > Provides a function to set the camera sensor a test pattern mode.
> > >
> > > Signed-off-by: Hirokazu Honda <hiroh@chromium.org>
> > > ---
> > >  include/libcamera/internal/camera_sensor.h |  1 +
> > >  src/libcamera/camera_sensor.cpp            | 39 ++++++++++++++++++++++
> > >  2 files changed, 40 insertions(+)
> > >
> > > diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
> > > index e133ebf4..8b9f84c9 100644
> > > --- a/include/libcamera/internal/camera_sensor.h
> > > +++ b/include/libcamera/internal/camera_sensor.h
> > > @@ -43,6 +43,7 @@ public:
> > >       {
> > >               return testPatternModes_;
> > >       }
> > > +     int setTestPatternMode(uint8_t testPatternMode);
> > >
> > >       V4L2SubdeviceFormat getFormat(const std::vector<unsigned int> &mbusCodes,
> > >                                     const Size &size) const;
> > > diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
> > > index 70bbd97a..ce8ff274 100644
> > > --- a/src/libcamera/camera_sensor.cpp
> > > +++ b/src/libcamera/camera_sensor.cpp
> > > @@ -507,6 +507,45 @@ Size CameraSensor::resolution() const
> > >   * \return The list of test pattern modes
> > >   */
> > >
> > > +/**
> > > + * \brief Set the camera sensor a specified controls::TestPatternMode
> >
> > Doxygen is puzzling me recently... the testPatternMode paramter is not
> > documented but I don't get a warning :/
> >
> > Also, I'm a bit debated about where to actually place this function
> > (or better, it's initTestPatternModes which is misplaced)
> > if we have to respect the declaration order or the way you sorted them
> > here (which is more logical) is better.
> >
> > > + *
> > > + * \return 0 on success or a negative error code otherwise
> > > + */
> > > +int CameraSensor::setTestPatternMode(uint8_t testPatternMode)
> > > +{
> > > +     if (std::find(testPatternModes_.begin(), testPatternModes_.end(),
> > > +                   testPatternMode) == testPatternModes_.end()) {
> > > +             LOG(CameraSensor, Error) << "Unsupported test pattern mode: "
> > > +                                      << testPatternMode;
> > > +             return -EINVAL;
> > > +     }
> >
> > Do we need this ? The testPatternModes_ map is constructed using the
> > camera sensor properties, the below find() on the props->testPatternModes
> > map should gurantee that is supported. Also, if a test pattern mode is
> > not reported as part of testPatternModes_ applications shouldn't set
> > it...
> >
> > > +
> > > +     const CameraSensorProperties *props = CameraSensorProperties::get(model_);
> > > +     if (!props)
> > > +             return -EINVAL;
> > > +
> > > +     auto it = props->testPatternModes.find(testPatternMode);
> > > +     ASSERT(it != props->testPatternModes.end());
> >
> > Yeah, I think the assertion here is more than enough..
> >
> > > +     const uint8_t index = it->second;
> > > +
> > > +     ControlList ctrls = getControls({ V4L2_CID_TEST_PATTERN });
> > > +     if (ctrls.empty()) {
> > > +             LOG(CameraSensor, Error)
> > > +                     << "Failed to retrieve test pattern control";
> > > +             return -EINVAL;
> > > +     }
> >
> > We won't register the TestPatternMode control in first place the V4L2
> > control is not supported..
>
> Replace this with ASSERT.
>
> >
> > > +
> > > +     ControlValue value = ctrls.get(V4L2_CID_TEST_PATTERN);
> > > +     if (value.get<int32_t>() == index)
> > > +             return 0;
> >
> > The V4L2 control framework should take care of this by itself, I think
> > we can set the control regardless
> >
>
> Yes, I put this in order to save a redundant Ioctl call.
> Do you want to remove that?

Well, the ctrls ControlList you create with getControls() goes through
an IOCTL :) We're talking details, but if we want to retain the
state of the testPatterMode we can make it a class member, so that the
code can be reduced to (not tested pseudo-code)

{
     if (testPatternMode == testPatternMode_)
           return 0;

     const CameraSensorProperties *props = CameraSensorProperties::get(model_);
     if (!props)
             return -EINVAL;

     auto it = props->testPatternModes.find(testPatternMode);
     ASSERT(it != props->testPatternModes.end());

     ControlList ctrls(controls());
     ctrls.set(V4L2_CID_TEST_PATTERN, it->second);

     int ret = setControls(&ctrls);
     if (ret)
            return ret;

     testPatternMode_ = testPatternMode;

     return 0;
}

I also wonder if the ASSERT() is not too harsh and we shouldn't just
error out. If the application tries to set an unsupported test pattern,
the whole library would crash, maybe we should be a little more
indulgent.

Thanks
   j

>
> -Hiro
> > > +
> > > +     value.set<int32_t>(index);
> > > +     ctrls.set(V4L2_CID_TEST_PATTERN, value);
> > > +
> > > +     return setControls(&ctrls);
> > > +}
> > > +
> > >  /**
> > >   * \brief Retrieve the best sensor format for a desired output
> > >   * \param[in] mbusCodes The list of acceptable media bus codes
> > > --
> > > 2.32.0.288.g62a8d224e6-goog
> > >
Hirokazu Honda June 23, 2021, 8:27 a.m. UTC | #4
Hi Jacopo,

On Wed, Jun 23, 2021 at 5:06 PM Jacopo Mondi <jacopo@jmondi.org> wrote:
>
> Hi Hiro,
>
> On Wed, Jun 23, 2021 at 04:49:46PM +0900, Hirokazu Honda wrote:
> > Hi Jacopo, thank you for reviewing.
> >
> > On Tue, Jun 22, 2021 at 7:30 PM Jacopo Mondi <jacopo@jmondi.org> wrote:
> > >
> > > Hi Hiro,
> > >
> > > On Tue, Jun 22, 2021 at 11:36:51AM +0900, Hirokazu Honda wrote:
> > > > Provides a function to set the camera sensor a test pattern mode.
> > > >
> > > > Signed-off-by: Hirokazu Honda <hiroh@chromium.org>
> > > > ---
> > > >  include/libcamera/internal/camera_sensor.h |  1 +
> > > >  src/libcamera/camera_sensor.cpp            | 39 ++++++++++++++++++++++
> > > >  2 files changed, 40 insertions(+)
> > > >
> > > > diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
> > > > index e133ebf4..8b9f84c9 100644
> > > > --- a/include/libcamera/internal/camera_sensor.h
> > > > +++ b/include/libcamera/internal/camera_sensor.h
> > > > @@ -43,6 +43,7 @@ public:
> > > >       {
> > > >               return testPatternModes_;
> > > >       }
> > > > +     int setTestPatternMode(uint8_t testPatternMode);
> > > >
> > > >       V4L2SubdeviceFormat getFormat(const std::vector<unsigned int> &mbusCodes,
> > > >                                     const Size &size) const;
> > > > diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
> > > > index 70bbd97a..ce8ff274 100644
> > > > --- a/src/libcamera/camera_sensor.cpp
> > > > +++ b/src/libcamera/camera_sensor.cpp
> > > > @@ -507,6 +507,45 @@ Size CameraSensor::resolution() const
> > > >   * \return The list of test pattern modes
> > > >   */
> > > >
> > > > +/**
> > > > + * \brief Set the camera sensor a specified controls::TestPatternMode
> > >
> > > Doxygen is puzzling me recently... the testPatternMode paramter is not
> > > documented but I don't get a warning :/
> > >
> > > Also, I'm a bit debated about where to actually place this function
> > > (or better, it's initTestPatternModes which is misplaced)
> > > if we have to respect the declaration order or the way you sorted them
> > > here (which is more logical) is better.
> > >
> > > > + *
> > > > + * \return 0 on success or a negative error code otherwise
> > > > + */
> > > > +int CameraSensor::setTestPatternMode(uint8_t testPatternMode)
> > > > +{
> > > > +     if (std::find(testPatternModes_.begin(), testPatternModes_.end(),
> > > > +                   testPatternMode) == testPatternModes_.end()) {
> > > > +             LOG(CameraSensor, Error) << "Unsupported test pattern mode: "
> > > > +                                      << testPatternMode;
> > > > +             return -EINVAL;
> > > > +     }
> > >
> > > Do we need this ? The testPatternModes_ map is constructed using the
> > > camera sensor properties, the below find() on the props->testPatternModes
> > > map should gurantee that is supported. Also, if a test pattern mode is
> > > not reported as part of testPatternModes_ applications shouldn't set
> > > it...
> > >
> > > > +
> > > > +     const CameraSensorProperties *props = CameraSensorProperties::get(model_);
> > > > +     if (!props)
> > > > +             return -EINVAL;
> > > > +
> > > > +     auto it = props->testPatternModes.find(testPatternMode);
> > > > +     ASSERT(it != props->testPatternModes.end());
> > >
> > > Yeah, I think the assertion here is more than enough..
> > >
> > > > +     const uint8_t index = it->second;
> > > > +
> > > > +     ControlList ctrls = getControls({ V4L2_CID_TEST_PATTERN });
> > > > +     if (ctrls.empty()) {
> > > > +             LOG(CameraSensor, Error)
> > > > +                     << "Failed to retrieve test pattern control";
> > > > +             return -EINVAL;
> > > > +     }
> > >
> > > We won't register the TestPatternMode control in first place the V4L2
> > > control is not supported..
> >
> > Replace this with ASSERT.
> >
> > >
> > > > +
> > > > +     ControlValue value = ctrls.get(V4L2_CID_TEST_PATTERN);
> > > > +     if (value.get<int32_t>() == index)
> > > > +             return 0;
> > >
> > > The V4L2 control framework should take care of this by itself, I think
> > > we can set the control regardless
> > >
> >
> > Yes, I put this in order to save a redundant Ioctl call.
> > Do you want to remove that?
>
> Well, the ctrls ControlList you create with getControls() goes through
> an IOCTL :) We're talking details, but if we want to retain the
> state of the testPatterMode we can make it a class member, so that the
> code can be reduced to (not tested pseudo-code)
>
> {
>      if (testPatternMode == testPatternMode_)
>            return 0;
>
>      const CameraSensorProperties *props = CameraSensorProperties::get(model_);
>      if (!props)
>              return -EINVAL;
>
>      auto it = props->testPatternModes.find(testPatternMode);
>      ASSERT(it != props->testPatternModes.end());
>
>      ControlList ctrls(controls());
>      ctrls.set(V4L2_CID_TEST_PATTERN, it->second);
>
>      int ret = setControls(&ctrls);
>      if (ret)
>             return ret;
>
>      testPatternMode_ = testPatternMode;
>
>      return 0;
> }
>
> I also wonder if the ASSERT() is not too harsh and we shouldn't just
> error out. If the application tries to set an unsupported test pattern,
> the whole library would crash, maybe we should be a little more
> indulgent.
>

I see what you meant. Thanks!

> Thanks
>    j
>
> >
> > -Hiro
> > > > +
> > > > +     value.set<int32_t>(index);
> > > > +     ctrls.set(V4L2_CID_TEST_PATTERN, value);
> > > > +
> > > > +     return setControls(&ctrls);
> > > > +}
> > > > +
> > > >  /**
> > > >   * \brief Retrieve the best sensor format for a desired output
> > > >   * \param[in] mbusCodes The list of acceptable media bus codes
> > > > --
> > > > 2.32.0.288.g62a8d224e6-goog
> > > >
Laurent Pinchart June 28, 2021, 3:12 a.m. UTC | #5
Hi Jacopo,

Thank you for the patch.

On Wed, Jun 23, 2021 at 10:07:04AM +0200, Jacopo Mondi wrote:
> On Wed, Jun 23, 2021 at 04:49:46PM +0900, Hirokazu Honda wrote:
> > On Tue, Jun 22, 2021 at 7:30 PM Jacopo Mondi wrote:
> > > On Tue, Jun 22, 2021 at 11:36:51AM +0900, Hirokazu Honda wrote:
> > > > Provides a function to set the camera sensor a test pattern mode.
> > > >
> > > > Signed-off-by: Hirokazu Honda <hiroh@chromium.org>
> > > > ---
> > > >  include/libcamera/internal/camera_sensor.h |  1 +
> > > >  src/libcamera/camera_sensor.cpp            | 39 ++++++++++++++++++++++
> > > >  2 files changed, 40 insertions(+)
> > > >
> > > > diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
> > > > index e133ebf4..8b9f84c9 100644
> > > > --- a/include/libcamera/internal/camera_sensor.h
> > > > +++ b/include/libcamera/internal/camera_sensor.h
> > > > @@ -43,6 +43,7 @@ public:
> > > >       {
> > > >               return testPatternModes_;
> > > >       }
> > > > +     int setTestPatternMode(uint8_t testPatternMode);
> > > >
> > > >       V4L2SubdeviceFormat getFormat(const std::vector<unsigned int> &mbusCodes,
> > > >                                     const Size &size) const;
> > > > diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
> > > > index 70bbd97a..ce8ff274 100644
> > > > --- a/src/libcamera/camera_sensor.cpp
> > > > +++ b/src/libcamera/camera_sensor.cpp
> > > > @@ -507,6 +507,45 @@ Size CameraSensor::resolution() const
> > > >   * \return The list of test pattern modes
> > > >   */
> > > >
> > > > +/**
> > > > + * \brief Set the camera sensor a specified controls::TestPatternMode
> > >
> > > Doxygen is puzzling me recently... the testPatternMode paramter is not
> > > documented but I don't get a warning :/
> > >
> > > Also, I'm a bit debated about where to actually place this function
> > > (or better, it's initTestPatternModes which is misplaced)
> > > if we have to respect the declaration order or the way you sorted them
> > > here (which is more logical) is better.
> > >
> > > > + *
> > > > + * \return 0 on success or a negative error code otherwise
> > > > + */
> > > > +int CameraSensor::setTestPatternMode(uint8_t testPatternMode)
> > > > +{
> > > > +     if (std::find(testPatternModes_.begin(), testPatternModes_.end(),
> > > > +                   testPatternMode) == testPatternModes_.end()) {
> > > > +             LOG(CameraSensor, Error) << "Unsupported test pattern mode: "
> > > > +                                      << testPatternMode;
> > > > +             return -EINVAL;
> > > > +     }
> > >
> > > Do we need this ? The testPatternModes_ map is constructed using the
> > > camera sensor properties, the below find() on the props->testPatternModes
> > > map should gurantee that is supported. Also, if a test pattern mode is
> > > not reported as part of testPatternModes_ applications shouldn't set
> > > it...
> > >
> > > > +
> > > > +     const CameraSensorProperties *props = CameraSensorProperties::get(model_);
> > > > +     if (!props)
> > > > +             return -EINVAL;

We already retrieve this in CameraSensor::initStaticProperties(), let's
cache the pointer in the CameraSensor class.

> > > > +
> > > > +     auto it = props->testPatternModes.find(testPatternMode);
> > > > +     ASSERT(it != props->testPatternModes.end());
> > >
> > > Yeah, I think the assertion here is more than enough..
> > >
> > > > +     const uint8_t index = it->second;
> > > > +
> > > > +     ControlList ctrls = getControls({ V4L2_CID_TEST_PATTERN });
> > > > +     if (ctrls.empty()) {
> > > > +             LOG(CameraSensor, Error)
> > > > +                     << "Failed to retrieve test pattern control";
> > > > +             return -EINVAL;
> > > > +     }
> > >
> > > We won't register the TestPatternMode control in first place the V4L2
> > > control is not supported..
> >
> > Replace this with ASSERT.
> >
> > > > +
> > > > +     ControlValue value = ctrls.get(V4L2_CID_TEST_PATTERN);
> > > > +     if (value.get<int32_t>() == index)
> > > > +             return 0;
> > >
> > > The V4L2 control framework should take care of this by itself, I think
> > > we can set the control regardless
> >
> > Yes, I put this in order to save a redundant Ioctl call.
> > Do you want to remove that?
> 
> Well, the ctrls ControlList you create with getControls() goes through
> an IOCTL :) We're talking details, but if we want to retain the
> state of the testPatterMode we can make it a class member, so that the
> code can be reduced to (not tested pseudo-code)
> 
> {
>      if (testPatternMode == testPatternMode_)
>            return 0;
> 
>      const CameraSensorProperties *props = CameraSensorProperties::get(model_);
>      if (!props)
>              return -EINVAL;
> 
>      auto it = props->testPatternModes.find(testPatternMode);
>      ASSERT(it != props->testPatternModes.end());
> 
>      ControlList ctrls(controls());
>      ctrls.set(V4L2_CID_TEST_PATTERN, it->second);
> 
>      int ret = setControls(&ctrls);
>      if (ret)
>             return ret;
> 
>      testPatternMode_ = testPatternMode;
> 
>      return 0;
> }
> 
> I also wonder if the ASSERT() is not too harsh and we shouldn't just
> error out. If the application tries to set an unsupported test pattern,
> the whole library would crash, maybe we should be a little more
> indulgent.

Yes, not crashing is a good idea :-)

> > > > +
> > > > +     value.set<int32_t>(index);
> > > > +     ctrls.set(V4L2_CID_TEST_PATTERN, value);
> > > > +
> > > > +     return setControls(&ctrls);
> > > > +}
> > > > +
> > > >  /**
> > > >   * \brief Retrieve the best sensor format for a desired output
> > > >   * \param[in] mbusCodes The list of acceptable media bus codes
Laurent Pinchart June 28, 2021, 3:28 a.m. UTC | #6
On Mon, Jun 28, 2021 at 06:12:32AM +0300, Laurent Pinchart wrote:
> Hi Jacopo,
> 
> Thank you for the patch.

The patch is from Hiro of course :-)

Another comment, do we need such a ad-hoc function, or could we handle
the test pattern mode using a more generic interface, with a ControlList
? The CameraSensor::setControls() takes V4L2 controls today, which makes
it unsuitable for this purpose. I would ideally like to see all this
fixed, but I suppose it's a too big task for this series. It adds up to
the technical debt though, so there's a high chance that I'll push back
more strongly on the next patch that adds a ad-hoc function to
CameraSensor, until we reach a point where the push back will be a
strong nack and all this will need to be refactored by an unlucky
person. All this means that nobody should think that delaying the
handling of technical debt is a smart move to move it to someone else's
plate, it may come back around :-)

> On Wed, Jun 23, 2021 at 10:07:04AM +0200, Jacopo Mondi wrote:
> > On Wed, Jun 23, 2021 at 04:49:46PM +0900, Hirokazu Honda wrote:
> > > On Tue, Jun 22, 2021 at 7:30 PM Jacopo Mondi wrote:
> > > > On Tue, Jun 22, 2021 at 11:36:51AM +0900, Hirokazu Honda wrote:
> > > > > Provides a function to set the camera sensor a test pattern mode.
> > > > >
> > > > > Signed-off-by: Hirokazu Honda <hiroh@chromium.org>
> > > > > ---
> > > > >  include/libcamera/internal/camera_sensor.h |  1 +
> > > > >  src/libcamera/camera_sensor.cpp            | 39 ++++++++++++++++++++++
> > > > >  2 files changed, 40 insertions(+)
> > > > >
> > > > > diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
> > > > > index e133ebf4..8b9f84c9 100644
> > > > > --- a/include/libcamera/internal/camera_sensor.h
> > > > > +++ b/include/libcamera/internal/camera_sensor.h
> > > > > @@ -43,6 +43,7 @@ public:
> > > > >       {
> > > > >               return testPatternModes_;
> > > > >       }
> > > > > +     int setTestPatternMode(uint8_t testPatternMode);
> > > > >
> > > > >       V4L2SubdeviceFormat getFormat(const std::vector<unsigned int> &mbusCodes,
> > > > >                                     const Size &size) const;
> > > > > diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
> > > > > index 70bbd97a..ce8ff274 100644
> > > > > --- a/src/libcamera/camera_sensor.cpp
> > > > > +++ b/src/libcamera/camera_sensor.cpp
> > > > > @@ -507,6 +507,45 @@ Size CameraSensor::resolution() const
> > > > >   * \return The list of test pattern modes
> > > > >   */
> > > > >
> > > > > +/**
> > > > > + * \brief Set the camera sensor a specified controls::TestPatternMode
> > > >
> > > > Doxygen is puzzling me recently... the testPatternMode paramter is not
> > > > documented but I don't get a warning :/
> > > >
> > > > Also, I'm a bit debated about where to actually place this function
> > > > (or better, it's initTestPatternModes which is misplaced)
> > > > if we have to respect the declaration order or the way you sorted them
> > > > here (which is more logical) is better.
> > > >
> > > > > + *
> > > > > + * \return 0 on success or a negative error code otherwise
> > > > > + */
> > > > > +int CameraSensor::setTestPatternMode(uint8_t testPatternMode)
> > > > > +{
> > > > > +     if (std::find(testPatternModes_.begin(), testPatternModes_.end(),
> > > > > +                   testPatternMode) == testPatternModes_.end()) {
> > > > > +             LOG(CameraSensor, Error) << "Unsupported test pattern mode: "
> > > > > +                                      << testPatternMode;
> > > > > +             return -EINVAL;
> > > > > +     }
> > > >
> > > > Do we need this ? The testPatternModes_ map is constructed using the
> > > > camera sensor properties, the below find() on the props->testPatternModes
> > > > map should gurantee that is supported. Also, if a test pattern mode is
> > > > not reported as part of testPatternModes_ applications shouldn't set
> > > > it...
> > > >
> > > > > +
> > > > > +     const CameraSensorProperties *props = CameraSensorProperties::get(model_);
> > > > > +     if (!props)
> > > > > +             return -EINVAL;
> 
> We already retrieve this in CameraSensor::initStaticProperties(), let's
> cache the pointer in the CameraSensor class.
> 
> > > > > +
> > > > > +     auto it = props->testPatternModes.find(testPatternMode);
> > > > > +     ASSERT(it != props->testPatternModes.end());
> > > >
> > > > Yeah, I think the assertion here is more than enough..
> > > >
> > > > > +     const uint8_t index = it->second;
> > > > > +
> > > > > +     ControlList ctrls = getControls({ V4L2_CID_TEST_PATTERN });
> > > > > +     if (ctrls.empty()) {
> > > > > +             LOG(CameraSensor, Error)
> > > > > +                     << "Failed to retrieve test pattern control";
> > > > > +             return -EINVAL;
> > > > > +     }
> > > >
> > > > We won't register the TestPatternMode control in first place the V4L2
> > > > control is not supported..
> > >
> > > Replace this with ASSERT.
> > >
> > > > > +
> > > > > +     ControlValue value = ctrls.get(V4L2_CID_TEST_PATTERN);
> > > > > +     if (value.get<int32_t>() == index)
> > > > > +             return 0;
> > > >
> > > > The V4L2 control framework should take care of this by itself, I think
> > > > we can set the control regardless
> > >
> > > Yes, I put this in order to save a redundant Ioctl call.
> > > Do you want to remove that?
> > 
> > Well, the ctrls ControlList you create with getControls() goes through
> > an IOCTL :) We're talking details, but if we want to retain the
> > state of the testPatterMode we can make it a class member, so that the
> > code can be reduced to (not tested pseudo-code)
> > 
> > {
> >      if (testPatternMode == testPatternMode_)
> >            return 0;
> > 
> >      const CameraSensorProperties *props = CameraSensorProperties::get(model_);
> >      if (!props)
> >              return -EINVAL;
> > 
> >      auto it = props->testPatternModes.find(testPatternMode);
> >      ASSERT(it != props->testPatternModes.end());
> > 
> >      ControlList ctrls(controls());
> >      ctrls.set(V4L2_CID_TEST_PATTERN, it->second);
> > 
> >      int ret = setControls(&ctrls);
> >      if (ret)
> >             return ret;
> > 
> >      testPatternMode_ = testPatternMode;
> > 
> >      return 0;
> > }
> > 
> > I also wonder if the ASSERT() is not too harsh and we shouldn't just
> > error out. If the application tries to set an unsupported test pattern,
> > the whole library would crash, maybe we should be a little more
> > indulgent.
> 
> Yes, not crashing is a good idea :-)
> 
> > > > > +
> > > > > +     value.set<int32_t>(index);
> > > > > +     ctrls.set(V4L2_CID_TEST_PATTERN, value);
> > > > > +
> > > > > +     return setControls(&ctrls);
> > > > > +}
> > > > > +
> > > > >  /**
> > > > >   * \brief Retrieve the best sensor format for a desired output
> > > > >   * \param[in] mbusCodes The list of acceptable media bus codes
Hirokazu Honda June 28, 2021, 5:16 a.m. UTC | #7
Hi Laurent,

On Mon, Jun 28, 2021 at 12:28 PM Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> On Mon, Jun 28, 2021 at 06:12:32AM +0300, Laurent Pinchart wrote:
> > Hi Jacopo,
> >
> > Thank you for the patch.
>
> The patch is from Hiro of course :-)
>
> Another comment, do we need such a ad-hoc function, or could we handle
> the test pattern mode using a more generic interface, with a ControlList
> ? The CameraSensor::setControls() takes V4L2 controls today, which makes
> it unsuitable for this purpose. I would ideally like to see all this
> fixed, but I suppose it's a too big task for this series. It adds up to
> the technical debt though, so there's a high chance that I'll push back
> more strongly on the next patch that adds a ad-hoc function to
> CameraSensor, until we reach a point where the push back will be a
> strong nack and all this will need to be refactored by an unlucky
> person. All this means that nobody should think that delaying the
> handling of technical debt is a smart move to move it to someone else's
> plate, it may come back around :-)
>

If we want to use CameraSensor::setControls(), it is necessary for a
pipeline handler to know the v4l2 index associated with a specific
test pattern mode.
How can we do that? Is it okay for a pipeline handler to read test
pattern mode in camera properties?

> > On Wed, Jun 23, 2021 at 10:07:04AM +0200, Jacopo Mondi wrote:
> > > On Wed, Jun 23, 2021 at 04:49:46PM +0900, Hirokazu Honda wrote:
> > > > On Tue, Jun 22, 2021 at 7:30 PM Jacopo Mondi wrote:
> > > > > On Tue, Jun 22, 2021 at 11:36:51AM +0900, Hirokazu Honda wrote:
> > > > > > Provides a function to set the camera sensor a test pattern mode.
> > > > > >
> > > > > > Signed-off-by: Hirokazu Honda <hiroh@chromium.org>
> > > > > > ---
> > > > > >  include/libcamera/internal/camera_sensor.h |  1 +
> > > > > >  src/libcamera/camera_sensor.cpp            | 39 ++++++++++++++++++++++
> > > > > >  2 files changed, 40 insertions(+)
> > > > > >
> > > > > > diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
> > > > > > index e133ebf4..8b9f84c9 100644
> > > > > > --- a/include/libcamera/internal/camera_sensor.h
> > > > > > +++ b/include/libcamera/internal/camera_sensor.h
> > > > > > @@ -43,6 +43,7 @@ public:
> > > > > >       {
> > > > > >               return testPatternModes_;
> > > > > >       }
> > > > > > +     int setTestPatternMode(uint8_t testPatternMode);
> > > > > >
> > > > > >       V4L2SubdeviceFormat getFormat(const std::vector<unsigned int> &mbusCodes,
> > > > > >                                     const Size &size) const;
> > > > > > diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
> > > > > > index 70bbd97a..ce8ff274 100644
> > > > > > --- a/src/libcamera/camera_sensor.cpp
> > > > > > +++ b/src/libcamera/camera_sensor.cpp
> > > > > > @@ -507,6 +507,45 @@ Size CameraSensor::resolution() const
> > > > > >   * \return The list of test pattern modes
> > > > > >   */
> > > > > >
> > > > > > +/**
> > > > > > + * \brief Set the camera sensor a specified controls::TestPatternMode
> > > > >
> > > > > Doxygen is puzzling me recently... the testPatternMode paramter is not
> > > > > documented but I don't get a warning :/
> > > > >
> > > > > Also, I'm a bit debated about where to actually place this function
> > > > > (or better, it's initTestPatternModes which is misplaced)
> > > > > if we have to respect the declaration order or the way you sorted them
> > > > > here (which is more logical) is better.
> > > > >
> > > > > > + *
> > > > > > + * \return 0 on success or a negative error code otherwise
> > > > > > + */
> > > > > > +int CameraSensor::setTestPatternMode(uint8_t testPatternMode)
> > > > > > +{
> > > > > > +     if (std::find(testPatternModes_.begin(), testPatternModes_.end(),
> > > > > > +                   testPatternMode) == testPatternModes_.end()) {
> > > > > > +             LOG(CameraSensor, Error) << "Unsupported test pattern mode: "
> > > > > > +                                      << testPatternMode;
> > > > > > +             return -EINVAL;
> > > > > > +     }
> > > > >
> > > > > Do we need this ? The testPatternModes_ map is constructed using the
> > > > > camera sensor properties, the below find() on the props->testPatternModes
> > > > > map should gurantee that is supported. Also, if a test pattern mode is
> > > > > not reported as part of testPatternModes_ applications shouldn't set
> > > > > it...
> > > > >
> > > > > > +
> > > > > > +     const CameraSensorProperties *props = CameraSensorProperties::get(model_);
> > > > > > +     if (!props)
> > > > > > +             return -EINVAL;
> >
> > We already retrieve this in CameraSensor::initStaticProperties(), let's
> > cache the pointer in the CameraSensor class.
> >
> > > > > > +
> > > > > > +     auto it = props->testPatternModes.find(testPatternMode);
> > > > > > +     ASSERT(it != props->testPatternModes.end());
> > > > >
> > > > > Yeah, I think the assertion here is more than enough..
> > > > >
> > > > > > +     const uint8_t index = it->second;
> > > > > > +
> > > > > > +     ControlList ctrls = getControls({ V4L2_CID_TEST_PATTERN });
> > > > > > +     if (ctrls.empty()) {
> > > > > > +             LOG(CameraSensor, Error)
> > > > > > +                     << "Failed to retrieve test pattern control";
> > > > > > +             return -EINVAL;
> > > > > > +     }
> > > > >
> > > > > We won't register the TestPatternMode control in first place the V4L2
> > > > > control is not supported..
> > > >
> > > > Replace this with ASSERT.
> > > >
> > > > > > +
> > > > > > +     ControlValue value = ctrls.get(V4L2_CID_TEST_PATTERN);
> > > > > > +     if (value.get<int32_t>() == index)
> > > > > > +             return 0;
> > > > >
> > > > > The V4L2 control framework should take care of this by itself, I think
> > > > > we can set the control regardless
> > > >
> > > > Yes, I put this in order to save a redundant Ioctl call.
> > > > Do you want to remove that?
> > >
> > > Well, the ctrls ControlList you create with getControls() goes through
> > > an IOCTL :) We're talking details, but if we want to retain the
> > > state of the testPatterMode we can make it a class member, so that the
> > > code can be reduced to (not tested pseudo-code)
> > >
> > > {
> > >      if (testPatternMode == testPatternMode_)
> > >            return 0;
> > >
> > >      const CameraSensorProperties *props = CameraSensorProperties::get(model_);
> > >      if (!props)
> > >              return -EINVAL;
> > >
> > >      auto it = props->testPatternModes.find(testPatternMode);
> > >      ASSERT(it != props->testPatternModes.end());
> > >
> > >      ControlList ctrls(controls());
> > >      ctrls.set(V4L2_CID_TEST_PATTERN, it->second);
> > >
> > >      int ret = setControls(&ctrls);
> > >      if (ret)
> > >             return ret;
> > >
> > >      testPatternMode_ = testPatternMode;
> > >
> > >      return 0;
> > > }
> > >
> > > I also wonder if the ASSERT() is not too harsh and we shouldn't just
> > > error out. If the application tries to set an unsupported test pattern,
> > > the whole library would crash, maybe we should be a little more
> > > indulgent.
> >
> > Yes, not crashing is a good idea :-)
> >
> > > > > > +
> > > > > > +     value.set<int32_t>(index);
> > > > > > +     ctrls.set(V4L2_CID_TEST_PATTERN, value);
> > > > > > +
> > > > > > +     return setControls(&ctrls);
> > > > > > +}
> > > > > > +
> > > > > >  /**
> > > > > >   * \brief Retrieve the best sensor format for a desired output
> > > > > >   * \param[in] mbusCodes The list of acceptable media bus codes
>
> --
> Regards,
>
> Laurent Pinchart
Laurent Pinchart June 28, 2021, 5:26 a.m. UTC | #8
Hi Hiro,

On Mon, Jun 28, 2021 at 02:16:00PM +0900, Hirokazu Honda wrote:
> On Mon, Jun 28, 2021 at 12:28 PM Laurent Pinchart wrote:
> > On Mon, Jun 28, 2021 at 06:12:32AM +0300, Laurent Pinchart wrote:
> > > Hi Jacopo,
> > >
> > > Thank you for the patch.
> >
> > The patch is from Hiro of course :-)
> >
> > Another comment, do we need such a ad-hoc function, or could we handle
> > the test pattern mode using a more generic interface, with a ControlList
> > ? The CameraSensor::setControls() takes V4L2 controls today, which makes
> > it unsuitable for this purpose. I would ideally like to see all this
> > fixed, but I suppose it's a too big task for this series. It adds up to
> > the technical debt though, so there's a high chance that I'll push back
> > more strongly on the next patch that adds a ad-hoc function to
> > CameraSensor, until we reach a point where the push back will be a
> > strong nack and all this will need to be refactored by an unlucky
> > person. All this means that nobody should think that delaying the
> > handling of technical debt is a smart move to move it to someone else's
> > plate, it may come back around :-)
> 
> If we want to use CameraSensor::setControls(), it is necessary for a
> pipeline handler to know the v4l2 index associated with a specific
> test pattern mode.
> How can we do that? Is it okay for a pipeline handler to read test
> pattern mode in camera properties?

I'd prefer going the other way around and avoid exposing V4L2 controls
from CameraSensor. I haven't really thought about how to do so yet
though.

> > > On Wed, Jun 23, 2021 at 10:07:04AM +0200, Jacopo Mondi wrote:
> > > > On Wed, Jun 23, 2021 at 04:49:46PM +0900, Hirokazu Honda wrote:
> > > > > On Tue, Jun 22, 2021 at 7:30 PM Jacopo Mondi wrote:
> > > > > > On Tue, Jun 22, 2021 at 11:36:51AM +0900, Hirokazu Honda wrote:
> > > > > > > Provides a function to set the camera sensor a test pattern mode.
> > > > > > >
> > > > > > > Signed-off-by: Hirokazu Honda <hiroh@chromium.org>
> > > > > > > ---
> > > > > > >  include/libcamera/internal/camera_sensor.h |  1 +
> > > > > > >  src/libcamera/camera_sensor.cpp            | 39 ++++++++++++++++++++++
> > > > > > >  2 files changed, 40 insertions(+)
> > > > > > >
> > > > > > > diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
> > > > > > > index e133ebf4..8b9f84c9 100644
> > > > > > > --- a/include/libcamera/internal/camera_sensor.h
> > > > > > > +++ b/include/libcamera/internal/camera_sensor.h
> > > > > > > @@ -43,6 +43,7 @@ public:
> > > > > > >       {
> > > > > > >               return testPatternModes_;
> > > > > > >       }
> > > > > > > +     int setTestPatternMode(uint8_t testPatternMode);
> > > > > > >
> > > > > > >       V4L2SubdeviceFormat getFormat(const std::vector<unsigned int> &mbusCodes,
> > > > > > >                                     const Size &size) const;
> > > > > > > diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
> > > > > > > index 70bbd97a..ce8ff274 100644
> > > > > > > --- a/src/libcamera/camera_sensor.cpp
> > > > > > > +++ b/src/libcamera/camera_sensor.cpp
> > > > > > > @@ -507,6 +507,45 @@ Size CameraSensor::resolution() const
> > > > > > >   * \return The list of test pattern modes
> > > > > > >   */
> > > > > > >
> > > > > > > +/**
> > > > > > > + * \brief Set the camera sensor a specified controls::TestPatternMode
> > > > > >
> > > > > > Doxygen is puzzling me recently... the testPatternMode paramter is not
> > > > > > documented but I don't get a warning :/
> > > > > >
> > > > > > Also, I'm a bit debated about where to actually place this function
> > > > > > (or better, it's initTestPatternModes which is misplaced)
> > > > > > if we have to respect the declaration order or the way you sorted them
> > > > > > here (which is more logical) is better.
> > > > > >
> > > > > > > + *
> > > > > > > + * \return 0 on success or a negative error code otherwise
> > > > > > > + */
> > > > > > > +int CameraSensor::setTestPatternMode(uint8_t testPatternMode)
> > > > > > > +{
> > > > > > > +     if (std::find(testPatternModes_.begin(), testPatternModes_.end(),
> > > > > > > +                   testPatternMode) == testPatternModes_.end()) {
> > > > > > > +             LOG(CameraSensor, Error) << "Unsupported test pattern mode: "
> > > > > > > +                                      << testPatternMode;
> > > > > > > +             return -EINVAL;
> > > > > > > +     }
> > > > > >
> > > > > > Do we need this ? The testPatternModes_ map is constructed using the
> > > > > > camera sensor properties, the below find() on the props->testPatternModes
> > > > > > map should gurantee that is supported. Also, if a test pattern mode is
> > > > > > not reported as part of testPatternModes_ applications shouldn't set
> > > > > > it...
> > > > > >
> > > > > > > +
> > > > > > > +     const CameraSensorProperties *props = CameraSensorProperties::get(model_);
> > > > > > > +     if (!props)
> > > > > > > +             return -EINVAL;
> > >
> > > We already retrieve this in CameraSensor::initStaticProperties(), let's
> > > cache the pointer in the CameraSensor class.
> > >
> > > > > > > +
> > > > > > > +     auto it = props->testPatternModes.find(testPatternMode);
> > > > > > > +     ASSERT(it != props->testPatternModes.end());
> > > > > >
> > > > > > Yeah, I think the assertion here is more than enough..
> > > > > >
> > > > > > > +     const uint8_t index = it->second;
> > > > > > > +
> > > > > > > +     ControlList ctrls = getControls({ V4L2_CID_TEST_PATTERN });
> > > > > > > +     if (ctrls.empty()) {
> > > > > > > +             LOG(CameraSensor, Error)
> > > > > > > +                     << "Failed to retrieve test pattern control";
> > > > > > > +             return -EINVAL;
> > > > > > > +     }
> > > > > >
> > > > > > We won't register the TestPatternMode control in first place the V4L2
> > > > > > control is not supported..
> > > > >
> > > > > Replace this with ASSERT.
> > > > >
> > > > > > > +
> > > > > > > +     ControlValue value = ctrls.get(V4L2_CID_TEST_PATTERN);
> > > > > > > +     if (value.get<int32_t>() == index)
> > > > > > > +             return 0;
> > > > > >
> > > > > > The V4L2 control framework should take care of this by itself, I think
> > > > > > we can set the control regardless
> > > > >
> > > > > Yes, I put this in order to save a redundant Ioctl call.
> > > > > Do you want to remove that?
> > > >
> > > > Well, the ctrls ControlList you create with getControls() goes through
> > > > an IOCTL :) We're talking details, but if we want to retain the
> > > > state of the testPatterMode we can make it a class member, so that the
> > > > code can be reduced to (not tested pseudo-code)
> > > >
> > > > {
> > > >      if (testPatternMode == testPatternMode_)
> > > >            return 0;
> > > >
> > > >      const CameraSensorProperties *props = CameraSensorProperties::get(model_);
> > > >      if (!props)
> > > >              return -EINVAL;
> > > >
> > > >      auto it = props->testPatternModes.find(testPatternMode);
> > > >      ASSERT(it != props->testPatternModes.end());
> > > >
> > > >      ControlList ctrls(controls());
> > > >      ctrls.set(V4L2_CID_TEST_PATTERN, it->second);
> > > >
> > > >      int ret = setControls(&ctrls);
> > > >      if (ret)
> > > >             return ret;
> > > >
> > > >      testPatternMode_ = testPatternMode;
> > > >
> > > >      return 0;
> > > > }
> > > >
> > > > I also wonder if the ASSERT() is not too harsh and we shouldn't just
> > > > error out. If the application tries to set an unsupported test pattern,
> > > > the whole library would crash, maybe we should be a little more
> > > > indulgent.
> > >
> > > Yes, not crashing is a good idea :-)
> > >
> > > > > > > +
> > > > > > > +     value.set<int32_t>(index);
> > > > > > > +     ctrls.set(V4L2_CID_TEST_PATTERN, value);
> > > > > > > +
> > > > > > > +     return setControls(&ctrls);
> > > > > > > +}
> > > > > > > +
> > > > > > >  /**
> > > > > > >   * \brief Retrieve the best sensor format for a desired output
> > > > > > >   * \param[in] mbusCodes The list of acceptable media bus codes
Hirokazu Honda June 28, 2021, 5:33 a.m. UTC | #9
Hi Laurent,

On Mon, Jun 28, 2021 at 2:26 PM Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> Hi Hiro,
>
> On Mon, Jun 28, 2021 at 02:16:00PM +0900, Hirokazu Honda wrote:
> > On Mon, Jun 28, 2021 at 12:28 PM Laurent Pinchart wrote:
> > > On Mon, Jun 28, 2021 at 06:12:32AM +0300, Laurent Pinchart wrote:
> > > > Hi Jacopo,
> > > >
> > > > Thank you for the patch.
> > >
> > > The patch is from Hiro of course :-)
> > >
> > > Another comment, do we need such a ad-hoc function, or could we handle
> > > the test pattern mode using a more generic interface, with a ControlList
> > > ? The CameraSensor::setControls() takes V4L2 controls today, which makes
> > > it unsuitable for this purpose. I would ideally like to see all this
> > > fixed, but I suppose it's a too big task for this series. It adds up to
> > > the technical debt though, so there's a high chance that I'll push back
> > > more strongly on the next patch that adds a ad-hoc function to
> > > CameraSensor, until we reach a point where the push back will be a
> > > strong nack and all this will need to be refactored by an unlucky
> > > person. All this means that nobody should think that delaying the
> > > handling of technical debt is a smart move to move it to someone else's
> > > plate, it may come back around :-)
> >
> > If we want to use CameraSensor::setControls(), it is necessary for a
> > pipeline handler to know the v4l2 index associated with a specific
> > test pattern mode.
> > How can we do that? Is it okay for a pipeline handler to read test
> > pattern mode in camera properties?
>
> I'd prefer going the other way around and avoid exposing V4L2 controls
> from CameraSensor. I haven't really thought about how to do so yet
> though.
>

Hmm, so how shall I do in this patch series?

> > > > On Wed, Jun 23, 2021 at 10:07:04AM +0200, Jacopo Mondi wrote:
> > > > > On Wed, Jun 23, 2021 at 04:49:46PM +0900, Hirokazu Honda wrote:
> > > > > > On Tue, Jun 22, 2021 at 7:30 PM Jacopo Mondi wrote:
> > > > > > > On Tue, Jun 22, 2021 at 11:36:51AM +0900, Hirokazu Honda wrote:
> > > > > > > > Provides a function to set the camera sensor a test pattern mode.
> > > > > > > >
> > > > > > > > Signed-off-by: Hirokazu Honda <hiroh@chromium.org>
> > > > > > > > ---
> > > > > > > >  include/libcamera/internal/camera_sensor.h |  1 +
> > > > > > > >  src/libcamera/camera_sensor.cpp            | 39 ++++++++++++++++++++++
> > > > > > > >  2 files changed, 40 insertions(+)
> > > > > > > >
> > > > > > > > diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
> > > > > > > > index e133ebf4..8b9f84c9 100644
> > > > > > > > --- a/include/libcamera/internal/camera_sensor.h
> > > > > > > > +++ b/include/libcamera/internal/camera_sensor.h
> > > > > > > > @@ -43,6 +43,7 @@ public:
> > > > > > > >       {
> > > > > > > >               return testPatternModes_;
> > > > > > > >       }
> > > > > > > > +     int setTestPatternMode(uint8_t testPatternMode);
> > > > > > > >
> > > > > > > >       V4L2SubdeviceFormat getFormat(const std::vector<unsigned int> &mbusCodes,
> > > > > > > >                                     const Size &size) const;
> > > > > > > > diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
> > > > > > > > index 70bbd97a..ce8ff274 100644
> > > > > > > > --- a/src/libcamera/camera_sensor.cpp
> > > > > > > > +++ b/src/libcamera/camera_sensor.cpp
> > > > > > > > @@ -507,6 +507,45 @@ Size CameraSensor::resolution() const
> > > > > > > >   * \return The list of test pattern modes
> > > > > > > >   */
> > > > > > > >
> > > > > > > > +/**
> > > > > > > > + * \brief Set the camera sensor a specified controls::TestPatternMode
> > > > > > >
> > > > > > > Doxygen is puzzling me recently... the testPatternMode paramter is not
> > > > > > > documented but I don't get a warning :/
> > > > > > >
> > > > > > > Also, I'm a bit debated about where to actually place this function
> > > > > > > (or better, it's initTestPatternModes which is misplaced)
> > > > > > > if we have to respect the declaration order or the way you sorted them
> > > > > > > here (which is more logical) is better.
> > > > > > >
> > > > > > > > + *
> > > > > > > > + * \return 0 on success or a negative error code otherwise
> > > > > > > > + */
> > > > > > > > +int CameraSensor::setTestPatternMode(uint8_t testPatternMode)
> > > > > > > > +{
> > > > > > > > +     if (std::find(testPatternModes_.begin(), testPatternModes_.end(),
> > > > > > > > +                   testPatternMode) == testPatternModes_.end()) {
> > > > > > > > +             LOG(CameraSensor, Error) << "Unsupported test pattern mode: "
> > > > > > > > +                                      << testPatternMode;
> > > > > > > > +             return -EINVAL;
> > > > > > > > +     }
> > > > > > >
> > > > > > > Do we need this ? The testPatternModes_ map is constructed using the
> > > > > > > camera sensor properties, the below find() on the props->testPatternModes
> > > > > > > map should gurantee that is supported. Also, if a test pattern mode is
> > > > > > > not reported as part of testPatternModes_ applications shouldn't set
> > > > > > > it...
> > > > > > >
> > > > > > > > +
> > > > > > > > +     const CameraSensorProperties *props = CameraSensorProperties::get(model_);
> > > > > > > > +     if (!props)
> > > > > > > > +             return -EINVAL;
> > > >
> > > > We already retrieve this in CameraSensor::initStaticProperties(), let's
> > > > cache the pointer in the CameraSensor class.
> > > >
> > > > > > > > +
> > > > > > > > +     auto it = props->testPatternModes.find(testPatternMode);
> > > > > > > > +     ASSERT(it != props->testPatternModes.end());
> > > > > > >
> > > > > > > Yeah, I think the assertion here is more than enough..
> > > > > > >
> > > > > > > > +     const uint8_t index = it->second;
> > > > > > > > +
> > > > > > > > +     ControlList ctrls = getControls({ V4L2_CID_TEST_PATTERN });
> > > > > > > > +     if (ctrls.empty()) {
> > > > > > > > +             LOG(CameraSensor, Error)
> > > > > > > > +                     << "Failed to retrieve test pattern control";
> > > > > > > > +             return -EINVAL;
> > > > > > > > +     }
> > > > > > >
> > > > > > > We won't register the TestPatternMode control in first place the V4L2
> > > > > > > control is not supported..
> > > > > >
> > > > > > Replace this with ASSERT.
> > > > > >
> > > > > > > > +
> > > > > > > > +     ControlValue value = ctrls.get(V4L2_CID_TEST_PATTERN);
> > > > > > > > +     if (value.get<int32_t>() == index)
> > > > > > > > +             return 0;
> > > > > > >
> > > > > > > The V4L2 control framework should take care of this by itself, I think
> > > > > > > we can set the control regardless
> > > > > >
> > > > > > Yes, I put this in order to save a redundant Ioctl call.
> > > > > > Do you want to remove that?
> > > > >
> > > > > Well, the ctrls ControlList you create with getControls() goes through
> > > > > an IOCTL :) We're talking details, but if we want to retain the
> > > > > state of the testPatterMode we can make it a class member, so that the
> > > > > code can be reduced to (not tested pseudo-code)
> > > > >
> > > > > {
> > > > >      if (testPatternMode == testPatternMode_)
> > > > >            return 0;
> > > > >
> > > > >      const CameraSensorProperties *props = CameraSensorProperties::get(model_);
> > > > >      if (!props)
> > > > >              return -EINVAL;
> > > > >
> > > > >      auto it = props->testPatternModes.find(testPatternMode);
> > > > >      ASSERT(it != props->testPatternModes.end());
> > > > >
> > > > >      ControlList ctrls(controls());
> > > > >      ctrls.set(V4L2_CID_TEST_PATTERN, it->second);
> > > > >
> > > > >      int ret = setControls(&ctrls);
> > > > >      if (ret)
> > > > >             return ret;
> > > > >
> > > > >      testPatternMode_ = testPatternMode;
> > > > >
> > > > >      return 0;
> > > > > }
> > > > >
> > > > > I also wonder if the ASSERT() is not too harsh and we shouldn't just
> > > > > error out. If the application tries to set an unsupported test pattern,
> > > > > the whole library would crash, maybe we should be a little more
> > > > > indulgent.
> > > >
> > > > Yes, not crashing is a good idea :-)
> > > >
> > > > > > > > +
> > > > > > > > +     value.set<int32_t>(index);
> > > > > > > > +     ctrls.set(V4L2_CID_TEST_PATTERN, value);
> > > > > > > > +
> > > > > > > > +     return setControls(&ctrls);
> > > > > > > > +}
> > > > > > > > +
> > > > > > > >  /**
> > > > > > > >   * \brief Retrieve the best sensor format for a desired output
> > > > > > > >   * \param[in] mbusCodes The list of acceptable media bus codes
>
> --
> Regards,
>
> Laurent Pinchart
Laurent Pinchart June 28, 2021, 5:45 a.m. UTC | #10
Hi Hiro,

On Mon, Jun 28, 2021 at 02:33:56PM +0900, Hirokazu Honda wrote:
> On Mon, Jun 28, 2021 at 2:26 PM Laurent Pinchart wrote:
> > On Mon, Jun 28, 2021 at 02:16:00PM +0900, Hirokazu Honda wrote:
> > > On Mon, Jun 28, 2021 at 12:28 PM Laurent Pinchart wrote:
> > > > On Mon, Jun 28, 2021 at 06:12:32AM +0300, Laurent Pinchart wrote:
> > > > > Hi Jacopo,
> > > > >
> > > > > Thank you for the patch.
> > > >
> > > > The patch is from Hiro of course :-)
> > > >
> > > > Another comment, do we need such a ad-hoc function, or could we handle
> > > > the test pattern mode using a more generic interface, with a ControlList
> > > > ? The CameraSensor::setControls() takes V4L2 controls today, which makes
> > > > it unsuitable for this purpose. I would ideally like to see all this
> > > > fixed, but I suppose it's a too big task for this series. It adds up to
> > > > the technical debt though, so there's a high chance that I'll push back
> > > > more strongly on the next patch that adds a ad-hoc function to
> > > > CameraSensor, until we reach a point where the push back will be a
> > > > strong nack and all this will need to be refactored by an unlucky
> > > > person. All this means that nobody should think that delaying the
> > > > handling of technical debt is a smart move to move it to someone else's
> > > > plate, it may come back around :-)
> > >
> > > If we want to use CameraSensor::setControls(), it is necessary for a
> > > pipeline handler to know the v4l2 index associated with a specific
> > > test pattern mode.
> > > How can we do that? Is it okay for a pipeline handler to read test
> > > pattern mode in camera properties?
> >
> > I'd prefer going the other way around and avoid exposing V4L2 controls
> > from CameraSensor. I haven't really thought about how to do so yet
> > though.
> 
> Hmm, so how shall I do in this patch series?

I think it may be too big for this series, so I'm ok adding the
setTestPatternMode() for now. We'll have to address this issue though,
so if you think of a way this could be done, we can start brainstorming
it.

> > > > > On Wed, Jun 23, 2021 at 10:07:04AM +0200, Jacopo Mondi wrote:
> > > > > > On Wed, Jun 23, 2021 at 04:49:46PM +0900, Hirokazu Honda wrote:
> > > > > > > On Tue, Jun 22, 2021 at 7:30 PM Jacopo Mondi wrote:
> > > > > > > > On Tue, Jun 22, 2021 at 11:36:51AM +0900, Hirokazu Honda wrote:
> > > > > > > > > Provides a function to set the camera sensor a test pattern mode.
> > > > > > > > >
> > > > > > > > > Signed-off-by: Hirokazu Honda <hiroh@chromium.org>
> > > > > > > > > ---
> > > > > > > > >  include/libcamera/internal/camera_sensor.h |  1 +
> > > > > > > > >  src/libcamera/camera_sensor.cpp            | 39 ++++++++++++++++++++++
> > > > > > > > >  2 files changed, 40 insertions(+)
> > > > > > > > >
> > > > > > > > > diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
> > > > > > > > > index e133ebf4..8b9f84c9 100644
> > > > > > > > > --- a/include/libcamera/internal/camera_sensor.h
> > > > > > > > > +++ b/include/libcamera/internal/camera_sensor.h
> > > > > > > > > @@ -43,6 +43,7 @@ public:
> > > > > > > > >       {
> > > > > > > > >               return testPatternModes_;
> > > > > > > > >       }
> > > > > > > > > +     int setTestPatternMode(uint8_t testPatternMode);
> > > > > > > > >
> > > > > > > > >       V4L2SubdeviceFormat getFormat(const std::vector<unsigned int> &mbusCodes,
> > > > > > > > >                                     const Size &size) const;
> > > > > > > > > diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
> > > > > > > > > index 70bbd97a..ce8ff274 100644
> > > > > > > > > --- a/src/libcamera/camera_sensor.cpp
> > > > > > > > > +++ b/src/libcamera/camera_sensor.cpp
> > > > > > > > > @@ -507,6 +507,45 @@ Size CameraSensor::resolution() const
> > > > > > > > >   * \return The list of test pattern modes
> > > > > > > > >   */
> > > > > > > > >
> > > > > > > > > +/**
> > > > > > > > > + * \brief Set the camera sensor a specified controls::TestPatternMode
> > > > > > > >
> > > > > > > > Doxygen is puzzling me recently... the testPatternMode paramter is not
> > > > > > > > documented but I don't get a warning :/
> > > > > > > >
> > > > > > > > Also, I'm a bit debated about where to actually place this function
> > > > > > > > (or better, it's initTestPatternModes which is misplaced)
> > > > > > > > if we have to respect the declaration order or the way you sorted them
> > > > > > > > here (which is more logical) is better.
> > > > > > > >
> > > > > > > > > + *
> > > > > > > > > + * \return 0 on success or a negative error code otherwise
> > > > > > > > > + */
> > > > > > > > > +int CameraSensor::setTestPatternMode(uint8_t testPatternMode)
> > > > > > > > > +{
> > > > > > > > > +     if (std::find(testPatternModes_.begin(), testPatternModes_.end(),
> > > > > > > > > +                   testPatternMode) == testPatternModes_.end()) {
> > > > > > > > > +             LOG(CameraSensor, Error) << "Unsupported test pattern mode: "
> > > > > > > > > +                                      << testPatternMode;
> > > > > > > > > +             return -EINVAL;
> > > > > > > > > +     }
> > > > > > > >
> > > > > > > > Do we need this ? The testPatternModes_ map is constructed using the
> > > > > > > > camera sensor properties, the below find() on the props->testPatternModes
> > > > > > > > map should gurantee that is supported. Also, if a test pattern mode is
> > > > > > > > not reported as part of testPatternModes_ applications shouldn't set
> > > > > > > > it...
> > > > > > > >
> > > > > > > > > +
> > > > > > > > > +     const CameraSensorProperties *props = CameraSensorProperties::get(model_);
> > > > > > > > > +     if (!props)
> > > > > > > > > +             return -EINVAL;
> > > > >
> > > > > We already retrieve this in CameraSensor::initStaticProperties(), let's
> > > > > cache the pointer in the CameraSensor class.
> > > > >
> > > > > > > > > +
> > > > > > > > > +     auto it = props->testPatternModes.find(testPatternMode);
> > > > > > > > > +     ASSERT(it != props->testPatternModes.end());
> > > > > > > >
> > > > > > > > Yeah, I think the assertion here is more than enough..
> > > > > > > >
> > > > > > > > > +     const uint8_t index = it->second;
> > > > > > > > > +
> > > > > > > > > +     ControlList ctrls = getControls({ V4L2_CID_TEST_PATTERN });
> > > > > > > > > +     if (ctrls.empty()) {
> > > > > > > > > +             LOG(CameraSensor, Error)
> > > > > > > > > +                     << "Failed to retrieve test pattern control";
> > > > > > > > > +             return -EINVAL;
> > > > > > > > > +     }
> > > > > > > >
> > > > > > > > We won't register the TestPatternMode control in first place the V4L2
> > > > > > > > control is not supported..
> > > > > > >
> > > > > > > Replace this with ASSERT.
> > > > > > >
> > > > > > > > > +
> > > > > > > > > +     ControlValue value = ctrls.get(V4L2_CID_TEST_PATTERN);
> > > > > > > > > +     if (value.get<int32_t>() == index)
> > > > > > > > > +             return 0;
> > > > > > > >
> > > > > > > > The V4L2 control framework should take care of this by itself, I think
> > > > > > > > we can set the control regardless
> > > > > > >
> > > > > > > Yes, I put this in order to save a redundant Ioctl call.
> > > > > > > Do you want to remove that?
> > > > > >
> > > > > > Well, the ctrls ControlList you create with getControls() goes through
> > > > > > an IOCTL :) We're talking details, but if we want to retain the
> > > > > > state of the testPatterMode we can make it a class member, so that the
> > > > > > code can be reduced to (not tested pseudo-code)
> > > > > >
> > > > > > {
> > > > > >      if (testPatternMode == testPatternMode_)
> > > > > >            return 0;
> > > > > >
> > > > > >      const CameraSensorProperties *props = CameraSensorProperties::get(model_);
> > > > > >      if (!props)
> > > > > >              return -EINVAL;
> > > > > >
> > > > > >      auto it = props->testPatternModes.find(testPatternMode);
> > > > > >      ASSERT(it != props->testPatternModes.end());
> > > > > >
> > > > > >      ControlList ctrls(controls());
> > > > > >      ctrls.set(V4L2_CID_TEST_PATTERN, it->second);
> > > > > >
> > > > > >      int ret = setControls(&ctrls);
> > > > > >      if (ret)
> > > > > >             return ret;
> > > > > >
> > > > > >      testPatternMode_ = testPatternMode;
> > > > > >
> > > > > >      return 0;
> > > > > > }
> > > > > >
> > > > > > I also wonder if the ASSERT() is not too harsh and we shouldn't just
> > > > > > error out. If the application tries to set an unsupported test pattern,
> > > > > > the whole library would crash, maybe we should be a little more
> > > > > > indulgent.
> > > > >
> > > > > Yes, not crashing is a good idea :-)
> > > > >
> > > > > > > > > +
> > > > > > > > > +     value.set<int32_t>(index);
> > > > > > > > > +     ctrls.set(V4L2_CID_TEST_PATTERN, value);
> > > > > > > > > +
> > > > > > > > > +     return setControls(&ctrls);
> > > > > > > > > +}
> > > > > > > > > +
> > > > > > > > >  /**
> > > > > > > > >   * \brief Retrieve the best sensor format for a desired output
> > > > > > > > >   * \param[in] mbusCodes The list of acceptable media bus codes

Patch
diff mbox series

diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
index e133ebf4..8b9f84c9 100644
--- a/include/libcamera/internal/camera_sensor.h
+++ b/include/libcamera/internal/camera_sensor.h
@@ -43,6 +43,7 @@  public:
 	{
 		return testPatternModes_;
 	}
+	int setTestPatternMode(uint8_t testPatternMode);
 
 	V4L2SubdeviceFormat getFormat(const std::vector<unsigned int> &mbusCodes,
 				      const Size &size) const;
diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
index 70bbd97a..ce8ff274 100644
--- a/src/libcamera/camera_sensor.cpp
+++ b/src/libcamera/camera_sensor.cpp
@@ -507,6 +507,45 @@  Size CameraSensor::resolution() const
  * \return The list of test pattern modes
  */
 
+/**
+ * \brief Set the camera sensor a specified controls::TestPatternMode
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int CameraSensor::setTestPatternMode(uint8_t testPatternMode)
+{
+	if (std::find(testPatternModes_.begin(), testPatternModes_.end(),
+		      testPatternMode) == testPatternModes_.end()) {
+		LOG(CameraSensor, Error) << "Unsupported test pattern mode: "
+					 << testPatternMode;
+		return -EINVAL;
+	}
+
+	const CameraSensorProperties *props = CameraSensorProperties::get(model_);
+	if (!props)
+		return -EINVAL;
+
+	auto it = props->testPatternModes.find(testPatternMode);
+	ASSERT(it != props->testPatternModes.end());
+	const uint8_t index = it->second;
+
+	ControlList ctrls = getControls({ V4L2_CID_TEST_PATTERN });
+	if (ctrls.empty()) {
+		LOG(CameraSensor, Error)
+			<< "Failed to retrieve test pattern control";
+		return -EINVAL;
+	}
+
+	ControlValue value = ctrls.get(V4L2_CID_TEST_PATTERN);
+	if (value.get<int32_t>() == index)
+		return 0;
+
+	value.set<int32_t>(index);
+	ctrls.set(V4L2_CID_TEST_PATTERN, value);
+
+	return setControls(&ctrls);
+}
+
 /**
  * \brief Retrieve the best sensor format for a desired output
  * \param[in] mbusCodes The list of acceptable media bus codes