[PATCH 1/1] libcamera: Add request API support for media controller device

Nicolas Dufresne nicolas at ndufresne.ca
Mon Sep 23 20:09:51 CEST 2024


Hi,

Le lundi 23 septembre 2024 à 06:02 +0000, Harvey Yang a écrit :
> From: Han-Lin Chen <hanlinchen at chromium.org>
> 
> This patch adds `allocateRequests` with MEDIA_IOC_REQUEST_ALLOC
> , `queueRequest` with MEDIA_REQUEST_IOC_QUEUE, and `reInitRequest`
> with MEDIA_REQUEST_IOC_REINIT.
> 
> Signed-off-by: Han-Lin Chen <hanlinchen at chromium.org>
> Co-developed-by: Harvey Yang <chenghaoyang at chromium.org>
> ---
>  include/libcamera/internal/media_device.h |  4 ++
>  src/libcamera/media_device.cpp            | 87 +++++++++++++++++++++++
>  2 files changed, 91 insertions(+)
> 
> diff --git a/include/libcamera/internal/media_device.h b/include/libcamera/internal/media_device.h
> index e412d3a0..8f54dd12 100644
> --- a/include/libcamera/internal/media_device.h
> +++ b/include/libcamera/internal/media_device.h
> @@ -53,6 +53,10 @@ public:
>  	MediaLink *link(const MediaPad *source, const MediaPad *sink);
>  	int disableLinks();
>  
> +	int allocateRequests(unsigned int count, std::vector<UniqueFD> &requests);
> +	int queueRequest(int requestFd);
> +	int reInitRequest(int requestFd);
> +
>  	Signal<> disconnected;
>  
>  protected:
> diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp
> index bd054552..47b75809 100644
> --- a/src/libcamera/media_device.cpp
> +++ b/src/libcamera/media_device.cpp
> @@ -9,6 +9,7 @@
>  
>  #include <errno.h>
>  #include <fcntl.h>
> +#include <poll.h>
>  #include <stdint.h>
>  #include <string>
>  #include <string.h>
> @@ -836,4 +837,90 @@ int MediaDevice::setupLink(const MediaLink *link, unsigned int flags)
>  	return 0;
>  }
>  
> +/**
> + * \brief Allocate \a count requests with ioctl
> + * \param[in] count The number of requests to be allocated
> + * \param[out] requests The request file descriptors to be returned
> + *
> + * This function returns request file descriptors if the MediaDevice supports
> + * requests. The file descriptors can then be queued and re-inited afterwards.
> + *
> + * \sa queueRequest(int requestFd)
> + * \sa reInitRequest(int requestFd)
> + *
> + * \return 0 on success or a negative error code otherwise
> + */
> +int MediaDevice::allocateRequests(unsigned int count, std::vector<UniqueFD> &requests)
> +{
> +	for (unsigned int i = 0; i < count; i++) {
> +		int fd;
> +		int ret = ioctl(fd_.get(), MEDIA_IOC_REQUEST_ALLOC, &fd);
> +		if (ret) {
> +			LOG(MediaDevice, Error) << "Allocate request failed "
> +						<< strerror(-ret);
> +			return -EBUSY;
> +		}
> +		requests.emplace_back(fd);
> +	}
> +
> +	return 0;
> +}

Wouldn't if be nicer if the request was an object ?

> +
> +/**
> + * \brief Queue a request with ioctl
> + * \param[in] requestFd The request file descriptor
> + *
> + * This function queues a request that was allocated before.
> + *
> + * \sa allocateRequests(unsigned int count, std::vector<UniqueFD> &requests)
> + * \sa reInitRequest(int requestFd)
> + *
> + * \return 0 on success or a negative error code otherwise
> + */
> +int MediaDevice::queueRequest(int requestFd)
> +{
> +	int ret = ioctl(requestFd, MEDIA_REQUEST_IOC_QUEUE, NULL);
> +	if (ret)
> +		LOG(MediaDevice, Error) << "QueueRequest fd " << requestFd
> +					<< "failed: " << strerror(-ret);
> +	return ret;
> +}
> +
> +/**
> + * \brief Re-init a request with ioctl
> + * \param[in] requestFd The request file descriptor
> + *
> + * This function recycles a request that was allocated and queued before. It
> + * polls on \a requestFd to ensure the request is completed, and reinits the
> + * request.
> + *
> + * \sa allocateRequests(unsigned int count, std::vector<UniqueFD> &requests)
> + * \sa queueRequest(int requestFd)
> + *
> + * \return 0 on success or a negative error code otherwise
> + */
> +int MediaDevice::reInitRequest(int requestFd)
> +{
> +	struct pollfd pfd;
> +
> +	pfd.fd = requestFd;
> +	pfd.events = POLLPRI;
> +
> +	int ret = TEMP_FAILURE_RETRY(poll(&pfd, 1, 300));

Shouldn't we split polling and re-init ? Polling is a very important feature of
Requests, since it can be used as a synchronization point, avoiding numerous
independent queue polling. Its also nicer if callers can control (or avoid) the
timeout.

Nicolas

> +	if (ret < 0)
> +		LOG(MediaDevice, Error) << "The request " << requestFd
> +					<< " polled failed: " << strerror(-ret);
> +	else if (ret == 0)
> +		LOG(MediaDevice, Error) << "The request " << requestFd
> +					<< " polled timeout: " << strerror(-ret);
> +
> +	ret = ::ioctl(requestFd, MEDIA_REQUEST_IOC_REINIT, NULL);
> +	if (ret)
> +		LOG(MediaDevice, Error) << "The request " << requestFd
> +					<< " is queued but not yet completed: "
> +					<< strerror(-ret);
> +
> +	return ret;
> +}
> +
>  } /* namespace libcamera */



More information about the libcamera-devel mailing list