[{"id":11167,"web_url":"https://patchwork.libcamera.org/comment/11167/","msgid":"<20200704181523.GA6018@pendragon.ideasonboard.com>","date":"2020-07-04T18:15:23","subject":"Re: [libcamera-devel] [PATCH v3 04/22] libcamera: V4L2VideoDevice:\n\tAdd tryFormat","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Paul,\n\nThank you for the patch.\n\nOn Sat, Jul 04, 2020 at 10:31:22PM +0900, Paul Elder wrote:\n> Add tryFormat and its variations (meta, single-plane, multi-plane) to\n> V4L2VideoDevice.\n> \n> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> \n> ---\n> New in v3\n> ---\n>  include/libcamera/internal/v4l2_videodevice.h |   4 +\n>  src/libcamera/v4l2_videodevice.cpp            | 121 ++++++++++++++++++\n>  2 files changed, 125 insertions(+)\n> \n> diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h\n> index 4d21f5a..56c3aee 100644\n> --- a/include/libcamera/internal/v4l2_videodevice.h\n> +++ b/include/libcamera/internal/v4l2_videodevice.h\n> @@ -186,6 +186,7 @@ public:\n>  \tconst V4L2Capability &caps() const { return caps_; }\n>  \n>  \tint getFormat(V4L2DeviceFormat *format);\n> +\tint tryFormat(V4L2DeviceFormat *format);\n>  \tint setFormat(V4L2DeviceFormat *format);\n>  \tstd::map<V4L2PixelFormat, std::vector<SizeRange>> formats(uint32_t code = 0);\n>  \n> @@ -217,12 +218,15 @@ protected:\n>  \n>  private:\n>  \tint getFormatMeta(V4L2DeviceFormat *format);\n> +\tint tryFormatMeta(V4L2DeviceFormat *format);\n>  \tint setFormatMeta(V4L2DeviceFormat *format);\n>  \n>  \tint getFormatMultiplane(V4L2DeviceFormat *format);\n> +\tint tryFormatMultiplane(V4L2DeviceFormat *format);\n>  \tint setFormatMultiplane(V4L2DeviceFormat *format);\n>  \n>  \tint getFormatSingleplane(V4L2DeviceFormat *format);\n> +\tint tryFormatSingleplane(V4L2DeviceFormat *format);\n>  \tint setFormatSingleplane(V4L2DeviceFormat *format);\n>  \n>  \tstd::vector<V4L2PixelFormat> enumPixelformats(uint32_t code);\n> diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp\n> index 3614b2e..f25914c 100644\n> --- a/src/libcamera/v4l2_videodevice.cpp\n> +++ b/src/libcamera/v4l2_videodevice.cpp\n> @@ -723,6 +723,26 @@ int V4L2VideoDevice::getFormat(V4L2DeviceFormat *format)\n>  \t\treturn getFormatSingleplane(format);\n>  }\n>  \n> +/**\n> + * \\brief Try an image format on the V4L2 video device\n> + * \\param[inout] format The image format to test applicablity to the video device\n\ns/applicablity/applicability/\n\n> + *\n> + * Test if the supplied \\a format to the video device is acceptable, and return\n> + * the actually applied format parameters, as \\ref V4L2VideoDevice::tryFormat\n\nThis is the documentation of V4L2VideoDevice::tryFormat... Did you mean\nsetFormat() ? You shouldn't need \\ref or the V4L2VideoDevice prefix,\nwriting setFormat() should generate the right link.\n\nAlso, the parameters are not \"applied\". How about\n\n * Try the supplied \\a format on the video device without applying it, returning\n * the format that would be applied. This is equivalent to setFormat(), except\n * that the device configuration is not changed.\n\n> + * would do.\n> + *\n> + * \\return 0 on success or a negative error code otherwise\n> + */\n> +int V4L2VideoDevice::tryFormat(V4L2DeviceFormat *format)\n> +{\n> +\tif (caps_.isMeta())\n> +\t\treturn tryFormatMeta(format);\n> +\telse if (caps_.isMultiplanar())\n> +\t\treturn tryFormatMultiplane(format);\n> +\telse\n> +\t\treturn tryFormatSingleplane(format);\n> +}\n> +\n>  /**\n>   * \\brief Configure an image format on the V4L2 video device\n>   * \\param[inout] format The image format to apply to the video device\n> @@ -765,6 +785,35 @@ int V4L2VideoDevice::getFormatMeta(V4L2DeviceFormat *format)\n>  \treturn 0;\n>  }\n>  \n> +int V4L2VideoDevice::tryFormatMeta(V4L2DeviceFormat *format)\n> +{\n> +\tstruct v4l2_format v4l2Format = {};\n> +\tstruct v4l2_meta_format *pix = &v4l2Format.fmt.meta;\n> +\tint ret;\n> +\n> +\tv4l2Format.type = bufferType_;\n> +\tpix->dataformat = format->fourcc;\n> +\tpix->buffersize = format->planes[0].size;\n> +\tret = ioctl(VIDIOC_TRY_FMT, &v4l2Format);\n> +\tif (ret) {\n> +\t\tLOG(V4L2, Error) << \"Unable to try format: \" << strerror(-ret);\n> +\t\treturn ret;\n> +\t}\n> +\n> +\t/*\n> +\t * Return to caller the format actually applied on the video device,\n> +\t * which might differ from the requested one.\n> +\t */\n> +\tformat->size.width = 0;\n> +\tformat->size.height = 0;\n> +\tformat->fourcc = V4L2PixelFormat(pix->dataformat);\n> +\tformat->planesCount = 1;\n> +\tformat->planes[0].bpl = pix->buffersize;\n> +\tformat->planes[0].size = pix->buffersize;\n> +\n> +\treturn 0;\n> +}\n> +\n\nThis is duplicating quite a bit of code. How about turning the existing\nsetFormatMeta(), setFormatMultiplane() and setFormatSinglePlane()\nfunctions into trySetFormat*(), with a parameter to tell whether to try\nthe format or set it (can be a \"bool set\" as these are private\nfunctions, if it was a public API an enum would be better) ?\n\nAs the error message is also different (the functions here print \"Unable\nto try format\"), if you want to avoid a\t(set ? \"set\" : \"try\")\nconditional, you can move the error messages from the low-level\nfunctions to setFormat() and tryFormat(). Up to you.\n\nWith these changes,\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n>  int V4L2VideoDevice::setFormatMeta(V4L2DeviceFormat *format)\n>  {\n>  \tstruct v4l2_format v4l2Format = {};\n> @@ -820,6 +869,46 @@ int V4L2VideoDevice::getFormatMultiplane(V4L2DeviceFormat *format)\n>  \treturn 0;\n>  }\n>  \n> +int V4L2VideoDevice::tryFormatMultiplane(V4L2DeviceFormat *format)\n> +{\n> +\tstruct v4l2_format v4l2Format = {};\n> +\tstruct v4l2_pix_format_mplane *pix = &v4l2Format.fmt.pix_mp;\n> +\tint ret;\n> +\n> +\tv4l2Format.type = bufferType_;\n> +\tpix->width = format->size.width;\n> +\tpix->height = format->size.height;\n> +\tpix->pixelformat = format->fourcc;\n> +\tpix->num_planes = format->planesCount;\n> +\tpix->field = V4L2_FIELD_NONE;\n> +\n> +\tfor (unsigned int i = 0; i < pix->num_planes; ++i) {\n> +\t\tpix->plane_fmt[i].bytesperline = format->planes[i].bpl;\n> +\t\tpix->plane_fmt[i].sizeimage = format->planes[i].size;\n> +\t}\n> +\n> +\tret = ioctl(VIDIOC_TRY_FMT, &v4l2Format);\n> +\tif (ret) {\n> +\t\tLOG(V4L2, Error) << \"Unable to try format: \" << strerror(-ret);\n> +\t\treturn ret;\n> +\t}\n> +\n> +\t/*\n> +\t * Return to caller the format actually applied on the video device,\n> +\t * which might differ from the requested one.\n> +\t */\n> +\tformat->size.width = pix->width;\n> +\tformat->size.height = pix->height;\n> +\tformat->fourcc = V4L2PixelFormat(pix->pixelformat);\n> +\tformat->planesCount = pix->num_planes;\n> +\tfor (unsigned int i = 0; i < format->planesCount; ++i) {\n> +\t\tformat->planes[i].bpl = pix->plane_fmt[i].bytesperline;\n> +\t\tformat->planes[i].size = pix->plane_fmt[i].sizeimage;\n> +\t}\n> +\n> +\treturn 0;\n> +}\n> +\n>  int V4L2VideoDevice::setFormatMultiplane(V4L2DeviceFormat *format)\n>  {\n>  \tstruct v4l2_format v4l2Format = {};\n> @@ -883,6 +972,38 @@ int V4L2VideoDevice::getFormatSingleplane(V4L2DeviceFormat *format)\n>  \treturn 0;\n>  }\n>  \n> +int V4L2VideoDevice::tryFormatSingleplane(V4L2DeviceFormat *format)\n> +{\n> +\tstruct v4l2_format v4l2Format = {};\n> +\tstruct v4l2_pix_format *pix = &v4l2Format.fmt.pix;\n> +\tint ret;\n> +\n> +\tv4l2Format.type = bufferType_;\n> +\tpix->width = format->size.width;\n> +\tpix->height = format->size.height;\n> +\tpix->pixelformat = format->fourcc;\n> +\tpix->bytesperline = format->planes[0].bpl;\n> +\tpix->field = V4L2_FIELD_NONE;\n> +\tret = ioctl(VIDIOC_TRY_FMT, &v4l2Format);\n> +\tif (ret) {\n> +\t\tLOG(V4L2, Error) << \"Unable to try format: \" << strerror(-ret);\n> +\t\treturn ret;\n> +\t}\n> +\n> +\t/*\n> +\t * Return to caller the format actually applied on the device,\n> +\t * which might differ from the requested one.\n> +\t */\n> +\tformat->size.width = pix->width;\n> +\tformat->size.height = pix->height;\n> +\tformat->fourcc = V4L2PixelFormat(pix->pixelformat);\n> +\tformat->planesCount = 1;\n> +\tformat->planes[0].bpl = pix->bytesperline;\n> +\tformat->planes[0].size = pix->sizeimage;\n> +\n> +\treturn 0;\n> +}\n> +\n>  int V4L2VideoDevice::setFormatSingleplane(V4L2DeviceFormat *format)\n>  {\n>  \tstruct v4l2_format v4l2Format = {};","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 24550BD790\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSat,  4 Jul 2020 18:15:30 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 979CA60E01;\n\tSat,  4 Jul 2020 20:15:29 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 562C7609C7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat,  4 Jul 2020 20:15:28 +0200 (CEST)","from pendragon.ideasonboard.com (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id C2A4A296;\n\tSat,  4 Jul 2020 20:15:27 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"wMpA0qj7\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1593886527;\n\tbh=gu7jgBuIgj4klrcqCXCZWyieUUvbQmRIf7h0DJGWtyc=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=wMpA0qj7MPlVMossZK/L8lcIP3XB7SMDjDeRnJxK6bKU46zkotyKmDEI441DX5MCZ\n\ti/ofRntf8D0QzzKHpaPlfZPqfTruEWX2NPs6Hd8BV1VkbeHahn1/1BPag1yj00gKC/\n\tFoSu3jzCYevRP8ekaeEOzVqCpFFH8RscL1KcdLRk=","Date":"Sat, 4 Jul 2020 21:15:23 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Paul Elder <paul.elder@ideasonboard.com>","Message-ID":"<20200704181523.GA6018@pendragon.ideasonboard.com>","References":"<20200704133140.1738660-1-paul.elder@ideasonboard.com>\n\t<20200704133140.1738660-5-paul.elder@ideasonboard.com>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20200704133140.1738660-5-paul.elder@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v3 04/22] libcamera: V4L2VideoDevice:\n\tAdd tryFormat","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]