[2/2] pipeline: rkisp1: Filter out sensor sizes not supported by the pipeline
diff mbox series

Message ID 20240909163719.267211-3-umang.jain@ideasonboard.com
State Superseded
Headers show
Series
  • pipeline: rkisp1: Filter out sensor sizes not supported by the pipeline
Related show

Commit Message

Umang Jain Sept. 9, 2024, 4:37 p.m. UTC
It is possible that the maximum sensor size (returned by
CameraSensor::resolution()) is not supported by the pipeline. In such
cases, a filter function is required to filter out resolutions of the
camera sensor, which cannot be supported by the pipeline.

Introduce the filter function filterSensorResolution() in RkISP1Path
class and use it for validate() and generateConfiguration(). The
maximum sensor resolution is picked from that filtered set of
resolutions instead of CameraSensor::resolution().

Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
---
 src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 48 ++++++++++++++++++-
 src/libcamera/pipeline/rkisp1/rkisp1_path.h   |  3 ++
 2 files changed, 49 insertions(+), 2 deletions(-)

Comments

Kieran Bingham Sept. 11, 2024, 10:52 a.m. UTC | #1
Quoting Umang Jain (2024-09-09 17:37:19)
> It is possible that the maximum sensor size (returned by
> CameraSensor::resolution()) is not supported by the pipeline. In such
> cases, a filter function is required to filter out resolutions of the
> camera sensor, which cannot be supported by the pipeline.
> 
> Introduce the filter function filterSensorResolution() in RkISP1Path
> class and use it for validate() and generateConfiguration(). The
> maximum sensor resolution is picked from that filtered set of
> resolutions instead of CameraSensor::resolution().
> 
> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
> ---
>  src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 48 ++++++++++++++++++-
>  src/libcamera/pipeline/rkisp1/rkisp1_path.h   |  3 ++
>  2 files changed, 49 insertions(+), 2 deletions(-)
> 
> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> index 9053af18..b3b27aa5 100644
> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> @@ -128,12 +128,56 @@ void RkISP1Path::populateFormats()
>         }
>  }
>  
> +/**
> + * \brief Filter the sensor resolutions that can be supported
> + * \param[in] sensor The camera sensor
> + *
> + * This function retrieves all the sizes supported by the sensor and
> + * filters all the resolutions that can be supported on the pipeline.
> + * It is possible that the sensor's maximum output resolution is higher
> + * than the ISP maximum input. In that case, this function filters out all
> + * the resolution incapable of being supported and returns the maximum
> + * sensor resolution that can be supported by the pipeline.
> + *
> + * \return Maximum sensor size supported on the pipeline
> + */
> +Size RkISP1Path::filterSensorResolution(const CameraSensor *sensor)
> +{
> +       if (!sensorSizes_.empty())
> +               return sensorSizes_.back();

I like that we keep the full list of supported sensorSizes_. My first
thought was that this list should be generated when the path is created,
but this also seems fine to me.

I think there's no need to complicate / split this until there's
actually a user of the full sensorSizes list ?

I'm a little surprised that's not not used actually. Do we report the
raw modes we support somewhere? Should that iterate the 'sensorSizes_'
as the supported sizes ?

Perhaps that's an improvement/fix on top though.

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

> +
> +       std::vector<Size> sensorSizes;
> +       const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
> +       for (const auto iter : mbusCodes) {
> +               std::vector<Size> sizes = sensor->sizes(iter);
> +               for (Size sz : sizes)
> +                       sensorSizes.push_back(sz);
> +       }
> +
> +       std::sort(sensorSizes.begin(), sensorSizes.end());
> +
> +       /* Remove duplicates. */
> +       auto last = std::unique(sensorSizes.begin(), sensorSizes.end());
> +       sensorSizes.erase(last, sensorSizes.end());
> +
> +       /* Discard any sizes that the pipeline is unable to support. */
> +       for (auto sz : sensorSizes) {
> +               if (sz.width > maxResolution_.width ||
> +                   sz.height > maxResolution_.height)
> +                       continue;
> +
> +               sensorSizes_.push_back(sz);
> +       }
> +
> +       return sensorSizes_.back();
> +}
> +
>  StreamConfiguration
>  RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size,
>                                   StreamRole role)
>  {
>         const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
> -       const Size &resolution = sensor->resolution();
> +       Size resolution = filterSensorResolution(sensor);
>  
>         /* Min and max resolutions to populate the available stream formats. */
>         Size maxResolution = maxResolution_.boundedToAspectRatio(resolution)
> @@ -222,7 +266,7 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
>                                                  StreamConfiguration *cfg)
>  {
>         const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
> -       const Size &resolution = sensor->resolution();
> +       Size resolution = filterSensorResolution(sensor);
>  
>         const StreamConfiguration reqCfg = *cfg;
>         CameraConfiguration::Status status = CameraConfiguration::Valid;
> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> index 13ba4b62..03ff9543 100644
> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> @@ -63,6 +63,7 @@ public:
>  
>  private:
>         void populateFormats();
> +       Size filterSensorResolution(const CameraSensor *sensor);
>  
>         static constexpr unsigned int RKISP1_BUFFER_COUNT = 4;
>  
> @@ -77,6 +78,8 @@ private:
>         std::unique_ptr<V4L2Subdevice> resizer_;
>         std::unique_ptr<V4L2VideoDevice> video_;
>         MediaLink *link_;
> +
> +       std::vector<Size> sensorSizes_;
>  };
>  
>  class RkISP1MainPath : public RkISP1Path
> -- 
> 2.45.0
>
Laurent Pinchart Sept. 11, 2024, 10:29 p.m. UTC | #2
On Wed, Sep 11, 2024 at 11:52:36AM +0100, Kieran Bingham wrote:
> Quoting Umang Jain (2024-09-09 17:37:19)
> > It is possible that the maximum sensor size (returned by
> > CameraSensor::resolution()) is not supported by the pipeline. In such
> > cases, a filter function is required to filter out resolutions of the
> > camera sensor, which cannot be supported by the pipeline.
> > 
> > Introduce the filter function filterSensorResolution() in RkISP1Path
> > class and use it for validate() and generateConfiguration(). The
> > maximum sensor resolution is picked from that filtered set of
> > resolutions instead of CameraSensor::resolution().
> > 
> > Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
> > ---
> >  src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 48 ++++++++++++++++++-
> >  src/libcamera/pipeline/rkisp1/rkisp1_path.h   |  3 ++
> >  2 files changed, 49 insertions(+), 2 deletions(-)
> > 
> > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> > index 9053af18..b3b27aa5 100644
> > --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> > +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> > @@ -128,12 +128,56 @@ void RkISP1Path::populateFormats()
> >         }
> >  }
> >  
> > +/**
> > + * \brief Filter the sensor resolutions that can be supported
> > + * \param[in] sensor The camera sensor
> > + *
> > + * This function retrieves all the sizes supported by the sensor and
> > + * filters all the resolutions that can be supported on the pipeline.
> > + * It is possible that the sensor's maximum output resolution is higher
> > + * than the ISP maximum input. In that case, this function filters out all
> > + * the resolution incapable of being supported and returns the maximum
> > + * sensor resolution that can be supported by the pipeline.
> > + *
> > + * \return Maximum sensor size supported on the pipeline
> > + */
> > +Size RkISP1Path::filterSensorResolution(const CameraSensor *sensor)
> > +{
> > +       if (!sensorSizes_.empty())
> > +               return sensorSizes_.back();

There are systems based on rkisp1 where multiple sensors are connected
to the same ISP. Obviously only one of them can be used at a time, but
applications can switch between them. This will be broken by caching
sensorSizes_.

> I like that we keep the full list of supported sensorSizes_. My first
> thought was that this list should be generated when the path is created,
> but this also seems fine to me.
> 
> I think there's no need to complicate / split this until there's
> actually a user of the full sensorSizes list ?
> 
> I'm a little surprised that's not not used actually. Do we report the
> raw modes we support somewhere? Should that iterate the 'sensorSizes_'
> as the supported sizes ?
> 
> Perhaps that's an improvement/fix on top though.
> 
> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> 
> > +
> > +       std::vector<Size> sensorSizes;
> > +       const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
> > +       for (const auto iter : mbusCodes) {
> > +               std::vector<Size> sizes = sensor->sizes(iter);
> > +               for (Size sz : sizes)
> > +                       sensorSizes.push_back(sz);
> > +       }
> > +
> > +       std::sort(sensorSizes.begin(), sensorSizes.end());
> > +
> > +       /* Remove duplicates. */
> > +       auto last = std::unique(sensorSizes.begin(), sensorSizes.end());
> > +       sensorSizes.erase(last, sensorSizes.end());
> > +
> > +       /* Discard any sizes that the pipeline is unable to support. */
> > +       for (auto sz : sensorSizes) {
> > +               if (sz.width > maxResolution_.width ||
> > +                   sz.height > maxResolution_.height)
> > +                       continue;
> > +
> > +               sensorSizes_.push_back(sz);
> > +       }
> > +
> > +       return sensorSizes_.back();
> > +}
> > +
> >  StreamConfiguration
> >  RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size,
> >                                   StreamRole role)
> >  {
> >         const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
> > -       const Size &resolution = sensor->resolution();
> > +       Size resolution = filterSensorResolution(sensor);
> >  
> >         /* Min and max resolutions to populate the available stream formats. */
> >         Size maxResolution = maxResolution_.boundedToAspectRatio(resolution)
> > @@ -222,7 +266,7 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
> >                                                  StreamConfiguration *cfg)
> >  {
> >         const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
> > -       const Size &resolution = sensor->resolution();
> > +       Size resolution = filterSensorResolution(sensor);
> >  
> >         const StreamConfiguration reqCfg = *cfg;
> >         CameraConfiguration::Status status = CameraConfiguration::Valid;
> > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> > index 13ba4b62..03ff9543 100644
> > --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> > +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> > @@ -63,6 +63,7 @@ public:
> >  
> >  private:
> >         void populateFormats();
> > +       Size filterSensorResolution(const CameraSensor *sensor);
> >  
> >         static constexpr unsigned int RKISP1_BUFFER_COUNT = 4;
> >  
> > @@ -77,6 +78,8 @@ private:
> >         std::unique_ptr<V4L2Subdevice> resizer_;
> >         std::unique_ptr<V4L2VideoDevice> video_;
> >         MediaLink *link_;
> > +
> > +       std::vector<Size> sensorSizes_;
> >  };
> >  
> >  class RkISP1MainPath : public RkISP1Path
Umang Jain Sept. 12, 2024, 10:29 a.m. UTC | #3
Hi Laurent

On 12/09/24 3:59 am, Laurent Pinchart wrote:
> On Wed, Sep 11, 2024 at 11:52:36AM +0100, Kieran Bingham wrote:
>> Quoting Umang Jain (2024-09-09 17:37:19)
>>> It is possible that the maximum sensor size (returned by
>>> CameraSensor::resolution()) is not supported by the pipeline. In such
>>> cases, a filter function is required to filter out resolutions of the
>>> camera sensor, which cannot be supported by the pipeline.
>>>
>>> Introduce the filter function filterSensorResolution() in RkISP1Path
>>> class and use it for validate() and generateConfiguration(). The
>>> maximum sensor resolution is picked from that filtered set of
>>> resolutions instead of CameraSensor::resolution().
>>>
>>> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
>>> ---
>>>   src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 48 ++++++++++++++++++-
>>>   src/libcamera/pipeline/rkisp1/rkisp1_path.h   |  3 ++
>>>   2 files changed, 49 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
>>> index 9053af18..b3b27aa5 100644
>>> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
>>> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
>>> @@ -128,12 +128,56 @@ void RkISP1Path::populateFormats()
>>>          }
>>>   }
>>>   
>>> +/**
>>> + * \brief Filter the sensor resolutions that can be supported
>>> + * \param[in] sensor The camera sensor
>>> + *
>>> + * This function retrieves all the sizes supported by the sensor and
>>> + * filters all the resolutions that can be supported on the pipeline.
>>> + * It is possible that the sensor's maximum output resolution is higher
>>> + * than the ISP maximum input. In that case, this function filters out all
>>> + * the resolution incapable of being supported and returns the maximum
>>> + * sensor resolution that can be supported by the pipeline.
>>> + *
>>> + * \return Maximum sensor size supported on the pipeline
>>> + */
>>> +Size RkISP1Path::filterSensorResolution(const CameraSensor *sensor)
>>> +{
>>> +       if (!sensorSizes_.empty())
>>> +               return sensorSizes_.back();
> There are systems based on rkisp1 where multiple sensors are connected
> to the same ISP. Obviously only one of them can be used at a time, but
> applications can switch between them. This will be broken by caching
> sensorSizes_.

Indeed, something that I missed while developing on i.MX8MP (two cameras 
but dual ISP as well)

I'll convert it to a std::map in next revision.

>> I like that we keep the full list of supported sensorSizes_. My first
>> thought was that this list should be generated when the path is created,
>> but this also seems fine to me.
>>
>> I think there's no need to complicate / split this until there's
>> actually a user of the full sensorSizes list ?
>>
>> I'm a little surprised that's not not used actually. Do we report the
>> raw modes we support somewhere? Should that iterate the 'sensorSizes_'
>> as the supported sizes ?

I will test how raw sizes are reported ? sensorSizes_ is a good 
candidate to update the raw size list as well.
>>
>> Perhaps that's an improvement/fix on top though.
>>
>> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
>>
>>> +
>>> +       std::vector<Size> sensorSizes;
>>> +       const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
>>> +       for (const auto iter : mbusCodes) {
>>> +               std::vector<Size> sizes = sensor->sizes(iter);
>>> +               for (Size sz : sizes)
>>> +                       sensorSizes.push_back(sz);
>>> +       }
>>> +
>>> +       std::sort(sensorSizes.begin(), sensorSizes.end());
>>> +
>>> +       /* Remove duplicates. */
>>> +       auto last = std::unique(sensorSizes.begin(), sensorSizes.end());
>>> +       sensorSizes.erase(last, sensorSizes.end());
>>> +
>>> +       /* Discard any sizes that the pipeline is unable to support. */
>>> +       for (auto sz : sensorSizes) {
>>> +               if (sz.width > maxResolution_.width ||
>>> +                   sz.height > maxResolution_.height)
>>> +                       continue;
>>> +
>>> +               sensorSizes_.push_back(sz);
>>> +       }
>>> +
>>> +       return sensorSizes_.back();
>>> +}
>>> +
>>>   StreamConfiguration
>>>   RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size,
>>>                                    StreamRole role)
>>>   {
>>>          const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
>>> -       const Size &resolution = sensor->resolution();
>>> +       Size resolution = filterSensorResolution(sensor);
>>>   
>>>          /* Min and max resolutions to populate the available stream formats. */
>>>          Size maxResolution = maxResolution_.boundedToAspectRatio(resolution)
>>> @@ -222,7 +266,7 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
>>>                                                   StreamConfiguration *cfg)
>>>   {
>>>          const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
>>> -       const Size &resolution = sensor->resolution();
>>> +       Size resolution = filterSensorResolution(sensor);
>>>   
>>>          const StreamConfiguration reqCfg = *cfg;
>>>          CameraConfiguration::Status status = CameraConfiguration::Valid;
>>> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
>>> index 13ba4b62..03ff9543 100644
>>> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h
>>> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
>>> @@ -63,6 +63,7 @@ public:
>>>   
>>>   private:
>>>          void populateFormats();
>>> +       Size filterSensorResolution(const CameraSensor *sensor);
>>>   
>>>          static constexpr unsigned int RKISP1_BUFFER_COUNT = 4;
>>>   
>>> @@ -77,6 +78,8 @@ private:
>>>          std::unique_ptr<V4L2Subdevice> resizer_;
>>>          std::unique_ptr<V4L2VideoDevice> video_;
>>>          MediaLink *link_;
>>> +
>>> +       std::vector<Size> sensorSizes_;
>>>   };
>>>   
>>>   class RkISP1MainPath : public RkISP1Path
Kieran Bingham Sept. 12, 2024, 10:48 a.m. UTC | #4
Quoting Umang Jain (2024-09-12 11:29:40)
> Hi Laurent
> 
> On 12/09/24 3:59 am, Laurent Pinchart wrote:
> > On Wed, Sep 11, 2024 at 11:52:36AM +0100, Kieran Bingham wrote:
> >> Quoting Umang Jain (2024-09-09 17:37:19)
> >>> It is possible that the maximum sensor size (returned by
> >>> CameraSensor::resolution()) is not supported by the pipeline. In such
> >>> cases, a filter function is required to filter out resolutions of the
> >>> camera sensor, which cannot be supported by the pipeline.
> >>>
> >>> Introduce the filter function filterSensorResolution() in RkISP1Path
> >>> class and use it for validate() and generateConfiguration(). The
> >>> maximum sensor resolution is picked from that filtered set of
> >>> resolutions instead of CameraSensor::resolution().
> >>>
> >>> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
> >>> ---
> >>>   src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 48 ++++++++++++++++++-
> >>>   src/libcamera/pipeline/rkisp1/rkisp1_path.h   |  3 ++
> >>>   2 files changed, 49 insertions(+), 2 deletions(-)
> >>>
> >>> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> >>> index 9053af18..b3b27aa5 100644
> >>> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> >>> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> >>> @@ -128,12 +128,56 @@ void RkISP1Path::populateFormats()
> >>>          }
> >>>   }
> >>>   
> >>> +/**
> >>> + * \brief Filter the sensor resolutions that can be supported
> >>> + * \param[in] sensor The camera sensor
> >>> + *
> >>> + * This function retrieves all the sizes supported by the sensor and
> >>> + * filters all the resolutions that can be supported on the pipeline.
> >>> + * It is possible that the sensor's maximum output resolution is higher
> >>> + * than the ISP maximum input. In that case, this function filters out all
> >>> + * the resolution incapable of being supported and returns the maximum
> >>> + * sensor resolution that can be supported by the pipeline.
> >>> + *
> >>> + * \return Maximum sensor size supported on the pipeline
> >>> + */
> >>> +Size RkISP1Path::filterSensorResolution(const CameraSensor *sensor)
> >>> +{
> >>> +       if (!sensorSizes_.empty())
> >>> +               return sensorSizes_.back();
> > There are systems based on rkisp1 where multiple sensors are connected
> > to the same ISP. Obviously only one of them can be used at a time, but
> > applications can switch between them. This will be broken by caching
> > sensorSizes_.
> 
> Indeed, something that I missed while developing on i.MX8MP (two cameras 
> but dual ISP as well)
> 
> I'll convert it to a std::map in next revision.

Rather than a map - can we just put this filter/or the sensorSizes_ into
the camera data?



> 
> >> I like that we keep the full list of supported sensorSizes_. My first
> >> thought was that this list should be generated when the path is created,
> >> but this also seems fine to me.
> >>
> >> I think there's no need to complicate / split this until there's
> >> actually a user of the full sensorSizes list ?
> >>
> >> I'm a little surprised that's not not used actually. Do we report the
> >> raw modes we support somewhere? Should that iterate the 'sensorSizes_'
> >> as the supported sizes ?
> 
> I will test how raw sizes are reported ? sensorSizes_ is a good 
> candidate to update the raw size list as well.

I'm intrigued on what it's currently reporting...

--
Kieran


> >>
> >> Perhaps that's an improvement/fix on top though.
> >>
> >> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> >>
> >>> +
> >>> +       std::vector<Size> sensorSizes;
> >>> +       const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
> >>> +       for (const auto iter : mbusCodes) {
> >>> +               std::vector<Size> sizes = sensor->sizes(iter);
> >>> +               for (Size sz : sizes)
> >>> +                       sensorSizes.push_back(sz);
> >>> +       }
> >>> +
> >>> +       std::sort(sensorSizes.begin(), sensorSizes.end());
> >>> +
> >>> +       /* Remove duplicates. */
> >>> +       auto last = std::unique(sensorSizes.begin(), sensorSizes.end());
> >>> +       sensorSizes.erase(last, sensorSizes.end());
> >>> +
> >>> +       /* Discard any sizes that the pipeline is unable to support. */
> >>> +       for (auto sz : sensorSizes) {
> >>> +               if (sz.width > maxResolution_.width ||
> >>> +                   sz.height > maxResolution_.height)
> >>> +                       continue;
> >>> +
> >>> +               sensorSizes_.push_back(sz);
> >>> +       }
> >>> +
> >>> +       return sensorSizes_.back();
> >>> +}
> >>> +
> >>>   StreamConfiguration
> >>>   RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size,
> >>>                                    StreamRole role)
> >>>   {
> >>>          const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
> >>> -       const Size &resolution = sensor->resolution();
> >>> +       Size resolution = filterSensorResolution(sensor);
> >>>   
> >>>          /* Min and max resolutions to populate the available stream formats. */
> >>>          Size maxResolution = maxResolution_.boundedToAspectRatio(resolution)
> >>> @@ -222,7 +266,7 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
> >>>                                                   StreamConfiguration *cfg)
> >>>   {
> >>>          const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
> >>> -       const Size &resolution = sensor->resolution();
> >>> +       Size resolution = filterSensorResolution(sensor);
> >>>   
> >>>          const StreamConfiguration reqCfg = *cfg;
> >>>          CameraConfiguration::Status status = CameraConfiguration::Valid;
> >>> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> >>> index 13ba4b62..03ff9543 100644
> >>> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> >>> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> >>> @@ -63,6 +63,7 @@ public:
> >>>   
> >>>   private:
> >>>          void populateFormats();
> >>> +       Size filterSensorResolution(const CameraSensor *sensor);
> >>>   
> >>>          static constexpr unsigned int RKISP1_BUFFER_COUNT = 4;
> >>>   
> >>> @@ -77,6 +78,8 @@ private:
> >>>          std::unique_ptr<V4L2Subdevice> resizer_;
> >>>          std::unique_ptr<V4L2VideoDevice> video_;
> >>>          MediaLink *link_;
> >>> +
> >>> +       std::vector<Size> sensorSizes_;
> >>>   };
> >>>   
> >>>   class RkISP1MainPath : public RkISP1Path
>
Umang Jain Sept. 12, 2024, 10:57 a.m. UTC | #5
On 12/09/24 4:18 pm, Kieran Bingham wrote:
> Quoting Umang Jain (2024-09-12 11:29:40)
>> Hi Laurent
>>
>> On 12/09/24 3:59 am, Laurent Pinchart wrote:
>>> On Wed, Sep 11, 2024 at 11:52:36AM +0100, Kieran Bingham wrote:
>>>> Quoting Umang Jain (2024-09-09 17:37:19)
>>>>> It is possible that the maximum sensor size (returned by
>>>>> CameraSensor::resolution()) is not supported by the pipeline. In such
>>>>> cases, a filter function is required to filter out resolutions of the
>>>>> camera sensor, which cannot be supported by the pipeline.
>>>>>
>>>>> Introduce the filter function filterSensorResolution() in RkISP1Path
>>>>> class and use it for validate() and generateConfiguration(). The
>>>>> maximum sensor resolution is picked from that filtered set of
>>>>> resolutions instead of CameraSensor::resolution().
>>>>>
>>>>> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
>>>>> ---
>>>>>    src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 48 ++++++++++++++++++-
>>>>>    src/libcamera/pipeline/rkisp1/rkisp1_path.h   |  3 ++
>>>>>    2 files changed, 49 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
>>>>> index 9053af18..b3b27aa5 100644
>>>>> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
>>>>> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
>>>>> @@ -128,12 +128,56 @@ void RkISP1Path::populateFormats()
>>>>>           }
>>>>>    }
>>>>>    
>>>>> +/**
>>>>> + * \brief Filter the sensor resolutions that can be supported
>>>>> + * \param[in] sensor The camera sensor
>>>>> + *
>>>>> + * This function retrieves all the sizes supported by the sensor and
>>>>> + * filters all the resolutions that can be supported on the pipeline.
>>>>> + * It is possible that the sensor's maximum output resolution is higher
>>>>> + * than the ISP maximum input. In that case, this function filters out all
>>>>> + * the resolution incapable of being supported and returns the maximum
>>>>> + * sensor resolution that can be supported by the pipeline.
>>>>> + *
>>>>> + * \return Maximum sensor size supported on the pipeline
>>>>> + */
>>>>> +Size RkISP1Path::filterSensorResolution(const CameraSensor *sensor)
>>>>> +{
>>>>> +       if (!sensorSizes_.empty())
>>>>> +               return sensorSizes_.back();
>>> There are systems based on rkisp1 where multiple sensors are connected
>>> to the same ISP. Obviously only one of them can be used at a time, but
>>> applications can switch between them. This will be broken by caching
>>> sensorSizes_.
>> Indeed, something that I missed while developing on i.MX8MP (two cameras
>> but dual ISP as well)
>>
>> I'll convert it to a std::map in next revision.
> Rather than a map - can we just put this filter/or the sensorSizes_ into
> the camera data?

hmm, might require passing CameraData into RkISP1Path::validate(...)

and

RkISP1Path:: generateConfiguration(const CameraSensor *sensor,....)

Possibly replacing the CameraSensor function argument in both.

>
>
>
>>>> I like that we keep the full list of supported sensorSizes_. My first
>>>> thought was that this list should be generated when the path is created,
>>>> but this also seems fine to me.
>>>>
>>>> I think there's no need to complicate / split this until there's
>>>> actually a user of the full sensorSizes list ?
>>>>
>>>> I'm a little surprised that's not not used actually. Do we report the
>>>> raw modes we support somewhere? Should that iterate the 'sensorSizes_'
>>>> as the supported sizes ?
>> I will test how raw sizes are reported ? sensorSizes_ is a good
>> candidate to update the raw size list as well.
> I'm intrigued on what it's currently reporting...
>
> --
> Kieran
>
>
>>>> Perhaps that's an improvement/fix on top though.
>>>>
>>>> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
>>>>
>>>>> +
>>>>> +       std::vector<Size> sensorSizes;
>>>>> +       const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
>>>>> +       for (const auto iter : mbusCodes) {
>>>>> +               std::vector<Size> sizes = sensor->sizes(iter);
>>>>> +               for (Size sz : sizes)
>>>>> +                       sensorSizes.push_back(sz);
>>>>> +       }
>>>>> +
>>>>> +       std::sort(sensorSizes.begin(), sensorSizes.end());
>>>>> +
>>>>> +       /* Remove duplicates. */
>>>>> +       auto last = std::unique(sensorSizes.begin(), sensorSizes.end());
>>>>> +       sensorSizes.erase(last, sensorSizes.end());
>>>>> +
>>>>> +       /* Discard any sizes that the pipeline is unable to support. */
>>>>> +       for (auto sz : sensorSizes) {
>>>>> +               if (sz.width > maxResolution_.width ||
>>>>> +                   sz.height > maxResolution_.height)
>>>>> +                       continue;
>>>>> +
>>>>> +               sensorSizes_.push_back(sz);
>>>>> +       }
>>>>> +
>>>>> +       return sensorSizes_.back();
>>>>> +}
>>>>> +
>>>>>    StreamConfiguration
>>>>>    RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size,
>>>>>                                     StreamRole role)
>>>>>    {
>>>>>           const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
>>>>> -       const Size &resolution = sensor->resolution();
>>>>> +       Size resolution = filterSensorResolution(sensor);
>>>>>    
>>>>>           /* Min and max resolutions to populate the available stream formats. */
>>>>>           Size maxResolution = maxResolution_.boundedToAspectRatio(resolution)
>>>>> @@ -222,7 +266,7 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
>>>>>                                                    StreamConfiguration *cfg)
>>>>>    {
>>>>>           const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
>>>>> -       const Size &resolution = sensor->resolution();
>>>>> +       Size resolution = filterSensorResolution(sensor);
>>>>>    
>>>>>           const StreamConfiguration reqCfg = *cfg;
>>>>>           CameraConfiguration::Status status = CameraConfiguration::Valid;
>>>>> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
>>>>> index 13ba4b62..03ff9543 100644
>>>>> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h
>>>>> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
>>>>> @@ -63,6 +63,7 @@ public:
>>>>>    
>>>>>    private:
>>>>>           void populateFormats();
>>>>> +       Size filterSensorResolution(const CameraSensor *sensor);
>>>>>    
>>>>>           static constexpr unsigned int RKISP1_BUFFER_COUNT = 4;
>>>>>    
>>>>> @@ -77,6 +78,8 @@ private:
>>>>>           std::unique_ptr<V4L2Subdevice> resizer_;
>>>>>           std::unique_ptr<V4L2VideoDevice> video_;
>>>>>           MediaLink *link_;
>>>>> +
>>>>> +       std::vector<Size> sensorSizes_;
>>>>>    };
>>>>>    
>>>>>    class RkISP1MainPath : public RkISP1Path
Umang Jain Sept. 13, 2024, 5:33 a.m. UTC | #6
Hello

On 12/09/24 4:27 pm, Umang Jain wrote:
>
>
> On 12/09/24 4:18 pm, Kieran Bingham wrote:
>> Quoting Umang Jain (2024-09-12 11:29:40)
>>> Hi Laurent
>>>
>>> On 12/09/24 3:59 am, Laurent Pinchart wrote:
>>>> On Wed, Sep 11, 2024 at 11:52:36AM +0100, Kieran Bingham wrote:
>>>>> Quoting Umang Jain (2024-09-09 17:37:19)
>>>>>> It is possible that the maximum sensor size (returned by
>>>>>> CameraSensor::resolution()) is not supported by the pipeline. In 
>>>>>> such
>>>>>> cases, a filter function is required to filter out resolutions of 
>>>>>> the
>>>>>> camera sensor, which cannot be supported by the pipeline.
>>>>>>
>>>>>> Introduce the filter function filterSensorResolution() in RkISP1Path
>>>>>> class and use it for validate() and generateConfiguration(). The
>>>>>> maximum sensor resolution is picked from that filtered set of
>>>>>> resolutions instead of CameraSensor::resolution().
>>>>>>
>>>>>> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
>>>>>> ---
>>>>>>    src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 48 
>>>>>> ++++++++++++++++++-
>>>>>>    src/libcamera/pipeline/rkisp1/rkisp1_path.h   |  3 ++
>>>>>>    2 files changed, 49 insertions(+), 2 deletions(-)
>>>>>>
>>>>>> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp 
>>>>>> b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
>>>>>> index 9053af18..b3b27aa5 100644
>>>>>> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
>>>>>> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
>>>>>> @@ -128,12 +128,56 @@ void RkISP1Path::populateFormats()
>>>>>>           }
>>>>>>    }
>>>>>>    +/**
>>>>>> + * \brief Filter the sensor resolutions that can be supported
>>>>>> + * \param[in] sensor The camera sensor
>>>>>> + *
>>>>>> + * This function retrieves all the sizes supported by the sensor 
>>>>>> and
>>>>>> + * filters all the resolutions that can be supported on the 
>>>>>> pipeline.
>>>>>> + * It is possible that the sensor's maximum output resolution is 
>>>>>> higher
>>>>>> + * than the ISP maximum input. In that case, this function 
>>>>>> filters out all
>>>>>> + * the resolution incapable of being supported and returns the 
>>>>>> maximum
>>>>>> + * sensor resolution that can be supported by the pipeline.
>>>>>> + *
>>>>>> + * \return Maximum sensor size supported on the pipeline
>>>>>> + */
>>>>>> +Size RkISP1Path::filterSensorResolution(const CameraSensor *sensor)
>>>>>> +{
>>>>>> +       if (!sensorSizes_.empty())
>>>>>> +               return sensorSizes_.back();
>>>> There are systems based on rkisp1 where multiple sensors are connected
>>>> to the same ISP. Obviously only one of them can be used at a time, but
>>>> applications can switch between them. This will be broken by caching
>>>> sensorSizes_.
>>> Indeed, something that I missed while developing on i.MX8MP (two 
>>> cameras
>>> but dual ISP as well)
>>>
>>> I'll convert it to a std::map in next revision.
>> Rather than a map - can we just put this filter/or the sensorSizes_ into
>> the camera data?
>
> hmm, might require passing CameraData into RkISP1Path::validate(...)
>
> and
>
> RkISP1Path:: generateConfiguration(const CameraSensor *sensor,....)
>
> Possibly replacing the CameraSensor function argument in both.

Doing this seems a bit awkward, given the RkISP1CameraData is defined in 
rkisp1.cpp
and it already has pointers to mainPath and selfPath RkISP1Path.

Should I try making RkISP1CameraData shared to path classes for solely 
this purpose?
>
>>
>>
>>
>>>>> I like that we keep the full list of supported sensorSizes_. My first
>>>>> thought was that this list should be generated when the path is 
>>>>> created,
>>>>> but this also seems fine to me.
>>>>>
>>>>> I think there's no need to complicate / split this until there's
>>>>> actually a user of the full sensorSizes list ?
>>>>>
>>>>> I'm a little surprised that's not not used actually. Do we report the
>>>>> raw modes we support somewhere? Should that iterate the 
>>>>> 'sensorSizes_'
>>>>> as the supported sizes ?
>>> I will test how raw sizes are reported ? sensorSizes_ is a good
>>> candidate to update the raw size list as well.
>> I'm intrigued on what it's currently reporting...

It's reporting the max sizes i.e. 5472x3648

After this series is applied, it's reports correct list with 5472x3648 
filtered out from the list.

Since the raw formats are reported with [format, Size], just iterating 
over the sensorSize_ is not enough. So probably, the usage of 
sensorSizes_ is limited for now.
>>
>> -- 
>> Kieran
>>
>>
>>>>> Perhaps that's an improvement/fix on top though.
>>>>>
>>>>> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
>>>>>
>>>>>> +
>>>>>> +       std::vector<Size> sensorSizes;
>>>>>> +       const std::vector<unsigned int> &mbusCodes = 
>>>>>> sensor->mbusCodes();
>>>>>> +       for (const auto iter : mbusCodes) {
>>>>>> +               std::vector<Size> sizes = sensor->sizes(iter);
>>>>>> +               for (Size sz : sizes)
>>>>>> +                       sensorSizes.push_back(sz);
>>>>>> +       }
>>>>>> +
>>>>>> +       std::sort(sensorSizes.begin(), sensorSizes.end());
>>>>>> +
>>>>>> +       /* Remove duplicates. */
>>>>>> +       auto last = std::unique(sensorSizes.begin(), 
>>>>>> sensorSizes.end());
>>>>>> +       sensorSizes.erase(last, sensorSizes.end());
>>>>>> +
>>>>>> +       /* Discard any sizes that the pipeline is unable to 
>>>>>> support. */
>>>>>> +       for (auto sz : sensorSizes) {
>>>>>> +               if (sz.width > maxResolution_.width ||
>>>>>> +                   sz.height > maxResolution_.height)
>>>>>> +                       continue;
>>>>>> +
>>>>>> +               sensorSizes_.push_back(sz);
>>>>>> +       }
>>>>>> +
>>>>>> +       return sensorSizes_.back();
>>>>>> +}
>>>>>> +
>>>>>>    StreamConfiguration
>>>>>>    RkISP1Path::generateConfiguration(const CameraSensor *sensor, 
>>>>>> const Size &size,
>>>>>>                                     StreamRole role)
>>>>>>    {
>>>>>>           const std::vector<unsigned int> &mbusCodes = 
>>>>>> sensor->mbusCodes();
>>>>>> -       const Size &resolution = sensor->resolution();
>>>>>> +       Size resolution = filterSensorResolution(sensor);
>>>>>>              /* Min and max resolutions to populate the available 
>>>>>> stream formats. */
>>>>>>           Size maxResolution = 
>>>>>> maxResolution_.boundedToAspectRatio(resolution)
>>>>>> @@ -222,7 +266,7 @@ CameraConfiguration::Status 
>>>>>> RkISP1Path::validate(const CameraSensor *sensor,
>>>>>> StreamConfiguration *cfg)
>>>>>>    {
>>>>>>           const std::vector<unsigned int> &mbusCodes = 
>>>>>> sensor->mbusCodes();
>>>>>> -       const Size &resolution = sensor->resolution();
>>>>>> +       Size resolution = filterSensorResolution(sensor);
>>>>>>              const StreamConfiguration reqCfg = *cfg;
>>>>>>           CameraConfiguration::Status status = 
>>>>>> CameraConfiguration::Valid;
>>>>>> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h 
>>>>>> b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
>>>>>> index 13ba4b62..03ff9543 100644
>>>>>> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h
>>>>>> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
>>>>>> @@ -63,6 +63,7 @@ public:
>>>>>>       private:
>>>>>>           void populateFormats();
>>>>>> +       Size filterSensorResolution(const CameraSensor *sensor);
>>>>>>              static constexpr unsigned int RKISP1_BUFFER_COUNT = 4;
>>>>>>    @@ -77,6 +78,8 @@ private:
>>>>>>           std::unique_ptr<V4L2Subdevice> resizer_;
>>>>>>           std::unique_ptr<V4L2VideoDevice> video_;
>>>>>>           MediaLink *link_;
>>>>>> +
>>>>>> +       std::vector<Size> sensorSizes_;
>>>>>>    };
>>>>>>       class RkISP1MainPath : public RkISP1Path
>

Patch
diff mbox series

diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
index 9053af18..b3b27aa5 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
@@ -128,12 +128,56 @@  void RkISP1Path::populateFormats()
 	}
 }
 
+/**
+ * \brief Filter the sensor resolutions that can be supported
+ * \param[in] sensor The camera sensor
+ *
+ * This function retrieves all the sizes supported by the sensor and
+ * filters all the resolutions that can be supported on the pipeline.
+ * It is possible that the sensor's maximum output resolution is higher
+ * than the ISP maximum input. In that case, this function filters out all
+ * the resolution incapable of being supported and returns the maximum
+ * sensor resolution that can be supported by the pipeline.
+ *
+ * \return Maximum sensor size supported on the pipeline
+ */
+Size RkISP1Path::filterSensorResolution(const CameraSensor *sensor)
+{
+	if (!sensorSizes_.empty())
+		return sensorSizes_.back();
+
+	std::vector<Size> sensorSizes;
+	const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
+	for (const auto iter : mbusCodes) {
+		std::vector<Size> sizes = sensor->sizes(iter);
+		for (Size sz : sizes)
+			sensorSizes.push_back(sz);
+	}
+
+	std::sort(sensorSizes.begin(), sensorSizes.end());
+
+	/* Remove duplicates. */
+	auto last = std::unique(sensorSizes.begin(), sensorSizes.end());
+	sensorSizes.erase(last, sensorSizes.end());
+
+	/* Discard any sizes that the pipeline is unable to support. */
+	for (auto sz : sensorSizes) {
+		if (sz.width > maxResolution_.width ||
+		    sz.height > maxResolution_.height)
+			continue;
+
+		sensorSizes_.push_back(sz);
+	}
+
+	return sensorSizes_.back();
+}
+
 StreamConfiguration
 RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size,
 				  StreamRole role)
 {
 	const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
-	const Size &resolution = sensor->resolution();
+	Size resolution = filterSensorResolution(sensor);
 
 	/* Min and max resolutions to populate the available stream formats. */
 	Size maxResolution = maxResolution_.boundedToAspectRatio(resolution)
@@ -222,7 +266,7 @@  CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
 						 StreamConfiguration *cfg)
 {
 	const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
-	const Size &resolution = sensor->resolution();
+	Size resolution = filterSensorResolution(sensor);
 
 	const StreamConfiguration reqCfg = *cfg;
 	CameraConfiguration::Status status = CameraConfiguration::Valid;
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
index 13ba4b62..03ff9543 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h
+++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
@@ -63,6 +63,7 @@  public:
 
 private:
 	void populateFormats();
+	Size filterSensorResolution(const CameraSensor *sensor);
 
 	static constexpr unsigned int RKISP1_BUFFER_COUNT = 4;
 
@@ -77,6 +78,8 @@  private:
 	std::unique_ptr<V4L2Subdevice> resizer_;
 	std::unique_ptr<V4L2VideoDevice> video_;
 	MediaLink *link_;
+
+	std::vector<Size> sensorSizes_;
 };
 
 class RkISP1MainPath : public RkISP1Path