From patchwork Wed Jun 3 14:16:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 3905 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C9C19610CD for ; Wed, 3 Jun 2020 16:16:23 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="LWhT9JBN"; dkim-atps=neutral Received: from emerald.amanokami.net (fs76eef344.knge213.ap.nuro.jp [118.238.243.68]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 96ED327C; Wed, 3 Jun 2020 16:16:22 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1591193783; bh=AIr7wRNotOTy7U1Ar79JAo4BPF97/S2I+/BM2hurd6c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LWhT9JBNdM7z3OFCOCCoiJT5tIT+WhzkPwaDQMOh1tN7WZl/mEFd6DqFCrJsbiTP6 oj/W+xvPqr5J5Ro/M6koh0/7n3xagvOWLFeRkcxHkYxOXjopWpGoVPha5silPTPfxi C0r0laQdcMe3AoMf9vTPrrRHpjkf5jHGtmICsK48= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 3 Jun 2020 23:16:05 +0900 Message-Id: <20200603141609.18584-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200603141609.18584-1-paul.elder@ideasonboard.com> References: <20200603141609.18584-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/5] IPAManager: make IPAManager lifetime explicitly managed X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 03 Jun 2020 14:16:24 -0000 If any ipa_context instances are destroyed before the IPAManager is destroyed, then a segfault will occur when the IPAManager is deconstructed, as it tries to destroy all of the IPAs that it manages. Fix this by making the lifetime of the IPAManager explicit, and make the CameraManager construct and deconstruct (automatically, via a unique pointer) the IPAManager. Also update the IPA interface test to do the construction and deconstruction of the IPAManager, as it does not use the CameraManager. Signed-off-by: Paul Elder --- include/libcamera/camera_manager.h | 4 ++++ include/libcamera/internal/ipa_manager.h | 7 ++++--- src/libcamera/camera_manager.cpp | 4 +++- src/libcamera/ipa_manager.cpp | 13 +++++++++++-- test/ipa/ipa_interface_test.cpp | 5 +++++ 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/include/libcamera/camera_manager.h b/include/libcamera/camera_manager.h index 079f848a..8f9398fa 100644 --- a/include/libcamera/camera_manager.h +++ b/include/libcamera/camera_manager.h @@ -14,6 +14,8 @@ #include +#include "libcamera/internal/ipa_manager.h" + namespace libcamera { class Camera; @@ -48,6 +50,8 @@ private: class Private; std::unique_ptr p_; + + std::unique_ptr ipaManager_; }; } /* namespace libcamera */ diff --git a/include/libcamera/internal/ipa_manager.h b/include/libcamera/internal/ipa_manager.h index 2412d757..65303d6d 100644 --- a/include/libcamera/internal/ipa_manager.h +++ b/include/libcamera/internal/ipa_manager.h @@ -22,6 +22,9 @@ namespace libcamera { class IPAManager { public: + IPAManager(); + ~IPAManager(); + static IPAManager *instance(); std::unique_ptr createIPA(PipelineHandler *pipe, @@ -30,9 +33,7 @@ public: private: std::vector modules_; - - IPAManager(); - ~IPAManager(); + static IPAManager *self_; void parseDir(const char *libDir, unsigned int maxDepth, std::vector &files); diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp index 849377ad..d19348df 100644 --- a/src/libcamera/camera_manager.cpp +++ b/src/libcamera/camera_manager.cpp @@ -15,6 +15,7 @@ #include "libcamera/internal/device_enumerator.h" #include "libcamera/internal/event_dispatcher_poll.h" +#include "libcamera/internal/ipa_manager.h" #include "libcamera/internal/log.h" #include "libcamera/internal/pipeline_handler.h" #include "libcamera/internal/thread.h" @@ -246,7 +247,8 @@ void CameraManager::Private::removeCamera(Camera *camera) CameraManager *CameraManager::self_ = nullptr; CameraManager::CameraManager() - : p_(new CameraManager::Private(this)) + : p_(new CameraManager::Private(this)), ipaManager_(new IPAManager()) + { if (self_) LOG(Camera, Fatal) diff --git a/src/libcamera/ipa_manager.cpp b/src/libcamera/ipa_manager.cpp index 505cf610..74112cde 100644 --- a/src/libcamera/ipa_manager.cpp +++ b/src/libcamera/ipa_manager.cpp @@ -93,8 +93,14 @@ LOG_DEFINE_CATEGORY(IPAManager) * plain C API, or to transmit the data to the isolated process through IPC. */ +IPAManager *IPAManager::self_ = nullptr; + IPAManager::IPAManager() { + if (self_) + LOG(IPAManager, Fatal) + << "Multiple IPAManager objects are not allowed"; + unsigned int ipaCount = 0; /* User-specified paths take precedence. */ @@ -134,12 +140,16 @@ IPAManager::IPAManager() if (!ipaCount) LOG(IPAManager, Warning) << "No IPA found in '" IPA_MODULE_DIR "'"; + + self_ = this; } IPAManager::~IPAManager() { for (IPAModule *module : modules_) delete module; + + self_ = nullptr; } /** @@ -153,8 +163,7 @@ IPAManager::~IPAManager() */ IPAManager *IPAManager::instance() { - static IPAManager ipaManager; - return &ipaManager; + return self_; } /** diff --git a/test/ipa/ipa_interface_test.cpp b/test/ipa/ipa_interface_test.cpp index 2f02af49..153493ba 100644 --- a/test/ipa/ipa_interface_test.cpp +++ b/test/ipa/ipa_interface_test.cpp @@ -39,11 +39,15 @@ public: ~IPAInterfaceTest() { delete notifier_; + ipa_.reset(); + ipaManager_.reset(); } protected: int init() override { + ipaManager_ = make_unique(); + /* Create a pipeline handler for vimc. */ std::vector &factories = PipelineHandlerFactory::factories(); @@ -161,6 +165,7 @@ private: std::shared_ptr pipe_; std::unique_ptr ipa_; + std::unique_ptr ipaManager_; enum IPAOperationCode trace_; EventNotifier *notifier_; int fd_; From patchwork Wed Jun 3 14:16:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 3906 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5CC2C6114D for ; Wed, 3 Jun 2020 16:16:25 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="D1oqqPGl"; dkim-atps=neutral Received: from emerald.amanokami.net (fs76eef344.knge213.ap.nuro.jp [118.238.243.68]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 179F527C; Wed, 3 Jun 2020 16:16:23 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1591193785; bh=zkkZ8HpwE1KadJjjp80IveswbRW2zPq0Smm8x52nocY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=D1oqqPGlRIDDGh6Y6IohlvH92L4nOYZR2zRZLOdccGNbTlz1NlC5MnMqBDh8uH952 Huiah4wsrwh1HCVhZxi/iXVqEIe9VJW74ArVyXaSn761AfZ8akHzOGZU8+2Ls2Kz7j GF76OlvPgjwE2Gf7LzTS2cMhugu4NLpuduA557iw= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 3 Jun 2020 23:16:06 +0900 Message-Id: <20200603141609.18584-3-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200603141609.18584-1-paul.elder@ideasonboard.com> References: <20200603141609.18584-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/5] v4l2: v4l2_camera_proxy: Fix bounds check for VIDIOC_ENUM_FMT X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 03 Jun 2020 14:16:26 -0000 VIDIOC_ENUM_FMT is meant to return -EINVAL if the requested index is out of bounds. This bounds is obtained from the libcamera Camera's list of formats. The bounds check for this list was incorrect; fix it. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- src/v4l2/v4l2_camera_proxy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 3df4d42b..ec6d265d 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -224,7 +224,7 @@ int V4L2CameraProxy::vidioc_enum_fmt(struct v4l2_fmtdesc *arg) LOG(V4L2Compat, Debug) << "Servicing vidioc_enum_fmt"; if (!validateBufferType(arg->type) || - arg->index > streamConfig_.formats().pixelformats().size()) + arg->index >= streamConfig_.formats().pixelformats().size()) return -EINVAL; /* \todo Add map from format to description. */ From patchwork Wed Jun 3 14:16:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 3907 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B988D6114D for ; Wed, 3 Jun 2020 16:16:26 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="rvA2fels"; dkim-atps=neutral Received: from emerald.amanokami.net (fs76eef344.knge213.ap.nuro.jp [118.238.243.68]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 8FE5827C; Wed, 3 Jun 2020 16:16:25 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1591193786; bh=0jvjRyLFjW1dQ/QuY+iycDWse4ctjcTQ5yW9YRmxhMY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rvA2felsjYH5KhBFV3+yP8g5F+dNeUzHatLLb0BNEQyeyfNS2ngmOA7uNsQZ3EWon ti7KlIcORQJBCPhOlKmbYqWKqlwsJ93CKwEkN+zbbuPt3C5RpkdB93uHU6yN3jEa3L 3xgtVaHGY/rkVGiXb/l5EZ8hVrH1QN+vPyybtR1Q= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 3 Jun 2020 23:16:07 +0900 Message-Id: <20200603141609.18584-4-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200603141609.18584-1-paul.elder@ideasonboard.com> References: <20200603141609.18584-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 3/5] v4l2: v4l2_camera_proxy: Acquire only one buffer semaphore on VIDIOC_DQBUF X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 03 Jun 2020 14:16:27 -0000 We use a semaphore to atomically keep track of how many buffers are available for dequeueing. The check for how to acquire the semaphore was incorrect, leading to a double acquire upon a successful nonblocking acquire. Fix this. Signed-off-by: Paul Elder --- src/v4l2/v4l2_camera_proxy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index ec6d265d..d2419b96 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -428,7 +428,7 @@ int V4L2CameraProxy::vidioc_dqbuf(struct v4l2_buffer *arg) if (nonBlocking_ && !vcam_->bufferSema_.tryAcquire()) return -EAGAIN; - else + else if (!nonBlocking_) vcam_->bufferSema_.acquire(); updateBuffers(); From patchwork Wed Jun 3 14:16:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 3908 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AB4576115D for ; Wed, 3 Jun 2020 16:16:28 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="CXHw+/VC"; dkim-atps=neutral Received: from emerald.amanokami.net (fs76eef344.knge213.ap.nuro.jp [118.238.243.68]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0F9A827C; Wed, 3 Jun 2020 16:16:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1591193788; bh=fzX5dsUHNWEcVPbQjILd17OrXxrDz+27H6d9cGGr7dE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CXHw+/VC1HXIq6EptMay9rW55nuHsVAvYvq9s9S8lnPRcTvSAFfPQOIw+JASmwbZL D81OGEJJtbTJqcxzrM8Lbfxq+EF4bOJdQqX9eycA5W4uRI5APH05QYp4b0wC/wGy+4 cMYWQxKqeS3OjQ5yXu92t4Zfo3zdmFmhKEl3TiVg= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 3 Jun 2020 23:16:08 +0900 Message-Id: <20200603141609.18584-5-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200603141609.18584-1-paul.elder@ideasonboard.com> References: <20200603141609.18584-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 4/5] v4l2: v4l2_camera_proxy: Don't return -EINVAL for zero sizeimage in REQBUFS X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 03 Jun 2020 14:16:29 -0000 If VIDIOC_REQBUFS returns -EINVAL, it signals to the application that the requested buffer or memory type is not supported. If we return -EINVAL due to a zero sizeimage, then the application will think that we don't support a memory type that we actually do. On the other hand, sizeimage will be zero for formats whose size we don't know how to calculate, such as MJPEG. If we try to stream such formats anyway, we will get a floating point exception and crash. Issue a warning for now, and don't return -EINVAL, so that we can continue operation. Signed-off-by: Paul Elder --- src/v4l2/v4l2_camera_proxy.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index d2419b96..f84982a2 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -352,8 +352,18 @@ int V4L2CameraProxy::vidioc_reqbufs(struct v4l2_requestbuffers *arg) return -EINVAL; sizeimage_ = calculateSizeImage(streamConfig_); + /* + * If we return -EINVAL here then the application will think that we + * don't support streaming mmap. Since we don't support readwrite and + * userptr either, the application will get confused and think that + * we don't support anything. + * On the other hand, if a format has a zero sizeimage (eg. MJPG), + * we'll get a floating point exception when we try to stream it. + */ if (sizeimage_ == 0) - return -EINVAL; + LOG(V4L2Compat, Warning) + << "sizeimage of at least one format is zero. " + << "Streaming this format will cause a floating point exception."; setFmtFromConfig(streamConfig_); From patchwork Wed Jun 3 14:16:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 3909 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2F9996116F for ; Wed, 3 Jun 2020 16:16:30 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="iLSk7tfQ"; dkim-atps=neutral Received: from emerald.amanokami.net (fs76eef344.knge213.ap.nuro.jp [118.238.243.68]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 093B027C; Wed, 3 Jun 2020 16:16:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1591193789; bh=R0WJ9U03iK+gB9VcUQHl5r54uddRL1IDSrncqefwfms=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iLSk7tfQ3WRXePchZlLXpIDhncKJxg3y+mvLrKMFIGJU5e/ow6mDZiLM832IMMJbo 5J6hwAwoC8C/emrdOl2g0grMC6O3RzqKJ5JCIQwy6ZesI3sFmMZz6ZmKkA5N7FU1Ys g4B/VUz+SBRcQ/Qsr77xgMfrcIPOZNF5V+IVqojs= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 3 Jun 2020 23:16:09 +0900 Message-Id: <20200603141609.18584-6-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200603141609.18584-1-paul.elder@ideasonboard.com> References: <20200603141609.18584-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 5/5] v4l2: v4l2_compat: Add sockets to support polling X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 03 Jun 2020 14:16:30 -0000 To support polling, we need to be able to signal when data is available to be read (POLLIN), as well as events (POLLPRI). To allow signaling POLLPRI specifically, change eventfd to a pair of sockets. After adding the socketpair, use the socketpair to signal POLLIN by writing a byte to the socket, and read the byte away upon VIDIOC_DQBUF to clear the handled POLLIN. Although POLLPRI is not actually implemented, since we don't support events, the facilities are in place. The implementation for signaling and clearing POLLPRI is the same as for POLLIN, except that we would send and receive an out-of-band byte through the socket. Signed-off-by: Paul Elder --- src/v4l2/v4l2_camera.cpp | 13 +++++++++++++ src/v4l2/v4l2_camera.h | 3 +++ src/v4l2/v4l2_camera_proxy.cpp | 14 ++++++++++++++ src/v4l2/v4l2_camera_proxy.h | 4 ++++ src/v4l2/v4l2_compat_manager.cpp | 22 ++++++++++++++++------ 5 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp index 4da01a45..ecbc87ec 100644 --- a/src/v4l2/v4l2_camera.cpp +++ b/src/v4l2/v4l2_camera.cpp @@ -8,6 +8,9 @@ #include "v4l2_camera.h" #include +#include +#include +#include #include "libcamera/internal/log.h" @@ -51,6 +54,13 @@ void V4L2Camera::close() bufferAllocator_ = nullptr; camera_->release(); + + ::close(sockfd_); +} + +void V4L2Camera::bind(int sockfd) +{ + sockfd_ = sockfd; } void V4L2Camera::getStreamConfig(StreamConfiguration *streamConfig) @@ -85,6 +95,9 @@ void V4L2Camera::requestComplete(Request *request) bufferLock_.unlock(); bufferSema_.release(); + + char tmp = 0; + ::send(sockfd_, &tmp, 1, 0); } int V4L2Camera::configure(StreamConfiguration *streamConfigOut, diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h index 303eda44..1ad040c1 100644 --- a/src/v4l2/v4l2_camera.h +++ b/src/v4l2/v4l2_camera.h @@ -39,6 +39,7 @@ public: int open(); void close(); + void bind(int sockfd); void getStreamConfig(StreamConfiguration *streamConfig); std::vector completedBuffers(); @@ -70,6 +71,8 @@ private: std::deque> pendingRequests_; std::deque> completedBuffers_; + + int sockfd_; }; #endif /* __V4L2_CAMERA_H__ */ diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index f84982a2..c9d7945a 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -13,6 +13,9 @@ #include #include #include +#include +#include +#include #include #include @@ -451,6 +454,11 @@ int V4L2CameraProxy::vidioc_dqbuf(struct v4l2_buffer *arg) currentBuf_ = (currentBuf_ + 1) % bufferCount_; + char tmp; + int ret = ::recv(sockfd_, &tmp, 1, 0); + if (ret < 1) + return -EBUSY; + return 0; } @@ -529,6 +537,12 @@ int V4L2CameraProxy::ioctl(unsigned long request, void *arg) return ret; } +void V4L2CameraProxy::bind(int sockfds[2]) +{ + sockfd_ = sockfds[0]; + vcam_->bind(sockfds[1]); +} + struct PixelFormatPlaneInfo { unsigned int bitsPerPixel; unsigned int hSubSampling; diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h index af9f9bbe..251b14a8 100644 --- a/src/v4l2/v4l2_camera_proxy.h +++ b/src/v4l2/v4l2_camera_proxy.h @@ -33,6 +33,8 @@ public: int ioctl(unsigned long request, void *arg); + void bind(int sockfds[2]); + private: bool validateBufferType(uint32_t type); bool validateMemoryType(uint32_t memory); @@ -77,6 +79,8 @@ private: std::map mmaps_; std::unique_ptr vcam_; + + int sockfd_; }; #endif /* __V4L2_CAMERA_PROXY_H__ */ diff --git a/src/v4l2/v4l2_compat_manager.cpp b/src/v4l2/v4l2_compat_manager.cpp index 2338a0ee..b6e84866 100644 --- a/src/v4l2/v4l2_compat_manager.cpp +++ b/src/v4l2/v4l2_compat_manager.cpp @@ -12,8 +12,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -155,15 +155,25 @@ int V4L2CompatManager::openat(int dirfd, const char *path, int oflag, mode_t mod if (ret < 0) return ret; - int efd = eventfd(0, oflag & (O_CLOEXEC | O_NONBLOCK)); - if (efd < 0) { + int sockets[2]; + ret = socketpair(AF_UNIX, + SOCK_STREAM + | ((oflag & O_CLOEXEC) ? SOCK_CLOEXEC : 0) + | ((oflag & O_NONBLOCK) ? SOCK_NONBLOCK : 0), + 0, sockets); + if (ret) { + int err = errno; proxy->close(); - return efd; + errno = err; + + return ret; } - devices_.emplace(efd, proxy); + proxy->bind(sockets); + + devices_.emplace(sockets[0], proxy); - return efd; + return sockets[0]; } int V4L2CompatManager::dup(int oldfd)