diff options
Diffstat (limited to 'src/v4l2')
-rw-r--r-- | src/v4l2/meson.build | 9 | ||||
-rw-r--r-- | src/v4l2/v4l2_camera.cpp | 48 | ||||
-rw-r--r-- | src/v4l2/v4l2_camera.h | 16 | ||||
-rw-r--r-- | src/v4l2/v4l2_camera_proxy.cpp | 13 | ||||
-rw-r--r-- | src/v4l2/v4l2_compat_manager.cpp | 15 |
5 files changed, 65 insertions, 36 deletions
diff --git a/src/v4l2/meson.build b/src/v4l2/meson.build index e3838f0b..f78497b6 100644 --- a/src/v4l2/meson.build +++ b/src/v4l2/meson.build @@ -1,5 +1,12 @@ # SPDX-License-Identifier: CC0-1.0 +if not get_option('v4l2') + v4l2_enabled = false + subdir_done() +endif + +v4l2_enabled = true + v4l2_compat_sources = files([ 'v4l2_camera.cpp', 'v4l2_camera_file.cpp', @@ -24,5 +31,5 @@ v4l2_compat = shared_library('v4l2-compat', v4l2_compat_sources, name_prefix : '', install : true, - dependencies : [ libcamera_dep, libdl ], + dependencies : [libcamera_private, libdl], cpp_args : v4l2_compat_cpp_args) diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp index 3565f369..157ab94e 100644 --- a/src/v4l2/v4l2_camera.cpp +++ b/src/v4l2/v4l2_camera.cpp @@ -10,11 +10,11 @@ #include <errno.h> #include <unistd.h> -#include "libcamera/internal/log.h" +#include <libcamera/base/log.h> using namespace libcamera; -LOG_DECLARE_CATEGORY(V4L2Compat); +LOG_DECLARE_CATEGORY(V4L2Compat) V4L2Camera::V4L2Camera(std::shared_ptr<Camera> camera) : camera_(camera), isRunning_(false), bufferAllocator_(nullptr), @@ -49,6 +49,8 @@ int V4L2Camera::open(StreamConfiguration *streamConfig) void V4L2Camera::close() { + requestPool_.clear(); + delete bufferAllocator_; bufferAllocator_ = nullptr; @@ -96,6 +98,7 @@ void V4L2Camera::requestComplete(Request *request) if (ret != sizeof(data)) LOG(V4L2Compat, Error) << "Failed to signal eventfd POLLIN"; + request->reuse(); { MutexLocker locker(bufferMutex_); bufferAvailableCount_++; @@ -154,16 +157,30 @@ int V4L2Camera::validateConfiguration(const PixelFormat &pixelFormat, return 0; } -int V4L2Camera::allocBuffers([[maybe_unused]] unsigned int count) +int V4L2Camera::allocBuffers(unsigned int count) { Stream *stream = config_->at(0).stream(); - return bufferAllocator_->allocate(stream); + int ret = bufferAllocator_->allocate(stream); + if (ret < 0) + return ret; + + for (unsigned int i = 0; i < count; i++) { + std::unique_ptr<Request> request = camera_->createRequest(i); + if (!request) { + requestPool_.clear(); + return -ENOMEM; + } + requestPool_.push_back(std::move(request)); + } + + return ret; } void V4L2Camera::freeBuffers() { pendingRequests_.clear(); + requestPool_.clear(); Stream *stream = config_->at(0).stream(); bufferAllocator_->free(stream); @@ -192,9 +209,9 @@ int V4L2Camera::streamOn() isRunning_ = true; - for (std::unique_ptr<Request> &req : pendingRequests_) { + for (Request *req : pendingRequests_) { /* \todo What should we do if this returns -EINVAL? */ - ret = camera_->queueRequest(req.release()); + ret = camera_->queueRequest(req); if (ret < 0) return ret == -EACCES ? -EBUSY : ret; } @@ -206,8 +223,12 @@ int V4L2Camera::streamOn() int V4L2Camera::streamOff() { - if (!isRunning_) + if (!isRunning_) { + for (std::unique_ptr<Request> &req : requestPool_) + req->reuse(); + return 0; + } pendingRequests_.clear(); @@ -226,12 +247,11 @@ int V4L2Camera::streamOff() int V4L2Camera::qbuf(unsigned int index) { - std::unique_ptr<Request> request = - std::unique_ptr<Request>(camera_->createRequest(index)); - if (!request) { - LOG(V4L2Compat, Error) << "Can't create request"; - return -ENOMEM; + if (index >= requestPool_.size()) { + LOG(V4L2Compat, Error) << "Invalid index"; + return -EINVAL; } + Request *request = requestPool_[index].get(); Stream *stream = config_->at(0).stream(); FrameBuffer *buffer = bufferAllocator_->buffers(stream)[index].get(); @@ -242,11 +262,11 @@ int V4L2Camera::qbuf(unsigned int index) } if (!isRunning_) { - pendingRequests_.push_back(std::move(request)); + pendingRequests_.push_back(request); return 0; } - ret = camera_->queueRequest(request.release()); + ret = camera_->queueRequest(request); if (ret < 0) { LOG(V4L2Compat, Error) << "Can't queue request"; return ret == -EACCES ? -EBUSY : ret; diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h index 1fc5ebef..a095f4e2 100644 --- a/src/v4l2/v4l2_camera.h +++ b/src/v4l2/v4l2_camera.h @@ -12,13 +12,13 @@ #include <mutex> #include <utility> -#include <libcamera/buffer.h> +#include <libcamera/base/semaphore.h> + #include <libcamera/camera.h> #include <libcamera/file_descriptor.h> +#include <libcamera/framebuffer.h> #include <libcamera/framebuffer_allocator.h> -#include "libcamera/internal/semaphore.h" - using namespace libcamera; class V4L2Camera @@ -26,12 +26,12 @@ class V4L2Camera public: struct Buffer { Buffer(unsigned int index, const FrameMetadata &data) - : index(index), data(data) + : index_(index), data_(data) { } - unsigned int index; - FrameMetadata data; + unsigned int index_; + FrameMetadata data_; }; V4L2Camera(std::shared_ptr<Camera> camera); @@ -76,7 +76,9 @@ private: std::mutex bufferLock_; FrameBufferAllocator *bufferAllocator_; - std::deque<std::unique_ptr<Request>> pendingRequests_; + std::vector<std::unique_ptr<Request>> requestPool_; + + std::deque<Request *> pendingRequests_; std::deque<std::unique_ptr<Buffer>> completedBuffers_; int efd_; diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 8ff990f6..7682c4bd 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -18,11 +18,12 @@ #include <libcamera/camera.h> #include <libcamera/formats.h> -#include <libcamera/object.h> + +#include <libcamera/base/log.h> +#include <libcamera/base/object.h> +#include <libcamera/base/utils.h> #include "libcamera/internal/formats.h" -#include "libcamera/internal/log.h" -#include "libcamera/internal/utils.h" #include "v4l2_camera.h" #include "v4l2_camera_file.h" @@ -32,7 +33,7 @@ using namespace libcamera; -LOG_DECLARE_CATEGORY(V4L2Compat); +LOG_DECLARE_CATEGORY(V4L2Compat) V4L2CameraProxy::V4L2CameraProxy(unsigned int index, std::shared_ptr<Camera> camera) @@ -206,8 +207,8 @@ void V4L2CameraProxy::updateBuffers() { std::vector<V4L2Camera::Buffer> completedBuffers = vcam_->completedBuffers(); for (const V4L2Camera::Buffer &buffer : completedBuffers) { - const FrameMetadata &fmd = buffer.data; - struct v4l2_buffer &buf = buffers_[buffer.index]; + const FrameMetadata &fmd = buffer.data_; + struct v4l2_buffer &buf = buffers_[buffer.index_]; switch (fmd.status) { case FrameMetadata::FrameSuccess: diff --git a/src/v4l2/v4l2_compat_manager.cpp b/src/v4l2/v4l2_compat_manager.cpp index 90c0f012..e566125a 100644 --- a/src/v4l2/v4l2_compat_manager.cpp +++ b/src/v4l2/v4l2_compat_manager.cpp @@ -19,11 +19,12 @@ #include <sys/types.h> #include <unistd.h> +#include <libcamera/base/log.h> +#include <libcamera/base/utils.h> + #include <libcamera/camera.h> #include <libcamera/camera_manager.h> -#include "libcamera/internal/log.h" - #include "v4l2_camera_file.h" using namespace libcamera; @@ -81,11 +82,10 @@ int V4L2CompatManager::start() * For each Camera registered in the system, a V4L2CameraProxy gets * created here to wrap a camera device. */ - unsigned int index = 0; - for (auto &camera : cm_->cameras()) { + auto cameras = cm_->cameras(); + for (auto [index, camera] : utils::enumerate(cameras)) { V4L2CameraProxy *proxy = new V4L2CameraProxy(index, camera); proxies_.emplace_back(proxy); - ++index; } return 0; @@ -117,11 +117,10 @@ int V4L2CompatManager::getCameraIndex(int fd) if (!target) return -1; - unsigned int index = 0; - for (auto &camera : cm_->cameras()) { + auto cameras = cm_->cameras(); + for (auto [index, camera] : utils::enumerate(cameras)) { if (camera == target) return index; - ++index; } return -1; |