Received: by 10.223.176.46 with SMTP id f43csp283644wra; Thu, 25 Jan 2018 22:04:12 -0800 (PST) X-Google-Smtp-Source: AH8x226PL7x6qgOtfePpVLaZTP8ZkcirEUct0zvL3wln7snwHj5TiMRyyj/DjBOXRC1opyVJ9VaA X-Received: by 10.98.36.77 with SMTP id r74mr18446568pfj.31.1516946652435; Thu, 25 Jan 2018 22:04:12 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516946652; cv=none; d=google.com; s=arc-20160816; b=Q60ly01Q4zHWYTcPwzTNOc7gy4P+EPeGRKZk2DgLtcUv62txI+brkTA3k60pbT1139 WpljkijjVvSk3WGuC6MhUtxqoH6QSGx9cKsLoTt4YzfR20JZwS7eE2/DnohdqcB5xOwl qFkdeUw6XU+9wZWGMEgYgEyzohMHTrTj2fgcu4W3dhFkdgX2snCU9QsYFRN9U6rjaPPq XVrY3+XGB46dbqeTejhTaZV2edabmuZwI/YW/qGGq4jMYFT/bIp9i06qFLH/A/lw5yjl vePiV00XaTcrN5Nh8ygMomo7d73pZVq+qG76sIra1IGKAfLecRG6zFsk8ZJpAYM/ovMA pi1Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=3rBCm69AEUIRkWQ2Lwlm5JwUpUMmlCtNrbTu/CgaH5c=; b=zIK4BeLk7OhsbOIZAohW/PpqiPM0vMHJq1hFLXeT/jl+nfeE1+aJ6ZBEFtqS7birWI 3vHXMirs2SunHD+ybDGrkpQfhJUu0SYo1M84nUgDuDhJIz/HSZF/5jXi+A7aWC6GFqLs 8udT36tkYuv4StKY7iYv2erDbWZEFCJ//+FzDzF/d/rBs8es6O/GV9+ETOt9hR0oUsIT QrAiaJ1sLmI1/2RKeei0l88CNQkCbnUyjDE+SBBg2onLEJAuKeeK/mlUihIe7F2hAxcP fjOxmyp/0aLkaBunKyc97LrYI2IJ3Xqdagv+CU+Vbgk9oo66szS2V3StwoASXLP5tpci BlYQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=FdeFQmJp; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c22si2584712pgn.460.2018.01.25.22.03.57; Thu, 25 Jan 2018 22:04:12 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=FdeFQmJp; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751947AbeAZGDD (ORCPT + 99 others); Fri, 26 Jan 2018 01:03:03 -0500 Received: from mail-pg0-f66.google.com ([74.125.83.66]:44825 "EHLO mail-pg0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751602AbeAZGC7 (ORCPT ); Fri, 26 Jan 2018 01:02:59 -0500 Received: by mail-pg0-f66.google.com with SMTP id m20so6617344pgc.11 for ; Thu, 25 Jan 2018 22:02:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=3rBCm69AEUIRkWQ2Lwlm5JwUpUMmlCtNrbTu/CgaH5c=; b=FdeFQmJpYsnHCV407kHqPRYmBlA5ERfNp4Z2N6qcrD7RXnT3v35oqojjwH3mJUEn8M YV7vwEx8jG/1q7nA29OKDFclllqZWdsMwgfCs0yt8HCZh89FZpf4AeUOEWiUbvOJvXlj ycF0bFR+6oD6/jRH8UBTueqa7ALcxrAR2zZRY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=3rBCm69AEUIRkWQ2Lwlm5JwUpUMmlCtNrbTu/CgaH5c=; b=A9coqbXNmntP6jIZSfn0H9h6KGjhLw/AJcIqi3jXgsfXE/x3+Nqdu5L9wp30LSscIC DUvwDffzg4OQxnBQpGpRjxHb9OOMT+YQSOn3wJLC6Mqpx/DRzaKHHhwzCZ3pF40eqc3X dj4z9U0ZHFBFMWhYRaoEu//DGkEyk7FxlgO80wBa3uBiUK8WgzLpW/IK7Zh+EA/IqmVo 4LOBR7KqLWIVs2su+l4P390WsqvM6qPrtoqYIdrrQ2Ek9tTV3RSAmhOhvg5C6SR8tNa0 TIKiKjKQ9w2uyRZ2OdGP3MOEEUpPftEC3Gq3OrSnZlvMgwZ6YeVuj/oydPfEsNA/8H7D Sr8Q== X-Gm-Message-State: AKwxytexgr4fYSwaVlHZ1Gsbmyr9pQmWv7H/egIeZQvKeya14dtM3THl fBH+l4kdLaacEvPq53gKQnCeGw== X-Received: by 10.98.102.4 with SMTP id a4mr18177593pfc.210.1516946578437; Thu, 25 Jan 2018 22:02:58 -0800 (PST) Received: from acourbot.tok.corp.google.com ([2401:fa00:4:1002:a6cd:a898:e07b:a331]) by smtp.gmail.com with ESMTPSA id j3sm14543201pfh.39.2018.01.25.22.02.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 25 Jan 2018 22:02:58 -0800 (PST) From: Alexandre Courbot To: Mauro Carvalho Chehab , Hans Verkuil , Laurent Pinchart , Pawel Osciak , Marek Szyprowski , Tomasz Figa , Sakari Ailus , Gustavo Padovan Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Alexandre Courbot Subject: [RFC PATCH 6/8] v4l2: document the request API interface Date: Fri, 26 Jan 2018 15:02:14 +0900 Message-Id: <20180126060216.147918-7-acourbot@chromium.org> X-Mailer: git-send-email 2.16.0.rc1.238.g530d649a79-goog In-Reply-To: <20180126060216.147918-1-acourbot@chromium.org> References: <20180126060216.147918-1-acourbot@chromium.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Document how the request API can be used along with the existing V4L2 interface. Signed-off-by: Alexandre Courbot --- Documentation/media/uapi/v4l/buffer.rst | 10 +- Documentation/media/uapi/v4l/common.rst | 1 + Documentation/media/uapi/v4l/request-api.rst | 194 +++++++++++++++++++++++++++ Documentation/media/uapi/v4l/vidioc-qbuf.rst | 21 +++ 4 files changed, 223 insertions(+), 3 deletions(-) create mode 100644 Documentation/media/uapi/v4l/request-api.rst diff --git a/Documentation/media/uapi/v4l/buffer.rst b/Documentation/media/uapi/v4l/buffer.rst index ae6ee73f151c..9d082784081d 100644 --- a/Documentation/media/uapi/v4l/buffer.rst +++ b/Documentation/media/uapi/v4l/buffer.rst @@ -301,10 +301,14 @@ struct v4l2_buffer elements in the ``planes`` array. The driver will fill in the actual number of valid elements in that array. * - __u32 - - ``reserved2`` + - ``request_fd`` - - - A place holder for future extensions. Drivers and applications - must set this to 0. + - The file descriptor of the request associated with this buffer. + user-space can set this when calling :ref:`VIDIOC_QBUF`, and drivers + will return the request used when processing a buffer (if any) upon + :ref:`VIDIOC_DQBUF`. + + A value of 0 means the buffer is not associated with any request. * - __u32 - ``reserved`` - diff --git a/Documentation/media/uapi/v4l/common.rst b/Documentation/media/uapi/v4l/common.rst index 13f2ed3fc5a6..a4aa0059d45a 100644 --- a/Documentation/media/uapi/v4l/common.rst +++ b/Documentation/media/uapi/v4l/common.rst @@ -44,3 +44,4 @@ applicable to all devices. crop selection-api streaming-par + request-api diff --git a/Documentation/media/uapi/v4l/request-api.rst b/Documentation/media/uapi/v4l/request-api.rst new file mode 100644 index 000000000000..a758a5fd3ca0 --- /dev/null +++ b/Documentation/media/uapi/v4l/request-api.rst @@ -0,0 +1,194 @@ +.. -*- coding: utf-8; mode: rst -*- + +.. _media-request-api: + +Request API +=========== + +The Request API has been designed to allow V4L2 to deal with requirements of +modern IPs (stateless codecs, MIPI cameras, ...) and APIs (Android Codec v2). +One such requirement is the ability for devices belonging to the same pipeline +to reconfigure and collaborate closely on a per-frame basis. Another is +efficient support of stateless codecs, which need per-frame controls to be set +asynchronously in order to be efficiently used. + +Supporting these features without the Request API is possible but terribly +inefficient: user-space would have to flush all activity on the media pipeline, +reconfigure it for the next frame, queue the buffers to be processed with that +configuration, and wait until they are all available for dequeing before +considering the next frame. This defeats the purpose of having buffer queues +since in practice only one buffer would be queued at a time. + +The Request API allows a specific configuration of the pipeline (media +controller topology + controls for each device) to be associated with specific +buffers. The parameters are applied by each participating device as buffers +associated to a request flow in. This allows user-space to schedule several +tasks ("requests") with different parameters in advance, knowing that the +parameters will be applied when needed to get the expected result. Controls +values at the time of request completion are also available for reading. + +Usage +===== + +The Request API is used on top of standard media controller and V4L2 calls, +which are augmented with an extra ``request_fd`` parameter. All operations on +requests themselves are performed using the command parameter of the +:c:func:`MEDIA_IOC_REQUEST_CMD` ioctl. + +Allocation +---------- + +User-space allocates requests using the ``MEDIA_REQ_CMD_ALLOC`` command on +an opened media device. This returns a file descriptor representing the +request. Typically, several such requests will be allocated. + +Request Preparation +------------------- + +Standard V4L2 ioctls can then receive a request file descriptor to express the +fact that the ioctl is part of said request, and is not to be applied +immediately. V4L2 ioctls supporting this are :c:func:`VIDIOC_S_EXT_CTRLS` and +:c:func:`VIDIOC_QBUF`. Controls set with a request parameter are stored instead +of being immediately applied, and queued buffers will block the buffer queue +until the request becomes active. + +RFC Note: currently several buffers can be queued to the same queue with the +same request. The request parameters will be only be applied when processing +the first buffer. Does it make more sense to allow at most one buffer per +request per queue instead? + +Request Submission +------------------ + +Once the parameters and buffers of the request are specified, it can be +submitted with the ``MEDIA_REQ_CMD_SUBMIT`` command. This will make the buffers +associated to the request available to their driver, which can then apply the +saved controls as buffers are processed. A submitted request cannot be used +with further :c:func:`VIDIOC_S_EXT_CTRLS` and :c:func:`VIDIOC_QBUF` ioctls. + +If several devices are part of the request, individual drivers may synchronize +so the requested pipeline's topology is applied before the buffers are +processed. This is at the discretion of the drivers and is not a requirement. + +Buffers queued without an associated request after a request-bound buffer will +be processed using the state of the hardware at the time of the request +completion. All the same, controls set without a request are applied +immediately, regardless of whether a request is in use or not. + +User-space can ``poll()`` a request FD in order to wait until the request +completes. A request is considered complete once all its associated buffers are +available for dequeing. Note that user-space does not need to wait for the +request to complete to dequeue its buffers: buffers that are available halfway +through a request can be dequeued independently of the request's state. + +A completed request includes the state of all devices that had queued buffers +associated with it at the time of the request completion. User-space can query +that state by calling :c:func:`VIDIOC_G_EXT_CTRLS` with the request FD. + +Recycling and Destruction +------------------------- + +Finally, completed request can either be discarded or be reused. Calling +``close()`` on a request FD will make that FD unusable, freeing the request if +it is not referenced elsewhere. The ``MEDIA_REQ_CMD_REINIT`` command will clear +a request's state and make it available again. No state is retained by this +operation: the request is as if it had just been allocated via +``MEDIA_REQ_CMD_ALLOC``. + +RFC Note: Since requests are represented by FDs themselves, the +``MEDIA_REQ_CMD_SUBMIT`` and ``MEDIA_REQ_CMD_REININT`` commands can be performed +on the request FD instead of the media device. This means the media device would +only need to manage ``MEDIA_REQ_CMD_ALLOC``, which could be turned into an +ioctl, while ``MEDIA_REQ_CMD_SUBMIT`` and ``MEDIA_REQ_CMD_REININT`` would +become ioctls on the request itself. This has the advantage of allowing +receivers of a request FD to submit the request, and also decouples requests +from the media device - a scenario that makes sense for stateless codecs where +the media device is not really useful. + +Example for a Codec Device +-------------------------- + +Codecs are single-node V4L2 devices providing one OUTPUT queue (for user-space +to provide input buffers) and one CAPTURE queue (to retrieve processed data). + +In this use-case, request API is used to associate specific controls to be +applied by the driver before processing a buffer from the OUTPUT queue. When +retrieving a buffer from a capture queue, user-space can then identify which +request, if any, produced it by looking at the request_fd field of the dequeued +v4l2_buffer. + +Put into code, after obtaining a request, user-space can assign controls and one +OUTPUT buffer to it: + + struct v4l2_buf buf; + struct v4l2_ext_controls ctrls; + ... + ctrls.request_fd = req_fd; + ... + ioctl(codec_fd, VIDIOC_S_EXT_CTRLS, &ctrls); + ... + buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + buf.request_fd = req_fd; + ioctl(codec_fd, VIDIOC_QBUF, &buf); + +Note that request_fd shall not be specified for CAPTURE buffers. + +Once the request is fully prepared, it can be submitted to the driver: + + struct media_request_cmd cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd = MEDIA_REQ_CMD_SUBMIT; + cmd.fd = request_fd; + ioctl(media_fd, MEDIA_IOC_REQUEST_CMD, &cmd); + +User-space can then lookup the request_fd field of dequeued capture buffers to +confirm which one has been produced by the request. + + struct v4l2_buf buf; + + memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + ioctl(codec_fd, VIDIOC_DQBUF, &buf); + + if (buf.request_fd == request_fd) + ... + +Example for a Simple Capture Device +----------------------------------- + +With a simple capture device, requests can be used to specify controls to apply +to a given CAPTURE buffer. The driver will apply these controls before producing +the marked CAPTURE buffer. + + struct v4l2_buf buf; + struct v4l2_ext_controls ctrls; + ... + ctrls.request_fd = req_fd; + ... + ioctl(camera_fd, VIDIOC_S_EXT_CTRLS, &ctrls); + ... + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.request_fd = req_fd; + ioctl(camera_fd, VIDIOC_QBUF, &buf); + +Once the request is fully prepared, it can be submitted to the driver: + + struct media_request_cmd cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd = MEDIA_REQ_CMD_SUBMIT; + cmd.fd = request_fd; + ioctl(media_fd, MEDIA_IOC_REQUEST_CMD, &cmd); + +User-space can then lookup the request_fd field of dequeued capture buffers to +confirm which one has been produced by the request. + + struct v4l2_buf buf; + + memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + ioctl(camera_fd, VIDIOC_DQBUF, &buf); + + if (buf.request_fd == request_fd) + ... diff --git a/Documentation/media/uapi/v4l/vidioc-qbuf.rst b/Documentation/media/uapi/v4l/vidioc-qbuf.rst index 9e448a4aa3aa..0cd596bd4cde 100644 --- a/Documentation/media/uapi/v4l/vidioc-qbuf.rst +++ b/Documentation/media/uapi/v4l/vidioc-qbuf.rst @@ -98,6 +98,12 @@ dequeued, until the :ref:`VIDIOC_STREAMOFF ` or :ref:`VIDIOC_REQBUFS` ioctl is called, or until the device is closed. +For all buffer types, the ``request_fd`` field can be used when enqueing +to specify the file descriptor of a request, if requests are in use. +Setting it means that the buffer will not be passed to the driver until +the request itself is submitted. Also, the driver will apply any setting +associated with the request before processing the buffer. + Applications call the ``VIDIOC_DQBUF`` ioctl to dequeue a filled (capturing) or displayed (output) buffer from the driver's outgoing queue. They just set the ``type``, ``memory`` and ``reserved`` fields of @@ -115,6 +121,21 @@ queue. When the ``O_NONBLOCK`` flag was given to the :ref:`open() ` function, ``VIDIOC_DQBUF`` returns immediately with an ``EAGAIN`` error code when no buffer is available. +If a dequeued buffer was produced as the result of a request, then the +``request_fd`` field of :c:type:`v4l2_buffer` will be set to the file +descriptor of the request, regardless of whether the buffer was initially +queued with a request associated to it or not. + +RFC note: a request can be referenced by several FDs, especially if the +request is shared between different processes. Also a FD can be closed +after a request is submitted. In that case the FD does not make much sense. +Maybe it would be better to define request fd as + + union { u32 request_fd; u32 request_id; } + +and use request_id when communicating a request to userspace so they can be +unambiguously referenced? + The struct :c:type:`v4l2_buffer` structure is specified in :ref:`buffer`. -- 2.16.0.rc1.238.g530d649a79-goog