[libcamera-devel] [RFC PATCH 3/6] libcamera: v4l2_subdevice: Add methods to get/set frame interval
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Wed Mar 17 11:58:28 CET 2021
Hi Marian,
On Wed, Mar 17, 2021 at 10:55:25AM +0100, Marian Cichy wrote:
> On 3/16/21 8:28 PM, Laurent Pinchart wrote:
> > On Tue, Mar 16, 2021 at 04:52:08PM +0100, Marian Cichy wrote:
> >> Add API-methods to get and set the frame interval on V4L2-subdevices.
> >>
> >> Signed-off-by: Marian Cichy <m.cichy at pengutronix.de>
> >> ---
> >> include/libcamera/internal/v4l2_subdevice.h | 4 ++
> >> src/libcamera/v4l2_subdevice.cpp | 43 +++++++++++++++++++++
> >> 2 files changed, 47 insertions(+)
> >>
> >> diff --git a/include/libcamera/internal/v4l2_subdevice.h b/include/libcamera/internal/v4l2_subdevice.h
> >> index d2b9ca55..310746d9 100644
> >> --- a/include/libcamera/internal/v4l2_subdevice.h
> >> +++ b/include/libcamera/internal/v4l2_subdevice.h
> >> @@ -12,6 +12,7 @@
> >> #include <vector>
> >>
> >> #include <libcamera/class.h>
> >> +#include <libcamera/fraction.h>
> >> #include <libcamera/geometry.h>
> >>
> >> #include "libcamera/internal/formats.h"
> >> @@ -60,6 +61,9 @@ public:
> >> int setFormat(unsigned int pad, V4L2SubdeviceFormat *format,
> >> Whence whence = ActiveFormat);
> >>
> >> + int getFrameInterval(unsigned int pad, Fraction *frameInterval);
> >> + int setFrameInterval(unsigned int pad, Fraction *frameInterval);
> >> +
> >> static std::unique_ptr<V4L2Subdevice>
> >> fromEntityName(const MediaDevice *media, const std::string &entity);
> >>
> >> diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp
> >> index 721ff5a9..eac2d7d3 100644
> >> --- a/src/libcamera/v4l2_subdevice.cpp
> >> +++ b/src/libcamera/v4l2_subdevice.cpp
> >> @@ -17,6 +17,7 @@
> >> #include <linux/media-bus-format.h>
> >> #include <linux/v4l2-subdev.h>
> >>
> >> +#include <libcamera/fraction.h>
> >> #include <libcamera/geometry.h>
> >>
> >> #include "libcamera/internal/log.h"
> >> @@ -440,6 +441,48 @@ int V4L2Subdevice::setFormat(unsigned int pad, V4L2SubdeviceFormat *format,
> >> return 0;
> >> }
> >>
> >> +int V4L2Subdevice::getFrameInterval(unsigned int pad, Fraction *frameInterval)
> >> +{
> >> + struct v4l2_subdev_frame_interval subdevFrameInterval = {};
> >> + subdevFrameInterval.pad = pad;
> >> +
> >> + int ret = ioctl(VIDIOC_SUBDEV_G_FRAME_INTERVAL, &subdevFrameInterval);
> >
> > Sensor drivers are supposed to control the frame rate through horizontal
> > and vertical blanking. Only in very specific cases do we want to use
> > these ioctls, when the sensor exposes a frame interval at the register
> > level (this will only be applicable to sensors containing an ISP). What
> > sensor are you using ?
>
> I am using the ar0237 sensor, it's driver is not upstream yet. We
> implement hblank/vblank only as read-only controls for now.
Looks like there's some work to do on the sensor side then ;-)
> However, using the i.MX-6Q, it is also possible to configure
> frame-dropping on the CSI-subdev. Afaik, this can only be configured
> with the frame_interval ioctl since the frame interval has to be set on
> source and sink pad.
Do you have a use case for this, compared to configuring the sensor with
a longer vertical blanking ?
> This is also why we propagate the frame interval from the sensor through
> the media pipeline. If for some reason, the CSI is configured to drop
> frames, we query the frame interval at the sensor, then try to set it on
> all following subdevices to effectively deactivate frame dropping.
>
> Of course, it is also thinkable that we want to configure the CSI to
> drop frames, for example to manage bandwidth.
>
> >> + if (ret) {
> >> + LOG(V4L2, Debug)
> >> + << "Unable to get frame interval on pad " << pad
> >> + << ": " << strerror(-ret);
> >> + return ret;
> >> + }
> >> +
> >> + frameInterval->numerator = subdevFrameInterval.interval.numerator;
> >> + frameInterval->denominator = subdevFrameInterval.interval.denominator;
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +int V4L2Subdevice::setFrameInterval(unsigned int pad, Fraction *frameInterval)
> >> +{
> >> + struct v4l2_subdev_frame_interval subdevFrameInterval = {};
> >> + struct v4l2_fract fract = { frameInterval->numerator,
> >> + frameInterval->denominator };
> >> +
> >> + subdevFrameInterval.pad = pad;
> >> + subdevFrameInterval.interval = fract;
> >> +
> >> + int ret = ioctl(VIDIOC_SUBDEV_S_FRAME_INTERVAL, &subdevFrameInterval);
> >> + if (ret) {
> >> + LOG(V4L2, Debug)
> >> + << "Unable to set frame interval on pad " << pad
> >> + << ": " << strerror(-ret);
> >> + return ret;
> >> + }
> >> +
> >> + frameInterval->numerator = subdevFrameInterval.interval.numerator;
> >> + frameInterval->denominator = subdevFrameInterval.interval.denominator;
> >> +
> >> + return 0;
> >> +}
> >> +
> >> /**
> >> * \brief Create a new video subdevice instance from \a entity in media device
> >> * \a media
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list