[libcamera-devel] [PATCH v2 05/17] v4l2: v4l2_camera_proxy: Implement VIDIOC_G/S_PRIORITY

Laurent Pinchart laurent.pinchart at ideasonboard.com
Sat Jun 20 03:42:30 CEST 2020


Hi Paul,

Thank you for the patch.

On Fri, Jun 19, 2020 at 02:41:11PM +0900, Paul Elder wrote:
> Implement VIDIOC_G_PRIORITY and VIDIOC_S_PRIORITY, according to what
> v4l2-compliance wants.

How about mentioning the kernel implementation instead of
v4l2-compliance ? Something along the lines of

Implement VIDIOC_G_PRIORITY and VIDIOC_S_PRIORITY. The behaviour
documented in the V4L2 specification doesn't match the implementation in
the Linux kernel, implement the latter.

> Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
> 
> ---
> Changes in v2:
> - use V4L2CameraFile instead of fd and priorities map
> ---
>  src/v4l2/v4l2_camera_proxy.cpp | 42 +++++++++++++++++++++++++++++++++-
>  src/v4l2/v4l2_camera_proxy.h   |  3 +++
>  2 files changed, 44 insertions(+), 1 deletion(-)
> 
> diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp
> index 117d7ff..3e95645 100644
> --- a/src/v4l2/v4l2_camera_proxy.cpp
> +++ b/src/v4l2/v4l2_camera_proxy.cpp
> @@ -37,7 +37,8 @@ V4L2CameraProxy::V4L2CameraProxy(unsigned int index,
>  				 std::shared_ptr<Camera> camera)
>  	: refcount_(0), index_(index), bufferCount_(0), currentBuf_(0),
>  	  vcam_(std::make_unique<V4L2Camera>(camera)), efd_(-1),
> -	  acquiredCf_(nullptr), initialized_(false)
> +	  v4l2RecordPriorityCf_(nullptr), acquiredCf_(nullptr),
> +	  initialized_(false)
>  {
>  	querycap(camera);
>  }
> @@ -344,6 +345,37 @@ int V4L2CameraProxy::vidioc_try_fmt(V4L2CameraFile *cf, struct v4l2_format *arg)
>  	return 0;
>  }
>  
> +int V4L2CameraProxy::vidioc_g_priority(V4L2CameraFile *cf, enum v4l2_priority *arg)
> +{
> +	LOG(V4L2Compat, Debug) << "Servicing vidioc_g_priority fd = " << cf->efd();
> +
> +	if (v4l2RecordPriorityCf_)
> +		*arg = V4L2_PRIORITY_RECORD;
> +	else
> +		*arg = cf->priority_;

This will please v4l2-compliance, but won't correctly support
V4L2_PRIORITY_INTERACTIVE and V4L2_PRIORITY_BACKGROUND. Is that why you
mentioned v4l2-compliance and not the kernel in the commit message ? Do
you think we should implement the full behaviour ? It shouldn't be too
difficult, but would require retrieving the max priority. You could do
so by storing a list of V4L2CameraFile in V4L2CameraProxy, or an array
of integers containing with the number of V4L2CameraFile for a given
priority.

To really implement priority support you would need to check if the file
has a high enough priority in all the ioctls that require doing so. For
the ioctls we support, that would be

	VIDIOC_S_FMT
	VIDIOC_S_PRIORITY
	VIDIOC_S_INPUT
	VIDIOC_REQBUFS
	VIDIOC_STREAMON
	VIDIOC_STREAMOFF

The check would simply verify that the file priority is >= max priority,
implemented in a helper function. I think that would also simplify the
implementation of vidioc_s_priority.

> +
> +	return 0;
> +}
> +
> +int V4L2CameraProxy::vidioc_s_priority(V4L2CameraFile *cf, enum v4l2_priority *arg)
> +{
> +	LOG(V4L2Compat, Debug)
> +		<< "Servicing vidioc_s_priority fd = " << cf->efd()
> +		<< " prio =  " << (int)*arg;

static_cast<int>

Should you check that the value of *arg is a valid priority ?

> +
> +	if (v4l2RecordPriorityCf_ && v4l2RecordPriorityCf_ != cf)
> +		return -EBUSY;
> +
> +	if (*arg == V4L2_PRIORITY_RECORD)
> +		v4l2RecordPriorityCf_ = cf;
> +	else if (v4l2RecordPriorityCf_ == cf)
> +		v4l2RecordPriorityCf_ = nullptr;
> +
> +	cf->priority_ = *arg;
> +
> +	return 0;
> +}
> +
>  int V4L2CameraProxy::freeBuffers()
>  {
>  	LOG(V4L2Compat, Debug) << "Freeing libcamera bufs";
> @@ -560,6 +592,8 @@ std::set<unsigned long> V4L2CameraProxy::supportedIoctls_ = {

I forgot to mention in the review of the patch that introduced this, I
wonder if std::unordered_set would be more efficient.

>  	VIDIOC_G_FMT,
>  	VIDIOC_S_FMT,
>  	VIDIOC_TRY_FMT,
> +	VIDIOC_G_PRIORITY,
> +	VIDIOC_S_PRIORITY,
>  	VIDIOC_REQBUFS,
>  	VIDIOC_QUERYBUF,
>  	VIDIOC_QBUF,
> @@ -597,6 +631,12 @@ int V4L2CameraProxy::ioctl(V4L2CameraFile *cf, unsigned long request, void *arg)
>  	case VIDIOC_TRY_FMT:
>  		ret = vidioc_try_fmt(cf, static_cast<struct v4l2_format *>(arg));
>  		break;
> +	case VIDIOC_G_PRIORITY:
> +		ret = vidioc_g_priority(cf, static_cast<enum v4l2_priority *>(arg));
> +		break;
> +	case VIDIOC_S_PRIORITY:
> +		ret = vidioc_s_priority(cf, static_cast<enum v4l2_priority *>(arg));
> +		break;
>  	case VIDIOC_REQBUFS:
>  		ret = vidioc_reqbufs(cf, static_cast<struct v4l2_requestbuffers *>(arg));
>  		break;
> diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h
> index dd7e793..3260eec 100644
> --- a/src/v4l2/v4l2_camera_proxy.h
> +++ b/src/v4l2/v4l2_camera_proxy.h
> @@ -51,6 +51,8 @@ private:
>  	int vidioc_g_fmt(V4L2CameraFile *cf, struct v4l2_format *arg);
>  	int vidioc_s_fmt(V4L2CameraFile *cf, struct v4l2_format *arg);
>  	int vidioc_try_fmt(V4L2CameraFile *cf, struct v4l2_format *arg);
> +	int vidioc_g_priority(V4L2CameraFile *cf, enum v4l2_priority *arg);
> +	int vidioc_s_priority(V4L2CameraFile *cf, enum v4l2_priority *arg);
>  	int vidioc_reqbufs(V4L2CameraFile *cf, struct v4l2_requestbuffers *arg);
>  	int vidioc_querybuf(V4L2CameraFile *cf, struct v4l2_buffer *arg);
>  	int vidioc_qbuf(V4L2CameraFile *cf, struct v4l2_buffer *arg);
> @@ -87,6 +89,7 @@ private:
>  
>  	int efd_;
>  
> +	V4L2CameraFile *v4l2RecordPriorityCf_;
>  	/*
>  	 * This is an exclusive lock on the camera. When this is not taken,
>  	 * anybody can call any ioctl before reqbufs. reqbufs with count > 0

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list