From patchwork Mon Feb 25 12:10:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 616 Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5E978610B3 for ; Mon, 25 Feb 2019 13:10:19 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id DD105100008; Mon, 25 Feb 2019 12:10:18 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 25 Feb 2019 13:10:33 +0100 Message-Id: <20190225121037.11415-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190225121037.11415-1-jacopo@jmondi.org> References: <20190225121037.11415-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 2/6] 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: Mon, 25 Feb 2019 12:10:19 -0000 Implement enumFormat() methods to enumerate the available image resolutions on the subdevice. Signed-off-by: Jacopo Mondi --- src/libcamera/include/v4l2_subdevice.h | 8 +++ src/libcamera/v4l2_subdevice.cpp | 93 ++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/src/libcamera/include/v4l2_subdevice.h b/src/libcamera/include/v4l2_subdevice.h index fcfbee5af106..cb033a76933c 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,16 +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 listPadFormats(unsigned int pad, + std::vector *formats); + void listFormats(); int setSelection(unsigned int pad, unsigned int target, Rectangle *rect); const MediaEntity *entity_; std::string deviceNode_; int fd_; + + std::map> formats_; }; } /* namespace libcamera */ diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp index ebf87f0124cb..0e9c654579dc 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,8 @@ int V4L2Subdevice::open() } fd_ = ret; + listFormats(); + return 0; } @@ -178,6 +184,17 @@ 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 on error + */ +std::vector &V4L2Subdevice::formats(unsigned int pad) +{ + 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 +259,82 @@ int V4L2Subdevice::setFormat(unsigned int pad, V4L2SubdeviceFormat *format) return 0; } +int V4L2Subdevice::listPadFormats(unsigned int pad, + std::vector *formats) +{ + struct v4l2_subdev_frame_size_enum sizeEnum = {}; + struct v4l2_subdev_mbus_code_enum mbusEnum = {}; + int ret; + + mbusEnum.index = 0; + mbusEnum.pad = pad; + mbusEnum.which = V4L2_SUBDEV_FORMAT_ACTIVE; + + while (!(ret = ioctl(fd_, VIDIOC_SUBDEV_ENUM_MBUS_CODE, &mbusEnum))) { + sizeEnum.index = 0; + sizeEnum.code = mbusEnum.code; + sizeEnum.pad = pad; + sizeEnum.which = V4L2_SUBDEV_FORMAT_ACTIVE; + + while (!(ret = ioctl(fd_, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, + &sizeEnum))) { + + /* Store the minimum and maximum reported sizes. */ + V4L2SubdeviceFormat minFormat = { + .mbus_code = mbusEnum.code, + .width = sizeEnum.min_width, + .height = sizeEnum.min_height, + }; + formats->push_back(minFormat); + + V4L2SubdeviceFormat maxFormat = { + .mbus_code = mbusEnum.code, + .width = sizeEnum.max_width, + .height = sizeEnum.max_height, + }; + formats->push_back(maxFormat); + + sizeEnum.index++; + } + + if (-errno != -EINVAL) { + LOG(V4L2Subdev, Error) + << "Unable to enumerate format on pad " << pad + << " of " << deviceNode_ << ": " + << strerror(-ret); + return ret; + } + + mbusEnum.index++; + } + + if (-errno != -EINVAL) { + LOG(V4L2Subdev, Error) + << "Unable to enumerate format on pad " << pad + << " of " << deviceNode_ << ": " << strerror(-ret); + return ret; + } + + return 0; +} + +void V4L2Subdevice::listFormats() +{ + int ret; + + for (MediaPad *pad : entity_->pads()) { + std::vector formats = {}; + ret = listPadFormats(pad->index(), &formats); + if (ret) { + formats = {}; + formats_[pad->index()] = formats; + continue; + } + + formats_[pad->index()] = formats; + } +} + int V4L2Subdevice::setSelection(unsigned int pad, unsigned int target, Rectangle *rect) {