From patchwork Tue Feb 26 16:26:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 631 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F05D8610B3 for ; Tue, 26 Feb 2019 17:26:18 +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 relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 811E76000F; Tue, 26 Feb 2019 16:26:18 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Tue, 26 Feb 2019 17:26:34 +0100 Message-Id: <20190226162641.12116-2-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190226162641.12116-1-jacopo@jmondi.org> References: <20190226162641.12116-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 1/8] libcamera: v4l2_subdevice: Store media entity 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: Tue, 26 Feb 2019 16:26:19 -0000 Store the media entity backing the V4L2Subdevice and add a deviceName() method to retrieve the human readable name of the subdevice, which is created using the name of the associated media entity. Use the deviceName() in error messages where appropriate, as the entity name is sometimes more informative than the device node path. Signed-off-by: Jacopo Mondi Reviewed-by: Niklas Söderlund Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/libcamera/include/v4l2_subdevice.h | 8 +++++--- src/libcamera/v4l2_subdevice.cpp | 17 ++++++++++++----- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/libcamera/include/v4l2_subdevice.h b/src/libcamera/include/v4l2_subdevice.h index 82fa6685ab52..eac699a06109 100644 --- a/src/libcamera/include/v4l2_subdevice.h +++ b/src/libcamera/include/v4l2_subdevice.h @@ -9,9 +9,10 @@ #include +#include "media_object.h" + namespace libcamera { -class MediaEntity; struct Rectangle; struct V4L2SubdeviceFormat { @@ -31,7 +32,8 @@ public: bool isOpen() const; void close(); - std::string deviceNode() const { return deviceNode_; } + std::string deviceNode() const { return entity_->deviceNode(); } + std::string deviceName() const { return entity_->name(); } int setCrop(unsigned int pad, Rectangle *rect); int setCompose(unsigned int pad, Rectangle *rect); @@ -43,7 +45,7 @@ private: int setSelection(unsigned int pad, unsigned int target, Rectangle *rect); - std::string deviceNode_; + const MediaEntity *entity_; int fd_; }; diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp index b436f73cc75f..56ecf3851cb0 100644 --- a/src/libcamera/v4l2_subdevice.cpp +++ b/src/libcamera/v4l2_subdevice.cpp @@ -88,7 +88,7 @@ LOG_DEFINE_CATEGORY(V4L2Subdev) * path */ V4L2Subdevice::V4L2Subdevice(const MediaEntity *entity) - : deviceNode_(entity->deviceNode()), fd_(-1) + : entity_(entity), fd_(-1) { } @@ -106,11 +106,11 @@ int V4L2Subdevice::open() return -EBUSY; } - ret = ::open(deviceNode_.c_str(), O_RDWR); + ret = ::open(deviceNode().c_str(), O_RDWR); if (ret < 0) { ret = -errno; LOG(V4L2Subdev, Error) - << "Failed to open V4L2 subdevice '" << deviceNode_ + << "Failed to open V4L2 subdevice '" << deviceNode() << "': " << strerror(-ret); return ret; } @@ -147,6 +147,13 @@ void V4L2Subdevice::close() * \return The subdevice's device node system path */ +/** + * \fn V4L2Subdevice::deviceName() + * \brief Retrieve the name of the media entity associated with the subdevice + * + * \return The name of the media entity the subdevice is associated to + */ + /** * \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 @@ -189,7 +196,7 @@ int V4L2Subdevice::getFormat(unsigned int pad, V4L2SubdeviceFormat *format) ret = -errno; LOG(V4L2Subdev, Error) << "Unable to get format on pad " << pad - << " of " << deviceNode_ << ": " << strerror(-ret); + << " of " << deviceName() << ": " << strerror(-ret); return ret; } @@ -255,7 +262,7 @@ int V4L2Subdevice::setSelection(unsigned int pad, unsigned int target, ret = -errno; LOG(V4L2Subdev, Error) << "Unable to set rectangle " << target << " on pad " - << pad << " of " << deviceNode_ << ": " + << pad << " of " << deviceName() << ": " << strerror(-ret); return ret; } From patchwork Tue Feb 26 16:26: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: 632 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 86E4C610B3 for ; Tue, 26 Feb 2019 17:26:19 +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 relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 1CB1960008; Tue, 26 Feb 2019 16:26:18 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Tue, 26 Feb 2019 17:26:35 +0100 Message-Id: <20190226162641.12116-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190226162641.12116-1-jacopo@jmondi.org> References: <20190226162641.12116-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 2/8] 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: Tue, 26 Feb 2019 16:26:19 -0000 Implement enumFormat() methods to enumerate the available image resolutions on the subdevice. Signed-off-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- src/libcamera/include/v4l2_subdevice.h | 9 ++ src/libcamera/v4l2_subdevice.cpp | 118 +++++++++++++++++++++++++ 2 files changed, 127 insertions(+) diff --git a/src/libcamera/include/v4l2_subdevice.h b/src/libcamera/include/v4l2_subdevice.h index eac699a06109..6b21308d2087 100644 --- a/src/libcamera/include/v4l2_subdevice.h +++ b/src/libcamera/include/v4l2_subdevice.h @@ -7,7 +7,9 @@ #ifndef __LIBCAMERA_V4L2_SUBDEVICE_H__ #define __LIBCAMERA_V4L2_SUBDEVICE_H__ +#include #include +#include #include "media_object.h" @@ -38,15 +40,22 @@ public: int setCrop(unsigned int pad, Rectangle *rect); int setCompose(unsigned int pad, Rectangle *rect); + std::vector &formats(unsigned int pad); int getFormat(unsigned int pad, V4L2SubdeviceFormat *format); int setFormat(unsigned int pad, V4L2SubdeviceFormat *format); private: + int listPadSizes(unsigned int pad, unsigned int mbus_code, + std::vector *formats); + std::vector listPadFormats(unsigned int pad); + int setSelection(unsigned int pad, unsigned int target, Rectangle *rect); const MediaEntity *entity_; int fd_; + + std::map> formats_; }; } /* namespace libcamera */ diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp index 56ecf3851cb0..f81a521f9e2a 100644 --- a/src/libcamera/v4l2_subdevice.cpp +++ b/src/libcamera/v4l2_subdevice.cpp @@ -5,6 +5,10 @@ * v4l2_subdevice.cpp - V4L2 Subdevice */ +#include +#include +#include + #include #include #include @@ -116,6 +120,9 @@ int V4L2Subdevice::open() } fd_ = ret; + for (MediaPad *pad : entity_->pads()) + formats_[pad->index()] = listPadFormats(pad->index()); + return 0; } @@ -178,6 +185,25 @@ 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 + * + * \return A vector of image formats, or an empty vector if the pad does not + * exist + */ +std::vector &V4L2Subdevice::formats(unsigned int pad) +{ + /* + * If pad does not exist, return an empty vector at position + * pads().size() + */ + if (pad > entity_->pads().size()) + pad = entity_->pads().size(); + + return formats_[pad]; +} + /** * \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 @@ -242,6 +268,98 @@ int V4L2Subdevice::setFormat(unsigned int pad, V4L2SubdeviceFormat *format) return 0; } +int V4L2Subdevice::listPadSizes(unsigned int pad, unsigned int mbus_code, + std::vector *formats) +{ + struct v4l2_subdev_frame_size_enum sizeEnum = {}; + int ret; + + sizeEnum.index = 0; + sizeEnum.pad = pad; + sizeEnum.code = mbus_code; + sizeEnum.which = V4L2_SUBDEV_FORMAT_ACTIVE; + + while (!(ret = ioctl(fd_, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, &sizeEnum))) { + V4L2SubdeviceFormat minFormat = { + .mbus_code = mbus_code, + .width = sizeEnum.min_width, + .height = sizeEnum.min_height, + }; + formats->push_back(minFormat); + + /* + * Most subdevices report discrete frame resolutions, where + * min and max sizes are identical. For continue frame + * resolutions, store the min and max sizes interval. + */ + if (sizeEnum.min_width == sizeEnum.max_width && + sizeEnum.min_height == sizeEnum.max_height) { + sizeEnum.index++; + continue; + } + + V4L2SubdeviceFormat maxFormat = { + .mbus_code = mbus_code, + .width = sizeEnum.max_width, + .height = sizeEnum.max_height, + }; + formats->push_back(maxFormat); + + sizeEnum.index++; + } + + if (ret && (errno != EINVAL && errno != ENOTTY)) { + LOG(V4L2Subdev, Error) + << "Unable to enumerate format on pad " << pad + << " of " << deviceName() << ": " + << strerror(errno); + return ret; + } + + return 0; +} + +std::vector V4L2Subdevice::listPadFormats(unsigned int pad) +{ + struct v4l2_subdev_mbus_code_enum mbusEnum = {}; + std::vector formats = {}; + int ret; + + mbusEnum.pad = pad; + mbusEnum.index = 0; + mbusEnum.which = V4L2_SUBDEV_FORMAT_ACTIVE; + + while (!(ret = ioctl(fd_, VIDIOC_SUBDEV_ENUM_MBUS_CODE, &mbusEnum))) { + ret = listPadSizes(pad, mbusEnum.code, &formats); + if (ret) + return formats; + + mbusEnum.index++; + } + + if (ret && (errno != EINVAL && errno != ENOTTY)) { + LOG(V4L2Subdev, Error) + << "Unable to enumerate format on pad " << pad + << " of " << deviceName() << ": " << strerror(-ret); + return formats; + } + + if (mbusEnum.index == 0 && ret && errno == EINVAL) { + /* + * The subdevice might not support ENUM_MBUS_CODE but + * might support ENUM_FRAME_SIZES. + */ + struct V4L2SubdeviceFormat subdevFormat; + ret = getFormat(pad, &subdevFormat); + if (ret) + return formats; + + listPadSizes(pad, subdevFormat.mbus_code, &formats); + } + + return formats; +} + int V4L2Subdevice::setSelection(unsigned int pad, unsigned int target, Rectangle *rect) { From patchwork Tue Feb 26 16:26: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: 633 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 18E56610B7 for ; Tue, 26 Feb 2019 17:26:20 +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 relay3-d.mail.gandi.net (Postfix) with ESMTPSA id A7E626000D; Tue, 26 Feb 2019 16:26:19 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Tue, 26 Feb 2019 17:26:36 +0100 Message-Id: <20190226162641.12116-4-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190226162641.12116-1-jacopo@jmondi.org> References: <20190226162641.12116-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 3/8] 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: Tue, 26 Feb 2019 16:26:20 -0000 Add support for devices that provide video meta-data to v4l2_device.cpp and re-arrange bufferType handling in open() method. Signed-off-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- src/libcamera/include/v4l2_device.h | 4 +++ src/libcamera/v4l2_device.cpp | 38 +++++++++++++++++------------ 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index 1d31d1b403bc..52eb6785cc15 100644 --- a/src/libcamera/include/v4l2_device.h +++ b/src/libcamera/include/v4l2_device.h @@ -53,6 +53,10 @@ struct V4L2Capability final : v4l2_capability { return device_caps() & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE); } + bool isMeta() const + { + return device_caps() & V4L2_CAP_META_CAPTURE; + } bool isOutput() const { return device_caps() & (V4L2_CAP_VIDEO_OUTPUT | diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 24e115554a99..8be8af7a2893 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -79,6 +79,15 @@ LOG_DEFINE_CATEGORY(V4L2) * \return True if the device can output video frames */ +/** + * \fn bool V4L2Capability::isMeta() + * \brief Identify if the device is capable of providing video meta-data + * + * FIXME: add support for META_OUTPUT, introduced in Linux v4.20 + * + * \return True if the device can provide video meta-data + */ + /** * \fn bool V4L2Capability::hasStreaming() * \brief Determine if the device can perform Streaming I/O @@ -280,33 +289,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_.isCapture()) { + fdEvent_ = new EventNotifier(fd_, EventNotifier::Read); bufferType_ = caps_.isMultiplanar() ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE; - else + } else if (caps_.isOutput()) { + 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_.isMeta()) { 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 Tue Feb 26 16:26: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: 634 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id ABC9D610B7 for ; Tue, 26 Feb 2019 17:26:20 +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 relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 3E6F26000D; Tue, 26 Feb 2019 16:26:20 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Tue, 26 Feb 2019 17:26:37 +0100 Message-Id: <20190226162641.12116-5-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190226162641.12116-1-jacopo@jmondi.org> References: <20190226162641.12116-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 4/8] libcamera: v4l2_subdevice: Update crop/compose rectangle 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: Tue, 26 Feb 2019 16:26:21 -0000 Update the crop/compose rectangle provided to setCrop()/setCompose() methods with the rectangle sizes set by the device driver after a S_SELECTION ioctl operation. Signed-off-by: Jacopo Mondi --- src/libcamera/v4l2_subdevice.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp index f81a521f9e2a..a043a07ff156 100644 --- a/src/libcamera/v4l2_subdevice.cpp +++ b/src/libcamera/v4l2_subdevice.cpp @@ -385,6 +385,11 @@ int V4L2Subdevice::setSelection(unsigned int pad, unsigned int target, return ret; } + rect->y = sel.r.left; + rect->x = sel.r.top; + rect->w = sel.r.width; + rect->h = sel.r.height; + return 0; } From patchwork Tue Feb 26 16:26: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: 635 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4FD84610B7 for ; Tue, 26 Feb 2019 17:26:21 +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 relay3-d.mail.gandi.net (Postfix) with ESMTPSA id D1DCC60008; Tue, 26 Feb 2019 16:26:20 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Tue, 26 Feb 2019 17:26:38 +0100 Message-Id: <20190226162641.12116-6-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190226162641.12116-1-jacopo@jmondi.org> References: <20190226162641.12116-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 5/8] test: v4l2_subdevice: Add format handling 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: Tue, 26 Feb 2019 16:26:21 -0000 Add test for video format get and set operations on V4L2Subdevice class. Signed-off-by: Jacopo Mondi Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- test/meson.build | 1 + test/v4l2_subdevice/meson.build | 10 +++ test/v4l2_subdevice/test_formats.cpp | 79 ++++++++++++++++++ test/v4l2_subdevice/v4l2_subdevice_test.cpp | 90 +++++++++++++++++++++ test/v4l2_subdevice/v4l2_subdevice_test.h | 36 +++++++++ 5 files changed, 216 insertions(+) create mode 100644 test/v4l2_subdevice/meson.build create mode 100644 test/v4l2_subdevice/test_formats.cpp create mode 100644 test/v4l2_subdevice/v4l2_subdevice_test.cpp create mode 100644 test/v4l2_subdevice/v4l2_subdevice_test.h diff --git a/test/meson.build b/test/meson.build index d515a716207e..5fb16fa6afb6 100644 --- a/test/meson.build +++ b/test/meson.build @@ -3,6 +3,7 @@ subdir('libtest') subdir('media_device') subdir('pipeline') subdir('v4l2_device') +subdir('v4l2_subdevice') public_tests = [ ['event', 'event.cpp'], diff --git a/test/v4l2_subdevice/meson.build b/test/v4l2_subdevice/meson.build new file mode 100644 index 000000000000..a4359fe1bc19 --- /dev/null +++ b/test/v4l2_subdevice/meson.build @@ -0,0 +1,10 @@ +v4l2_subdevice_tests = [ + [ 'test_formats', 'test_formats.cpp'], +] + +foreach t : v4l2_subdevice_tests + exe = executable(t[0], [t[1], 'v4l2_subdevice_test.cpp'], + link_with : test_libraries, + include_directories : test_includes_internal) + test(t[0], exe, suite: 'v4l2_subdevice', is_parallel: false) +endforeach diff --git a/test/v4l2_subdevice/test_formats.cpp b/test/v4l2_subdevice/test_formats.cpp new file mode 100644 index 000000000000..91b460f64e7e --- /dev/null +++ b/test/v4l2_subdevice/test_formats.cpp @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * libcamera V4L2 Subdevice format handling test + */ + +#include +#include + +#include "v4l2_subdevice.h" + +#include "v4l2_subdevice_test.h" + +using namespace std; +using namespace libcamera; + +/* Test format handling on the "Scaler" subdevice of vimc media device. */ + +class FormatHandlingTest : public V4L2SubdeviceTest +{ +protected: + int run(); +}; + +int FormatHandlingTest::run() +{ + V4L2SubdeviceFormat format = {}; + + /* + * Get format on a non-existing Scaler pad: expect failure. + */ + int ret = scaler_->getFormat(2, &format); + if (!ret) { + cerr << "Get format on a non existing pad should fail" << endl; + return TestFail; + } + + ret = scaler_->getFormat(0, &format); + if (ret) { + cerr << "Failed to get format" << endl; + return TestFail; + } + + /* + * Set unrealistic image resolutions and make sure it gets updated. + */ + format.width = UINT_MAX; + format.height = UINT_MAX; + ret = scaler_->setFormat(0, &format); + if (ret) { + cerr << "Failed to set format: image resolution is wrong, but " + << "setFormat() should not fail." << endl; + return TestFail; + } + + if (format.width == UINT_MAX || format.height == UINT_MAX) { + cerr << "Failed to update image format" << endl; + return TestFail; + } + + format.width = 0; + format.height = 0; + ret = scaler_->setFormat(0, &format); + if (ret) { + cerr << "Failed to set format: image resolution is wrong, but " + << "setFormat() should not fail." << endl; + return TestFail; + } + + if (format.width == 0 || format.height == 0) { + cerr << "Failed to update image format" << endl; + return TestFail; + } + + return TestPass; +} + +TEST_REGISTER(FormatHandlingTest); diff --git a/test/v4l2_subdevice/v4l2_subdevice_test.cpp b/test/v4l2_subdevice/v4l2_subdevice_test.cpp new file mode 100644 index 000000000000..10fe2655e5e4 --- /dev/null +++ b/test/v4l2_subdevice/v4l2_subdevice_test.cpp @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * v4l2_subdevice_test.cpp - V4L2 subdevice test + */ + +#include +#include +#include + +#include "device_enumerator.h" +#include "media_device.h" +#include "v4l2_subdevice.h" + +#include "v4l2_subdevice_test.h" + +using namespace std; +using namespace libcamera; + +/* + * This test runs on vimc media device. For a description of vimc, in the + * context of libcamera testingrefer to + * 'test/media_device/media_device_link_test.cpp' file. + * + * If the vimc module is not loaded, the test gets skipped. + */ + +int V4L2SubdeviceTest::init() +{ + enumerator_ = DeviceEnumerator::create(); + if (!enumerator_) { + cerr << "Failed to create device enumerator" << endl; + return TestFail; + } + + if (enumerator_->enumerate()) { + cerr << "Failed to enumerate media devices" << endl; + return TestFail; + } + + DeviceMatch dm("vimc"); + media_ = std::move(enumerator_->search(dm)); + if (!media_) { + cerr << "Unable to find \'vimc\' media device node" << endl; + return TestSkip; + } + + media_->acquire(); + + int ret = media_->open(); + if (ret) { + cerr << "Unable to open media device: " << media_->deviceNode() + << ": " << strerror(ret) << endl; + media_->release(); + return TestSkip; + } + + MediaEntity *videoEntity = media_->getEntityByName("Scaler"); + if (!videoEntity) { + cerr << "Unable to find media entity 'Scaler'" << endl; + media_->release(); + return TestSkip; + } + + scaler_ = new V4L2Subdevice(videoEntity); + if (!scaler_) { + cerr << "Unable to create media device from media entity: " + << videoEntity->deviceNode(); + media_->release(); + return TestSkip; + } + + ret = scaler_->open(); + if (ret) { + cerr << "Unable to open video subdevice " + << scaler_->deviceNode() << endl; + media_->release(); + return TestSkip; + } + + return 0; +} + +void V4L2SubdeviceTest::cleanup() +{ + media_->release(); + + delete scaler_; +} diff --git a/test/v4l2_subdevice/v4l2_subdevice_test.h b/test/v4l2_subdevice/v4l2_subdevice_test.h new file mode 100644 index 000000000000..7b64c6122745 --- /dev/null +++ b/test/v4l2_subdevice/v4l2_subdevice_test.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * v4l2_subdevice_test.h - V4L2 subdevice test + */ + +#ifndef __LIBCAMERA_V4L2_SUBDEVICE_TEST_H_ +#define __LIBCAMERA_V4L2_SUBDEVICE_TEST_H_ + +#include + +#include "device_enumerator.h" +#include "media_device.h" +#include "test.h" +#include "v4l2_subdevice.h" + +using namespace libcamera; + +class V4L2SubdeviceTest : public Test +{ +public: + V4L2SubdeviceTest() + : scaler_(nullptr){}; + +protected: + int init(); + virtual int run() = 0; + void cleanup(); + + std::unique_ptr enumerator_; + std::shared_ptr media_; + V4L2Subdevice *scaler_; +}; + +#endif /* __LIBCAMERA_V4L2_SUBDEVICE_TEST_H_ */ From patchwork Tue Feb 26 16:26: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: 636 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F135A610B7 for ; Tue, 26 Feb 2019 17:26:21 +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 relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 812F560008; Tue, 26 Feb 2019 16:26:21 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Tue, 26 Feb 2019 17:26:39 +0100 Message-Id: <20190226162641.12116-7-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190226162641.12116-1-jacopo@jmondi.org> References: <20190226162641.12116-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 6/8] 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: Tue, 26 Feb 2019 16:26:22 -0000 Add test to list formats on a v4l2 subdevice. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- test/v4l2_subdevice/list_formats.cpp | 76 ++++++++++++++++++++++++++++ test/v4l2_subdevice/meson.build | 1 + 2 files changed, 77 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..3c4737a17afc --- /dev/null +++ b/test/v4l2_subdevice/list_formats.cpp @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * libcamera V4L2 Subdevice format handling test + */ + +#include +#include + +#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(); + +private: + void printFormats(unsigned int pad, + std::vector &formats); +}; + +void ListFormatsTest::printFormats(unsigned int pad, + std::vector &formats) +{ + cout << "Enumerate formats on pad " << pad << endl; + for (V4L2SubdeviceFormat &format : formats) { + cout << " Mbus code: 0x" << hex << format.mbus_code << endl; + cout << " Width: " << dec << format.width << endl; + cout << " Height: " << dec << format.height << endl; + } +} + +int ListFormatsTest::run() +{ + /* List all formats available on existing "Scaler" pads. */ + std::vector formats = {}; + + formats = scaler_->formats(0); + if (formats.empty()) { + cerr << "Failed to list formats on pad 0 of sudevice " + << scaler_->deviceNode() << endl; + return TestFail; + } + printFormats(0, formats); + + formats = {}; + formats = scaler_->formats(1); + if (formats.empty()) { + cerr << "Failed to list formats on pad 1 of sudevice " + << scaler_->deviceNode() << endl; + return TestFail; + } + printFormats(1, formats); + + /* List format on a non-existing pad, format vector shall be empty. */ + formats = {}; + formats = scaler_->formats(2); + if (!formats.empty()) { + cerr << "Listing formats on non-existing pad 2 of subdevice " + << scaler_->deviceNode() + << " 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 a4359fe1bc19..6023d15e1558 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 Tue Feb 26 16:26:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 637 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8E382610B7 for ; Tue, 26 Feb 2019 17:26:22 +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 relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 2432F60004; Tue, 26 Feb 2019 16:26:21 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Tue, 26 Feb 2019 17:26:40 +0100 Message-Id: <20190226162641.12116-8-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190226162641.12116-1-jacopo@jmondi.org> References: <20190226162641.12116-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 7/8] test: v4l2_device: Add format handling 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: Tue, 26 Feb 2019 16:26:22 -0000 Add test for V4L2Device set and get format methods. Signed-off-by: Jacopo Mondi Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- test/v4l2_device/meson.build | 1 + test/v4l2_device/test_formats.cpp | 65 +++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 test/v4l2_device/test_formats.cpp diff --git a/test/v4l2_device/meson.build b/test/v4l2_device/meson.build index 9f7a7545ac9b..e5e50faac282 100644 --- a/test/v4l2_device/meson.build +++ b/test/v4l2_device/meson.build @@ -6,6 +6,7 @@ v4l2_device_tests = [ [ 'stream_on_off', 'stream_on_off.cpp' ], [ 'capture_async', 'capture_async.cpp' ], [ 'buffer_sharing', 'buffer_sharing.cpp' ], + [ 'test_formats', 'test_formats.cpp' ], ] foreach t : v4l2_device_tests diff --git a/test/v4l2_device/test_formats.cpp b/test/v4l2_device/test_formats.cpp new file mode 100644 index 000000000000..dcb05a3904f7 --- /dev/null +++ b/test/v4l2_device/test_formats.cpp @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * libcamera V4L2 device format handling test + */ + +#include +#include + +#include "v4l2_device.h" + +#include "v4l2_device_test.h" + +using namespace std; +using namespace libcamera; + +class Format : public V4L2DeviceTest +{ +protected: + int run(); +}; + +int Format::run() +{ + V4L2DeviceFormat format = {}; + + int ret = capture_->getFormat(&format); + if (ret) { + cerr << "Failed to get format" << endl; + return TestFail; + } + + format.width = UINT_MAX; + format.height = UINT_MAX; + ret = capture_->setFormat(&format); + if (ret) { + cerr << "Failed to set format: image resolution is wrong, but " + << "setFormat() should not fail." << endl; + return TestFail; + } + + if (format.width == UINT_MAX || format.height == UINT_MAX) { + cerr << "Failed to update image format" << endl; + return TestFail; + } + + format.width = 0; + format.height = 0; + ret = capture_->setFormat(&format); + if (ret) { + cerr << "Failed to set format: image resolution is wrong, but " + << "setFormat() should not fail." << endl; + return TestFail; + } + + if (format.width == 0 || format.height == 0) { + cerr << "Failed to update image format" << endl; + return TestFail; + } + + return TestPass; +} + +TEST_REGISTER(Format); From patchwork Tue Feb 26 16:26:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 638 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2A09D610CD for ; Tue, 26 Feb 2019 17:26:23 +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 relay3-d.mail.gandi.net (Postfix) with ESMTPSA id AEDDD60002; Tue, 26 Feb 2019 16:26:22 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Tue, 26 Feb 2019 17:26:41 +0100 Message-Id: <20190226162641.12116-9-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190226162641.12116-1-jacopo@jmondi.org> References: <20190226162641.12116-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 8/8] libcamera: v4l2_subdevice: Inherit from Loggable 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: Tue, 26 Feb 2019 16:26:23 -0000 Prefix the V4L2Subdevice error messages with the name of the entity. Remove the manually printed name from log messages where it was used. Signed-off-by: Jacopo Mondi Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/libcamera/include/v4l2_subdevice.h | 7 ++++++- src/libcamera/v4l2_subdevice.cpp | 10 ++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/libcamera/include/v4l2_subdevice.h b/src/libcamera/include/v4l2_subdevice.h index 6b21308d2087..dcf38d719fcb 100644 --- a/src/libcamera/include/v4l2_subdevice.h +++ b/src/libcamera/include/v4l2_subdevice.h @@ -13,6 +13,8 @@ #include "media_object.h" +#include "log.h" + namespace libcamera { struct Rectangle; @@ -23,7 +25,7 @@ struct V4L2SubdeviceFormat { uint32_t height; }; -class V4L2Subdevice +class V4L2Subdevice : protected Loggable { public: explicit V4L2Subdevice(const MediaEntity *entity); @@ -44,6 +46,9 @@ public: int getFormat(unsigned int pad, V4L2SubdeviceFormat *format); int setFormat(unsigned int pad, V4L2SubdeviceFormat *format); +protected: + std::string logPrefix() const { return "'" + deviceName() + "'"; } + private: int listPadSizes(unsigned int pad, unsigned int mbus_code, std::vector *formats); diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp index a043a07ff156..20439b895b99 100644 --- a/src/libcamera/v4l2_subdevice.cpp +++ b/src/libcamera/v4l2_subdevice.cpp @@ -222,7 +222,7 @@ int V4L2Subdevice::getFormat(unsigned int pad, V4L2SubdeviceFormat *format) ret = -errno; LOG(V4L2Subdev, Error) << "Unable to get format on pad " << pad - << " of " << deviceName() << ": " << strerror(-ret); + << ": " << strerror(-ret); return ret; } @@ -311,8 +311,7 @@ int V4L2Subdevice::listPadSizes(unsigned int pad, unsigned int mbus_code, if (ret && (errno != EINVAL && errno != ENOTTY)) { LOG(V4L2Subdev, Error) << "Unable to enumerate format on pad " << pad - << " of " << deviceName() << ": " - << strerror(errno); + << ": " << strerror(errno); return ret; } @@ -340,7 +339,7 @@ std::vector V4L2Subdevice::listPadFormats(unsigned int pad) if (ret && (errno != EINVAL && errno != ENOTTY)) { LOG(V4L2Subdev, Error) << "Unable to enumerate format on pad " << pad - << " of " << deviceName() << ": " << strerror(-ret); + << ": " << strerror(-ret); return formats; } @@ -380,8 +379,7 @@ int V4L2Subdevice::setSelection(unsigned int pad, unsigned int target, ret = -errno; LOG(V4L2Subdev, Error) << "Unable to set rectangle " << target << " on pad " - << pad << " of " << deviceName() << ": " - << strerror(-ret); + << ": " << strerror(-ret); return ret; }