From patchwork Fri Mar 1 11:51:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 690 Return-Path: Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AC010610BF for ; Fri, 1 Mar 2019 12:52:44 +0100 (CET) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 2F57EC0011; Fri, 1 Mar 2019 11:52:42 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 1 Mar 2019 12:51:35 +0100 Message-Id: <20190301115139.11060-2-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190301115139.11060-1-jacopo@jmondi.org> References: <20190301115139.11060-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v6 1/5] libcamera: v4l2_subdevice: Implement ENUM_FRAME_SIZES X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 01 Mar 2019 11:52:44 -0000 Implement format and size enumeration methods to list all the available subdevice image resolutions and formats. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/libcamera/geometry.cpp | 34 +++++++++++ src/libcamera/include/geometry.h | 12 ++++ src/libcamera/include/v4l2_subdevice.h | 11 +++- src/libcamera/v4l2_subdevice.cpp | 84 ++++++++++++++++++++++++++ 4 files changed, 139 insertions(+), 2 deletions(-) diff --git a/src/libcamera/geometry.cpp b/src/libcamera/geometry.cpp index 57f4fc7716d9..b6b6592bdfec 100644 --- a/src/libcamera/geometry.cpp +++ b/src/libcamera/geometry.cpp @@ -46,4 +46,38 @@ namespace libcamera { * \brief The distance between the top and bottom sides */ +/** + * \struct SizeRange + * \brief Describe a range of image sizes + * + * SizeRange describes a range of image sizes included in the (minWidth, + * minHeight) - (maxWidth, maxHeight) interval. If the minimum and + * maximum sizes are identical it represents a single image resolution. + */ + +/** + * \fn SizeRange::SizeRange() + * \brief Construct a size range + */ + +/** + * \var SizeRange::minWidth + * \brief The minimum image width + */ + +/** + * \var SizeRange::minHeight + * \brief The minimum image height + */ + +/** + * \var SizeRange::maxWidth + * \brief The maximum image width + */ + +/** + * \var SizeRange::maxHeight + * \brief The maximum image height + */ + } /* namespace libcamera */ diff --git a/src/libcamera/include/geometry.h b/src/libcamera/include/geometry.h index cc146da7cb0d..eadc4ed4f9cb 100644 --- a/src/libcamera/include/geometry.h +++ b/src/libcamera/include/geometry.h @@ -17,6 +17,18 @@ struct Rectangle { unsigned int h; }; +struct SizeRange { + SizeRange(unsigned int minW, unsigned int minH, + unsigned int maxW, unsigned int maxH) + : minWidth(minW), minHeight(minH), maxWidth(maxW), + maxHeight(maxH) {} + + unsigned int minWidth; + unsigned int minHeight; + unsigned int maxWidth; + unsigned int maxHeight; +}; + } /* namespace libcamera */ #endif /* __LIBCAMERA_GEOMETRY_H__ */ diff --git a/src/libcamera/include/v4l2_subdevice.h b/src/libcamera/include/v4l2_subdevice.h index 669e79f9a9fd..aa7451e86962 100644 --- a/src/libcamera/include/v4l2_subdevice.h +++ b/src/libcamera/include/v4l2_subdevice.h @@ -7,15 +7,16 @@ #ifndef __LIBCAMERA_V4L2_SUBDEVICE_H__ #define __LIBCAMERA_V4L2_SUBDEVICE_H__ +#include #include +#include +#include "geometry.h" #include "log.h" #include "media_object.h" namespace libcamera { -struct Rectangle; - struct V4L2SubdeviceFormat { uint32_t mbus_code; uint32_t width; @@ -39,6 +40,9 @@ public: int setCrop(unsigned int pad, Rectangle *rect); int setCompose(unsigned int pad, Rectangle *rect); + const std::map> + formats(unsigned int pad); + int getFormat(unsigned int pad, V4L2SubdeviceFormat *format); int setFormat(unsigned int pad, V4L2SubdeviceFormat *format); @@ -46,6 +50,9 @@ protected: std::string logPrefix() const; private: + std::vector enumPadSizes(unsigned int pad, + unsigned int code); + int setSelection(unsigned int pad, unsigned int target, Rectangle *rect); diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp index 87377762664d..07035886c766 100644 --- a/src/libcamera/v4l2_subdevice.cpp +++ b/src/libcamera/v4l2_subdevice.cpp @@ -183,6 +183,57 @@ int V4L2Subdevice::setCompose(unsigned int pad, Rectangle *rect) return setSelection(pad, V4L2_SEL_TGT_COMPOSE, rect); } +/** + * \brief List the sub-device image resolutions and formats on \a pad + * \param[in] pad The 0-indexed pad number to enumerate formats on + * + * Retrieve a list of image formats and sizes on the \a pad of a video + * subdevice. Subdevices can report either a list of discrete sizes they + * support or a list of intervals expressed as a [min-max] sizes range. + * + * Each image size list is associated with a media bus pixel code for which + * the reported resolutions are supported. + * + * \return A map of image formats associated with a list of image sizes, or + * an empty map on error or if the pad does not exist + */ +const std::map> +V4L2Subdevice::formats(unsigned int pad) +{ + std::map> formatMap = {}; + struct v4l2_subdev_mbus_code_enum mbusEnum = {}; + int ret; + + if (pad >= entity_->pads().size()) { + LOG(V4L2Subdev, Error) + << "Invalid pad: " << pad; + return formatMap; + } + + mbusEnum.pad = pad; + mbusEnum.index = 0; + mbusEnum.which = V4L2_SUBDEV_FORMAT_ACTIVE; + while (true) { + ret = ioctl(fd_, VIDIOC_SUBDEV_ENUM_MBUS_CODE, &mbusEnum); + if (ret) + break; + + formatMap[mbusEnum.code] = enumPadSizes(pad, mbusEnum.code); + + mbusEnum.index++; + } + + if (ret && (errno != EINVAL && errno != ENOTTY)) { + ret = -errno; + LOG(V4L2Subdev, Error) + << "Unable to enumerate formats on pad " << pad + << ": " << strerror(-ret); + formatMap.clear(); + } + + return formatMap; +} + /** * \brief Retrieve the image format set on one of the V4L2 subdevice pads * \param[in] pad The 0-indexed pad number the format is to be retrieved from @@ -248,6 +299,39 @@ int V4L2Subdevice::setFormat(unsigned int pad, V4L2SubdeviceFormat *format) return 0; } +std::vector V4L2Subdevice::enumPadSizes(unsigned int pad, + unsigned int code) +{ + struct v4l2_subdev_frame_size_enum sizeEnum = {}; + std::vector sizes = {}; + int ret; + + sizeEnum.index = 0; + sizeEnum.pad = pad; + sizeEnum.code = code; + sizeEnum.which = V4L2_SUBDEV_FORMAT_ACTIVE; + while (true) { + ret = ioctl(fd_, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, &sizeEnum); + if (ret) + break; + + sizes.emplace_back(sizeEnum.min_width, sizeEnum.min_height, + sizeEnum.max_width, sizeEnum.max_height); + + sizeEnum.index++; + } + + if (ret && (errno != EINVAL && errno != ENOTTY)) { + ret = -errno; + LOG(V4L2Subdev, Error) + << "Unable to enumerate sizes on pad " << pad + << ": " << strerror(-ret); + sizes.clear(); + } + + return sizes; +} + int V4L2Subdevice::setSelection(unsigned int pad, unsigned int target, Rectangle *rect) { From patchwork Fri Mar 1 11:51:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 691 Return-Path: Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 824F3610C3 for ; Fri, 1 Mar 2019 12:52:45 +0100 (CET) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id D389CC0014; Fri, 1 Mar 2019 11:52:43 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 1 Mar 2019 12:51:36 +0100 Message-Id: <20190301115139.11060-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190301115139.11060-1-jacopo@jmondi.org> References: <20190301115139.11060-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v6 2/5] test: v4l2_subdevice: Add ListFormat test X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 01 Mar 2019 11:52:45 -0000 Add test to list formats on a v4l2 subdevice. Reviewed-by: Laurent Pinchart Signed-off-by: Jacopo Mondi --- test/v4l2_subdevice/list_formats.cpp | 81 ++++++++++++++++++++++++++++ test/v4l2_subdevice/meson.build | 1 + 2 files changed, 82 insertions(+) create mode 100644 test/v4l2_subdevice/list_formats.cpp diff --git a/test/v4l2_subdevice/list_formats.cpp b/test/v4l2_subdevice/list_formats.cpp new file mode 100644 index 000000000000..b4eab68f9f7e --- /dev/null +++ b/test/v4l2_subdevice/list_formats.cpp @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * libcamera V4L2 Subdevice format handling test + */ + +#include +#include +#include + +#include "geometry.h" +#include "v4l2_subdevice.h" +#include "v4l2_subdevice_test.h" + +using namespace std; +using namespace libcamera; + +/* List image formats on the "Scaler" subdevice of vimc media device. */ + +class ListFormatsTest : public V4L2SubdeviceTest +{ +protected: + int run() override; + +private: + void printFormats(unsigned int pad, unsigned code, + std::vector &formats); +}; + +void ListFormatsTest::printFormats(unsigned int pad, + unsigned int code, + std::vector &sizes) +{ + cout << "Enumerate formats on pad " << pad << endl; + for (SizeRange &size : sizes) { + cout << " mbus code: 0x" << setfill('0') << setw(4) + << hex << code << endl; + cout << " min width: " << dec << size.minWidth << endl; + cout << " min height: " << dec << size.minHeight << endl; + cout << " max width: " << dec << size.maxWidth << endl; + cout << " max height: " << dec << size.maxHeight << endl; + } +} + +int ListFormatsTest::run() +{ + /* List all formats available on existing "Scaler" pads. */ + std::map> formats; + + formats = scaler_->formats(0); + if (formats.size() == 0) { + cerr << "Failed to list formats on pad 0 of subdevice " + << scaler_->deviceName() << endl; + return TestFail; + } + for (auto it = formats.begin(); it != formats.end(); ++it) + printFormats(0, it->first, it->second); + + formats = scaler_->formats(1); + if (formats.size() == 0) { + cerr << "Failed to list formats on pad 1 of subdevice " + << scaler_->deviceName() << endl; + return TestFail; + } + for (auto it = formats.begin(); it != formats.end(); ++it) + printFormats(1, it->first, it->second); + + /* List format on a non-existing pad, format vector shall be empty. */ + formats = scaler_->formats(2); + if (formats.size() != 0) { + cerr << "Listing formats on non-existing pad 2 of subdevice " + << scaler_->deviceName() + << " should return an empty format list" << endl; + return TestFail; + } + + return TestPass; +} + +TEST_REGISTER(ListFormatsTest); diff --git a/test/v4l2_subdevice/meson.build b/test/v4l2_subdevice/meson.build index f45dca0d23d7..80cfbbbf9413 100644 --- a/test/v4l2_subdevice/meson.build +++ b/test/v4l2_subdevice/meson.build @@ -1,4 +1,5 @@ v4l2_subdevice_tests = [ + [ 'list_formats', 'list_formats.cpp'], [ 'test_formats', 'test_formats.cpp'], ] From patchwork Fri Mar 1 11:51:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 692 Return-Path: Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2CEF661114 for ; Fri, 1 Mar 2019 12:52:46 +0100 (CET) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id AAC95C0015; Fri, 1 Mar 2019 11:52:44 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 1 Mar 2019 12:51:37 +0100 Message-Id: <20190301115139.11060-4-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190301115139.11060-1-jacopo@jmondi.org> References: <20190301115139.11060-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v6 3/5] libcamera: v4l2_subdevice: Cosmetic update X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 01 Mar 2019 11:52:46 -0000 Cosmetic updated of V4L2Subdevice class: re-sort methods and comments to reflect the declaration order in the class definition. Cosmetic update, no functional changes intended. Signed-off-by: Jacopo Mondi Acked-by: Laurent Pinchart --- src/libcamera/v4l2_subdevice.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp index 07035886c766..de006b898af9 100644 --- a/src/libcamera/v4l2_subdevice.cpp +++ b/src/libcamera/v4l2_subdevice.cpp @@ -54,6 +54,11 @@ LOG_DEFINE_CATEGORY(V4L2Subdev) * Section 4.15.3.1 of the above mentioned Linux kernel documentation section. */ +/** + * \var V4L2SubdeviceFormat::mbus_code + * \brief The image format bus code + */ + /** * \var V4L2SubdeviceFormat::width * \brief The image width in pixels @@ -64,11 +69,6 @@ LOG_DEFINE_CATEGORY(V4L2Subdev) * \brief The image height in pixels */ -/** - * \var V4L2SubdeviceFormat::mbus_code - * \brief The image format bus code - */ - /** * \class V4L2Subdevice * \brief A V4L2 subdevice as exposed by the Linux kernel @@ -154,11 +154,6 @@ void V4L2Subdevice::close() * \return The name of the media entity the subdevice is associated to */ -std::string V4L2Subdevice::logPrefix() const -{ - return "'" + deviceName() + "'"; -} - /** * \brief Set a crop rectangle on one of the V4L2 subdevice pads * \param[in] pad The 0-indexed pad number the rectangle is to be applied to @@ -299,6 +294,11 @@ int V4L2Subdevice::setFormat(unsigned int pad, V4L2SubdeviceFormat *format) return 0; } +std::string V4L2Subdevice::logPrefix() const +{ + return "'" + deviceName() + "'"; +} + std::vector V4L2Subdevice::enumPadSizes(unsigned int pad, unsigned int code) { From patchwork Fri Mar 1 11:51:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 693 Return-Path: Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 02364610F5 for ; Fri, 1 Mar 2019 12:52:47 +0100 (CET) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 57CE5C0006; Fri, 1 Mar 2019 11:52:45 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 1 Mar 2019 12:51:38 +0100 Message-Id: <20190301115139.11060-5-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190301115139.11060-1-jacopo@jmondi.org> References: <20190301115139.11060-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v6 4/5] libcamera: v4l2_device: Add support for META_CAPTURE devices X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 01 Mar 2019 11:52:47 -0000 Add support for devices that provide video meta-data to v4l2_device.cpp and re-arrange bufferType handling in open() method. Reviewed-by: Kieran Bingham Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/libcamera/include/v4l2_device.h | 26 ++++++++++- src/libcamera/v4l2_device.cpp | 70 +++++++++++++++++++++-------- 2 files changed, 76 insertions(+), 20 deletions(-) diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index 622c9722c992..5c379fac66dc 100644 --- a/src/libcamera/include/v4l2_device.h +++ b/src/libcamera/include/v4l2_device.h @@ -51,13 +51,37 @@ struct V4L2Capability final : v4l2_capability { bool isCapture() const { return device_caps() & (V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_VIDEO_CAPTURE_MPLANE); + V4L2_CAP_VIDEO_CAPTURE_MPLANE | + V4L2_CAP_META_CAPTURE); } bool isOutput() const { return device_caps() & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE); } + bool isVideo() const + { + return device_caps() & (V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_VIDEO_CAPTURE_MPLANE | + V4L2_CAP_VIDEO_OUTPUT | + V4L2_CAP_VIDEO_OUTPUT_MPLANE); + } + bool isMeta() const + { + return device_caps() & V4L2_CAP_META_CAPTURE; + } + bool isVideoCapture() const + { + return isVideo() && isCapture(); + } + bool isVideoOutput() const + { + return isVideo() && isOutput(); + } + bool isMetaCapture() const + { + return isMeta() && isCapture(); + } bool hasStreaming() const { return device_caps() & V4L2_CAP_STREAMING; diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 4c670185bb7c..b19cf9f78029 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -69,14 +69,47 @@ LOG_DEFINE_CATEGORY(V4L2) /** * \fn bool V4L2Capability::isCapture() - * \brief Identify if the device is capable of capturing video - * \return True if the device can capture video frames + * \brief Identify if the device captures data + * \return True if the device can capture data */ /** * \fn bool V4L2Capability::isOutput() - * \brief Identify if the device is capable of outputting video - * \return True if the device can output video frames + * \brief Identify if the device outputs data + * \return True if the device can output data + */ + +/** + * \fn bool V4L2Capability::isVideo() + * \brief Identify if the device captures or outputs images + * \return True if the device can capture or output images + */ + +/** + * \fn bool V4L2Capability::isMeta() + * \brief Identify if the device captures or outputs image meta-data + * + * \todo Add support for META_CAPTURE introduced in Linux v5.0 + * + * \return True if the device can capture or output image meta-data + */ + +/** + * \fn bool V4L2Capability::isVideoCapture() + * \brief Identify if the device captures images + * \return True if the device can capture images + */ + +/** + * \fn bool V4L2Capability::isVideoOutput() + * \brief Identify if the device outputs images + * \return True if the device can output images + */ + +/** + * \fn bool V4L2Capability::isMetaCapture() + * \brief Identify if the device captures image meta-data + * \return True if the device can capture image meta-data */ /** @@ -280,33 +313,32 @@ int V4L2Device::open() << "Opened device " << caps_.bus_info() << ": " << caps_.driver() << ": " << caps_.card(); - if (!caps_.isCapture() && !caps_.isOutput()) { - LOG(V4L2, Debug) << "Device is not a supported type"; - return -EINVAL; - } - if (!caps_.hasStreaming()) { LOG(V4L2, Error) << "Device does not support streaming I/O"; return -EINVAL; } - if (caps_.isCapture()) + /* + * Set buffer type and wait for read notifications on CAPTURE devices + * (POLLIN), and write notifications for OUTPUT devices (POLLOUT). + */ + if (caps_.isVideoCapture()) { + fdEvent_ = new EventNotifier(fd_, EventNotifier::Read); bufferType_ = caps_.isMultiplanar() ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE; - else + } else if (caps_.isVideoOutput()) { + fdEvent_ = new EventNotifier(fd_, EventNotifier::Write); bufferType_ = caps_.isMultiplanar() ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : V4L2_BUF_TYPE_VIDEO_OUTPUT; - - /* - * We wait for Read notifications on CAPTURE devices (POLLIN), and - * Write notifications for OUTPUT devices (POLLOUT). - */ - if (caps_.isCapture()) + } else if (caps_.isMetaCapture()) { fdEvent_ = new EventNotifier(fd_, EventNotifier::Read); - else - fdEvent_ = new EventNotifier(fd_, EventNotifier::Write); + bufferType_ = V4L2_BUF_TYPE_META_CAPTURE; + } else { + LOG(V4L2, Debug) << "Device is not a supported type"; + return -EINVAL; + } fdEvent_->activated.connect(this, &V4L2Device::bufferAvailable); fdEvent_->setEnabled(false); From patchwork Fri Mar 1 11:51:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 694 Return-Path: Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AA2CE61114 for ; Fri, 1 Mar 2019 12:52:47 +0100 (CET) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 2CD14C000D; Fri, 1 Mar 2019 11:52:45 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 1 Mar 2019 12:51:39 +0100 Message-Id: <20190301115139.11060-6-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190301115139.11060-1-jacopo@jmondi.org> References: <20190301115139.11060-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v6 5/5] libcamera: v4l2_device: Cosmetic update X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 01 Mar 2019 11:52:47 -0000 Cosmetic update of V4L2Device class: - remove the return type from Doxygen documentation of inline functions - re-sort methods implementation to reflect the declaration order in the class definition Cosmetic update, no functional changes intended. Signed-off-by: Jacopo Mondi Acked-by: Laurent Pinchart --- src/libcamera/v4l2_device.cpp | 412 +++++++++++++++++----------------- 1 file changed, 206 insertions(+), 206 deletions(-) diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index b19cf9f78029..5f2cf4846c65 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -37,56 +37,56 @@ LOG_DEFINE_CATEGORY(V4L2) */ /** - * \fn const char *V4L2Capability::driver() + * \fn V4L2Capability::driver() * \brief Retrieve the driver module name * \return The string containing the name of the driver module */ /** - * \fn const char *V4L2Capability::card() + * \fn V4L2Capability::card() * \brief Retrieve the device card name * \return The string containing the device name */ /** - * \fn const char *V4L2Capability::bus_info() + * \fn V4L2Capability::bus_info() * \brief Retrieve the location of the device in the system * \return The string containing the device location */ /** - * \fn unsigned int V4L2Capability::device_caps() + * \fn V4L2Capability::device_caps() * \brief Retrieve the capabilities of the device * \return The device specific capabilities if V4L2_CAP_DEVICE_CAPS is set or * driver capabilities otherwise */ /** - * \fn bool V4L2Capability::isMultiplanar() + * \fn V4L2Capability::isMultiplanar() * \brief Identify if the device implements the V4L2 multiplanar APIs * \return True if the device supports multiplanar APIs */ /** - * \fn bool V4L2Capability::isCapture() + * \fn V4L2Capability::isCapture() * \brief Identify if the device captures data * \return True if the device can capture data */ /** - * \fn bool V4L2Capability::isOutput() + * \fn V4L2Capability::isOutput() * \brief Identify if the device outputs data * \return True if the device can output data */ /** - * \fn bool V4L2Capability::isVideo() + * \fn V4L2Capability::isVideo() * \brief Identify if the device captures or outputs images * \return True if the device can capture or output images */ /** - * \fn bool V4L2Capability::isMeta() + * \fn V4L2Capability::isMeta() * \brief Identify if the device captures or outputs image meta-data * * \todo Add support for META_CAPTURE introduced in Linux v5.0 @@ -95,25 +95,25 @@ LOG_DEFINE_CATEGORY(V4L2) */ /** - * \fn bool V4L2Capability::isVideoCapture() + * \fn V4L2Capability::isVideoCapture() * \brief Identify if the device captures images * \return True if the device can capture images */ /** - * \fn bool V4L2Capability::isVideoOutput() + * \fn V4L2Capability::isVideoOutput() * \brief Identify if the device outputs images * \return True if the device can output images */ /** - * \fn bool V4L2Capability::isMetaCapture() + * \fn V4L2Capability::isMetaCapture() * \brief Identify if the device captures image meta-data * \return True if the device can capture image meta-data */ /** - * \fn bool V4L2Capability::hasStreaming() + * \fn V4L2Capability::hasStreaming() * \brief Determine if the device can perform Streaming I/O * \return True if the device provides Streaming I/O IOCTLs */ @@ -371,19 +371,19 @@ void V4L2Device::close() } /** - * \fn const char *V4L2Device::driverName() + * \fn V4L2Device::driverName() * \brief Retrieve the name of the V4L2 device driver * \return The string containing the driver name */ /** - * \fn const char *V4L2Device::deviceName() + * \fn V4L2Device::deviceName() * \brief Retrieve the name of the V4L2 device * \return The string containing the device name */ /** - * \fn const char *V4L2Device::busName() + * \fn V4L2Device::busName() * \brief Retrieve the location of the device in the system * \return The string containing the device location */ @@ -394,11 +394,6 @@ void V4L2Device::close() * \return The video device device node path */ -std::string V4L2Device::logPrefix() const -{ - return deviceNode_; -} - /** * \brief Retrieve the image format set on the V4L2 device * \param[out] format The image format applied on the device @@ -426,155 +421,6 @@ int V4L2Device::setFormat(V4L2DeviceFormat *format) setFormatSingleplane(format); } -int V4L2Device::getFormatSingleplane(V4L2DeviceFormat *format) -{ - struct v4l2_format v4l2Format = {}; - struct v4l2_pix_format *pix = &v4l2Format.fmt.pix; - int ret; - - v4l2Format.type = bufferType_; - ret = ioctl(fd_, VIDIOC_G_FMT, &v4l2Format); - if (ret) { - ret = -errno; - LOG(V4L2, Error) << "Unable to get format: " << strerror(-ret); - return ret; - } - - format->width = pix->width; - format->height = pix->height; - format->fourcc = pix->pixelformat; - format->planesCount = 1; - format->planes[0].bpl = pix->bytesperline; - format->planes[0].size = pix->sizeimage; - - return 0; -} - -int V4L2Device::setFormatSingleplane(V4L2DeviceFormat *format) -{ - struct v4l2_format v4l2Format = {}; - struct v4l2_pix_format *pix = &v4l2Format.fmt.pix; - int ret; - - v4l2Format.type = bufferType_; - pix->width = format->width; - pix->height = format->height; - pix->pixelformat = format->fourcc; - pix->bytesperline = format->planes[0].bpl; - pix->field = V4L2_FIELD_NONE; - - ret = ioctl(fd_, VIDIOC_S_FMT, &v4l2Format); - if (ret) { - ret = -errno; - LOG(V4L2, Error) << "Unable to set format: " << strerror(-ret); - return ret; - } - - /* - * Return to caller the format actually applied on the device, - * which might differ from the requested one. - */ - format->width = pix->width; - format->height = pix->height; - format->fourcc = pix->pixelformat; - format->planesCount = 1; - format->planes[0].bpl = pix->bytesperline; - format->planes[0].size = pix->sizeimage; - - return 0; -} - -int V4L2Device::getFormatMultiplane(V4L2DeviceFormat *format) -{ - struct v4l2_format v4l2Format = {}; - struct v4l2_pix_format_mplane *pix = &v4l2Format.fmt.pix_mp; - int ret; - - v4l2Format.type = bufferType_; - ret = ioctl(fd_, VIDIOC_G_FMT, &v4l2Format); - if (ret) { - ret = -errno; - LOG(V4L2, Error) << "Unable to get format: " << strerror(-ret); - return ret; - } - - format->width = pix->width; - format->height = pix->height; - format->fourcc = pix->pixelformat; - format->planesCount = pix->num_planes; - - for (unsigned int i = 0; i < format->planesCount; ++i) { - format->planes[i].bpl = pix->plane_fmt[i].bytesperline; - format->planes[i].size = pix->plane_fmt[i].sizeimage; - } - - return 0; -} - -int V4L2Device::setFormatMultiplane(V4L2DeviceFormat *format) -{ - struct v4l2_format v4l2Format = {}; - struct v4l2_pix_format_mplane *pix = &v4l2Format.fmt.pix_mp; - int ret; - - v4l2Format.type = bufferType_; - pix->width = format->width; - pix->height = format->height; - pix->pixelformat = format->fourcc; - pix->num_planes = format->planesCount; - pix->field = V4L2_FIELD_NONE; - - for (unsigned int i = 0; i < pix->num_planes; ++i) { - pix->plane_fmt[i].bytesperline = format->planes[i].bpl; - pix->plane_fmt[i].sizeimage = format->planes[i].size; - } - - ret = ioctl(fd_, VIDIOC_S_FMT, &v4l2Format); - if (ret) { - ret = -errno; - LOG(V4L2, Error) << "Unable to set format: " << strerror(-ret); - return ret; - } - - /* - * Return to caller the format actually applied on the device, - * which might differ from the requested one. - */ - format->width = pix->width; - format->height = pix->height; - format->fourcc = pix->pixelformat; - format->planesCount = pix->num_planes; - for (unsigned int i = 0; i < format->planesCount; ++i) { - format->planes[i].bpl = pix->plane_fmt[i].bytesperline; - format->planes[i].size = pix->plane_fmt[i].sizeimage; - } - - return 0; -} - -int V4L2Device::requestBuffers(unsigned int count) -{ - struct v4l2_requestbuffers rb = {}; - int ret; - - rb.count = count; - rb.type = bufferType_; - rb.memory = memoryType_; - - ret = ioctl(fd_, VIDIOC_REQBUFS, &rb); - if (ret < 0) { - ret = -errno; - LOG(V4L2, Error) - << "Unable to request " << count << " buffers: " - << strerror(-ret); - return ret; - } - - LOG(V4L2, Debug) << rb.count << " buffers requested."; - - return rb.count; -} - /** * \brief Request buffers to be allocated from the device and stored in the * buffer pool provided. @@ -649,37 +495,6 @@ int V4L2Device::exportBuffers(BufferPool *pool) return 0; } -int V4L2Device::createPlane(Buffer *buffer, unsigned int planeIndex, - unsigned int length) -{ - struct v4l2_exportbuffer expbuf = {}; - int ret; - - LOG(V4L2, Debug) - << "Buffer " << buffer->index() - << " plane " << planeIndex - << ": length=" << length; - - expbuf.type = bufferType_; - expbuf.index = buffer->index(); - expbuf.plane = planeIndex; - expbuf.flags = O_RDWR; - - ret = ioctl(fd_, VIDIOC_EXPBUF, &expbuf); - if (ret < 0) { - ret = -errno; - LOG(V4L2, Error) - << "Failed to export buffer: " << strerror(-ret); - return ret; - } - - buffer->planes().emplace_back(); - Plane &plane = buffer->planes().back(); - plane.setDmabuf(expbuf.fd, length); - - return 0; -} - /** * \brief Import the externally allocated \a pool of buffers * \param[in] pool BufferPool of buffers to import @@ -790,6 +605,11 @@ int V4L2Device::queueBuffer(Buffer *buffer) return 0; } +/** + * \var V4L2Device::bufferReady + * \brief A Signal emitted when a buffer completes + */ + /** * \brief Dequeue the next available buffer from the device * @@ -860,11 +680,6 @@ void V4L2Device::bufferAvailable(EventNotifier *notifier) buffer->completed.emit(buffer); } -/** - * \var V4L2Device::bufferReady - * \brief A Signal emitted when a buffer completes - */ - /** * \brief Start the video stream * @@ -910,4 +725,189 @@ int V4L2Device::streamOff() return 0; } +std::string V4L2Device::logPrefix() const +{ + return deviceNode_; +} + +int V4L2Device::getFormatSingleplane(V4L2DeviceFormat *format) +{ + struct v4l2_format v4l2Format = {}; + struct v4l2_pix_format *pix = &v4l2Format.fmt.pix; + int ret; + + v4l2Format.type = bufferType_; + ret = ioctl(fd_, VIDIOC_G_FMT, &v4l2Format); + if (ret) { + ret = -errno; + LOG(V4L2, Error) << "Unable to get format: " << strerror(-ret); + return ret; + } + + format->width = pix->width; + format->height = pix->height; + format->fourcc = pix->pixelformat; + format->planesCount = 1; + format->planes[0].bpl = pix->bytesperline; + format->planes[0].size = pix->sizeimage; + + return 0; +} + +int V4L2Device::setFormatSingleplane(V4L2DeviceFormat *format) +{ + struct v4l2_format v4l2Format = {}; + struct v4l2_pix_format *pix = &v4l2Format.fmt.pix; + int ret; + + v4l2Format.type = bufferType_; + pix->width = format->width; + pix->height = format->height; + pix->pixelformat = format->fourcc; + pix->bytesperline = format->planes[0].bpl; + pix->field = V4L2_FIELD_NONE; + + ret = ioctl(fd_, VIDIOC_S_FMT, &v4l2Format); + if (ret) { + ret = -errno; + LOG(V4L2, Error) << "Unable to set format: " << strerror(-ret); + return ret; + } + + /* + * Return to caller the format actually applied on the device, + * which might differ from the requested one. + */ + format->width = pix->width; + format->height = pix->height; + format->fourcc = pix->pixelformat; + format->planesCount = 1; + format->planes[0].bpl = pix->bytesperline; + format->planes[0].size = pix->sizeimage; + + return 0; +} + +int V4L2Device::getFormatMultiplane(V4L2DeviceFormat *format) +{ + struct v4l2_format v4l2Format = {}; + struct v4l2_pix_format_mplane *pix = &v4l2Format.fmt.pix_mp; + int ret; + + v4l2Format.type = bufferType_; + ret = ioctl(fd_, VIDIOC_G_FMT, &v4l2Format); + if (ret) { + ret = -errno; + LOG(V4L2, Error) << "Unable to get format: " << strerror(-ret); + return ret; + } + + format->width = pix->width; + format->height = pix->height; + format->fourcc = pix->pixelformat; + format->planesCount = pix->num_planes; + + for (unsigned int i = 0; i < format->planesCount; ++i) { + format->planes[i].bpl = pix->plane_fmt[i].bytesperline; + format->planes[i].size = pix->plane_fmt[i].sizeimage; + } + + return 0; +} + +int V4L2Device::setFormatMultiplane(V4L2DeviceFormat *format) +{ + struct v4l2_format v4l2Format = {}; + struct v4l2_pix_format_mplane *pix = &v4l2Format.fmt.pix_mp; + int ret; + + v4l2Format.type = bufferType_; + pix->width = format->width; + pix->height = format->height; + pix->pixelformat = format->fourcc; + pix->num_planes = format->planesCount; + pix->field = V4L2_FIELD_NONE; + + for (unsigned int i = 0; i < pix->num_planes; ++i) { + pix->plane_fmt[i].bytesperline = format->planes[i].bpl; + pix->plane_fmt[i].sizeimage = format->planes[i].size; + } + + ret = ioctl(fd_, VIDIOC_S_FMT, &v4l2Format); + if (ret) { + ret = -errno; + LOG(V4L2, Error) << "Unable to set format: " << strerror(-ret); + return ret; + } + + /* + * Return to caller the format actually applied on the device, + * which might differ from the requested one. + */ + format->width = pix->width; + format->height = pix->height; + format->fourcc = pix->pixelformat; + format->planesCount = pix->num_planes; + for (unsigned int i = 0; i < format->planesCount; ++i) { + format->planes[i].bpl = pix->plane_fmt[i].bytesperline; + format->planes[i].size = pix->plane_fmt[i].sizeimage; + } + + return 0; +} + +int V4L2Device::requestBuffers(unsigned int count) +{ + struct v4l2_requestbuffers rb = {}; + int ret; + + rb.count = count; + rb.type = bufferType_; + rb.memory = memoryType_; + + ret = ioctl(fd_, VIDIOC_REQBUFS, &rb); + if (ret < 0) { + ret = -errno; + LOG(V4L2, Error) + << "Unable to request " << count << " buffers: " + << strerror(-ret); + return ret; + } + + LOG(V4L2, Debug) << rb.count << " buffers requested."; + + return rb.count; +} + +int V4L2Device::createPlane(Buffer *buffer, unsigned int planeIndex, + unsigned int length) +{ + struct v4l2_exportbuffer expbuf = {}; + int ret; + + LOG(V4L2, Debug) + << "Buffer " << buffer->index() + << " plane " << planeIndex + << ": length=" << length; + + expbuf.type = bufferType_; + expbuf.index = buffer->index(); + expbuf.plane = planeIndex; + expbuf.flags = O_RDWR; + + ret = ioctl(fd_, VIDIOC_EXPBUF, &expbuf); + if (ret < 0) { + ret = -errno; + LOG(V4L2, Error) + << "Failed to export buffer: " << strerror(-ret); + return ret; + } + + buffer->planes().emplace_back(); + Plane &plane = buffer->planes().back(); + plane.setDmabuf(expbuf.fd, length); + + return 0; +} + } /* namespace libcamera */