diff options
Diffstat (limited to 'src/v4l2')
-rw-r--r-- | src/v4l2/meson.build | 7 | ||||
-rw-r--r-- | src/v4l2/v4l2_camera.cpp | 7 | ||||
-rw-r--r-- | src/v4l2/v4l2_camera.h | 16 | ||||
-rw-r--r-- | src/v4l2/v4l2_camera_file.cpp | 2 | ||||
-rw-r--r-- | src/v4l2/v4l2_camera_file.h | 2 | ||||
-rw-r--r-- | src/v4l2/v4l2_camera_proxy.cpp | 20 | ||||
-rw-r--r-- | src/v4l2/v4l2_camera_proxy.h | 14 | ||||
-rw-r--r-- | src/v4l2/v4l2_compat.cpp | 2 | ||||
-rw-r--r-- | src/v4l2/v4l2_compat_manager.cpp | 34 | ||||
-rw-r--r-- | src/v4l2/v4l2_compat_manager.h | 2 |
10 files changed, 72 insertions, 34 deletions
diff --git a/src/v4l2/meson.build b/src/v4l2/meson.build index f132103c..58f53bf3 100644 --- a/src/v4l2/meson.build +++ b/src/v4l2/meson.build @@ -24,6 +24,7 @@ v4l2_compat_cpp_args = [ '-U_FILE_OFFSET_BITS', '-D_FILE_OFFSET_BITS=32', '-D_LARGEFILE64_SOURCE', + '-U_TIME_BITS', '-fvisibility=hidden', ] @@ -31,6 +32,7 @@ v4l2_compat = shared_library('v4l2-compat', v4l2_compat_sources, name_prefix : '', install : true, + install_dir : libcamera_libexecdir, dependencies : [libcamera_private, libdl], cpp_args : v4l2_compat_cpp_args) @@ -38,9 +40,10 @@ v4l2_compat = shared_library('v4l2-compat', # adaptation layer. cdata = configuration_data() -cdata.set('LIBCAMERA_V4L2_SO', get_option('prefix') / get_option('libdir') / 'v4l2-compat.so') +cdata.set('LIBCAMERA_V4L2_SO', get_option('prefix') / libcamera_libexecdir / 'v4l2-compat.so') configure_file(input : 'libcamerify.in', output : 'libcamerify', configuration : cdata, - install_dir : get_option('bindir')) + install_dir : get_option('bindir'), + install_tag : 'bin') diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp index e922b9e6..0f3b862f 100644 --- a/src/v4l2/v4l2_camera.cpp +++ b/src/v4l2/v4l2_camera.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * v4l2_camera.cpp - V4L2 compatibility camera + * V4L2 compatibility camera */ #include "v4l2_camera.h" @@ -71,11 +71,10 @@ std::vector<V4L2Camera::Buffer> V4L2Camera::completedBuffers() { std::vector<Buffer> v; - bufferLock_.lock(); + MutexLocker lock(bufferLock_); for (std::unique_ptr<Buffer> &metadata : completedBuffers_) v.push_back(*metadata.get()); completedBuffers_.clear(); - bufferLock_.unlock(); return v; } @@ -278,7 +277,7 @@ int V4L2Camera::qbuf(unsigned int index) void V4L2Camera::waitForBufferAvailable() { MutexLocker locker(bufferMutex_); - bufferCV_.wait(locker, [&] { + bufferCV_.wait(locker, [&]() LIBCAMERA_TSA_REQUIRES(bufferMutex_) { return bufferAvailableCount_ >= 1 || !isRunning_; }); if (isRunning_) diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h index 03e74118..278cc33e 100644 --- a/src/v4l2/v4l2_camera.h +++ b/src/v4l2/v4l2_camera.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * v4l2_camera.h - V4L2 compatibility camera + * V4L2 compatibility camera */ #pragma once @@ -39,7 +39,7 @@ public: void bind(int efd); void unbind(); - std::vector<Buffer> completedBuffers(); + std::vector<Buffer> completedBuffers() LIBCAMERA_TSA_EXCLUDES(bufferLock_); int configure(libcamera::StreamConfiguration *streamConfigOut, const libcamera::Size &size, @@ -58,13 +58,14 @@ public: int qbuf(unsigned int index); - void waitForBufferAvailable(); - bool isBufferAvailable(); + void waitForBufferAvailable() LIBCAMERA_TSA_EXCLUDES(bufferMutex_); + bool isBufferAvailable() LIBCAMERA_TSA_EXCLUDES(bufferMutex_); bool isRunning(); private: - void requestComplete(libcamera::Request *request); + void requestComplete(libcamera::Request *request) + LIBCAMERA_TSA_EXCLUDES(bufferLock_); std::shared_ptr<libcamera::Camera> camera_; std::unique_ptr<libcamera::CameraConfiguration> config_; @@ -77,11 +78,12 @@ private: std::vector<std::unique_ptr<libcamera::Request>> requestPool_; std::deque<libcamera::Request *> pendingRequests_; - std::deque<std::unique_ptr<Buffer>> completedBuffers_; + std::deque<std::unique_ptr<Buffer>> completedBuffers_ + LIBCAMERA_TSA_GUARDED_BY(bufferLock_); int efd_; libcamera::Mutex bufferMutex_; libcamera::ConditionVariable bufferCV_; - unsigned int bufferAvailableCount_; + unsigned int bufferAvailableCount_ LIBCAMERA_TSA_GUARDED_BY(bufferMutex_); }; diff --git a/src/v4l2/v4l2_camera_file.cpp b/src/v4l2/v4l2_camera_file.cpp index 0a41587c..d8fe854b 100644 --- a/src/v4l2/v4l2_camera_file.cpp +++ b/src/v4l2/v4l2_camera_file.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2020, Google Inc. * - * v4l2_camera_file.h - V4L2 compatibility camera file information + * V4L2 compatibility camera file information */ #include "v4l2_camera_file.h" diff --git a/src/v4l2/v4l2_camera_file.h b/src/v4l2/v4l2_camera_file.h index 1a7b6a63..1212989e 100644 --- a/src/v4l2/v4l2_camera_file.h +++ b/src/v4l2/v4l2_camera_file.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2020, Google Inc. * - * v4l2_camera_file.h - V4L2 compatibility camera file information + * V4L2 compatibility camera file information */ #pragma once diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 26a227da..3f7c00a2 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * v4l2_camera_proxy.cpp - Proxy to V4L2 compatibility camera + * Proxy to V4L2 compatibility camera */ #include "v4l2_camera_proxy.h" @@ -182,7 +182,7 @@ void V4L2CameraProxy::setFmtFromConfig(const StreamConfiguration &streamConfig) v4l2PixFormat_.width = size.width; v4l2PixFormat_.height = size.height; - v4l2PixFormat_.pixelformat = V4L2PixelFormat::fromPixelFormat(streamConfig.pixelFormat); + v4l2PixFormat_.pixelformat = V4L2PixelFormat::fromPixelFormat(streamConfig.pixelFormat)[0]; v4l2PixFormat_.field = V4L2_FIELD_NONE; v4l2PixFormat_.bytesperline = streamConfig.stride; v4l2PixFormat_.sizeimage = streamConfig.frameSize; @@ -290,7 +290,7 @@ int V4L2CameraProxy::vidioc_enum_fmt(V4L2CameraFile *file, struct v4l2_fmtdesc * return -EINVAL; PixelFormat format = streamConfig_.formats().pixelformats()[arg->index]; - V4L2PixelFormat v4l2Format = V4L2PixelFormat::fromPixelFormat(format); + V4L2PixelFormat v4l2Format = V4L2PixelFormat::fromPixelFormat(format)[0]; arg->flags = format == formats::MJPEG ? V4L2_FMT_FLAG_COMPRESSED : 0; utils::strlcpy(reinterpret_cast<char *>(arg->description), @@ -333,7 +333,7 @@ int V4L2CameraProxy::tryFormat(struct v4l2_format *arg) arg->fmt.pix.width = config.size.width; arg->fmt.pix.height = config.size.height; - arg->fmt.pix.pixelformat = V4L2PixelFormat::fromPixelFormat(config.pixelFormat); + arg->fmt.pix.pixelformat = V4L2PixelFormat::fromPixelFormat(config.pixelFormat)[0]; arg->fmt.pix.field = V4L2_FIELD_NONE; arg->fmt.pix.bytesperline = config.stride; arg->fmt.pix.sizeimage = config.frameSize; @@ -778,10 +778,20 @@ const std::set<unsigned long> V4L2CameraProxy::supportedIoctls_ = { VIDIOC_STREAMOFF, }; -int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *arg) +int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long longRequest, void *arg) { MutexLocker locker(proxyMutex_); + /* + * The Linux Kernel only processes 32 bits of an IOCTL. + * + * Prevent unexpected sign-extensions that could occur if applications + * use a signed int for the ioctl request, which would sign-extend to + * an incorrect value for unsigned longs on 64 bit architectures by + * explicitly casting as an unsigned int here. + */ + unsigned int request = longRequest; + if (!arg && (_IOC_DIR(request) & _IOC_WRITE)) { errno = EFAULT; return -1; diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h index 76ca2d8a..3d8784df 100644 --- a/src/v4l2/v4l2_camera_proxy.h +++ b/src/v4l2/v4l2_camera_proxy.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * v4l2_camera_proxy.h - Proxy to V4L2 compatibility camera + * Proxy to V4L2 compatibility camera */ #pragma once @@ -27,13 +27,15 @@ class V4L2CameraProxy public: V4L2CameraProxy(unsigned int index, std::shared_ptr<libcamera::Camera> camera); - int open(V4L2CameraFile *file); - void close(V4L2CameraFile *file); + int open(V4L2CameraFile *file) LIBCAMERA_TSA_EXCLUDES(proxyMutex_); + void close(V4L2CameraFile *file) LIBCAMERA_TSA_EXCLUDES(proxyMutex_); void *mmap(V4L2CameraFile *file, void *addr, size_t length, int prot, - int flags, off64_t offset); - int munmap(V4L2CameraFile *file, void *addr, size_t length); + int flags, off64_t offset) LIBCAMERA_TSA_EXCLUDES(proxyMutex_); + int munmap(V4L2CameraFile *file, void *addr, size_t length) + LIBCAMERA_TSA_EXCLUDES(proxyMutex_); - int ioctl(V4L2CameraFile *file, unsigned long request, void *arg); + int ioctl(V4L2CameraFile *file, unsigned long request, void *arg) + LIBCAMERA_TSA_EXCLUDES(proxyMutex_); private: bool validateBufferType(uint32_t type); diff --git a/src/v4l2/v4l2_compat.cpp b/src/v4l2/v4l2_compat.cpp index 1765fb5d..8e2b7e92 100644 --- a/src/v4l2/v4l2_compat.cpp +++ b/src/v4l2/v4l2_compat.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * v4l2_compat.cpp - V4L2 compatibility layer + * V4L2 compatibility layer */ #include "v4l2_compat_manager.h" diff --git a/src/v4l2/v4l2_compat_manager.cpp b/src/v4l2/v4l2_compat_manager.cpp index 0f7575c5..6a00afb5 100644 --- a/src/v4l2/v4l2_compat_manager.cpp +++ b/src/v4l2/v4l2_compat_manager.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * v4l2_compat_manager.cpp - V4L2 compatibility manager + * V4L2 compatibility manager */ #include "v4l2_compat_manager.h" @@ -24,6 +24,7 @@ #include <libcamera/camera.h> #include <libcamera/camera_manager.h> +#include <libcamera/property_ids.h> #include "v4l2_camera_file.h" @@ -113,14 +114,35 @@ int V4L2CompatManager::getCameraIndex(int fd) if (ret < 0) return -1; - std::shared_ptr<Camera> target = cm_->get(statbuf.st_rdev); - if (!target) - return -1; + const dev_t devnum = statbuf.st_rdev; + /* + * Iterate each known camera and identify if it reports this nodes + * device number in its list of SystemDevices. + */ auto cameras = cm_->cameras(); for (auto [index, camera] : utils::enumerate(cameras)) { - if (camera == target) - return index; + Span<const int64_t> devices = camera->properties() + .get(properties::SystemDevices) + .value_or(Span<int64_t>{}); + + /* + * While there may be multiple cameras that could reference the + * same device node, we take a first match as a best effort for + * now. + * + * \todo Each camera can be accessed through any of the video + * device nodes that it uses. This may confuse applications. + * Consider reworking the V4L2 adaptation layer to instead + * expose each Camera instance through a single video device + * node (with a consistent and stable mapping). The other + * device nodes could possibly be hidden from the application + * by intercepting additional calls to the C library. + */ + for (const int64_t dev : devices) { + if (dev == static_cast<int64_t>(devnum)) + return index; + } } return -1; diff --git a/src/v4l2/v4l2_compat_manager.h b/src/v4l2/v4l2_compat_manager.h index 64af9a8c..f7c6f122 100644 --- a/src/v4l2/v4l2_compat_manager.h +++ b/src/v4l2/v4l2_compat_manager.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * v4l2_compat_manager.h - V4L2 compatibility manager + * V4L2 compatibility manager */ #pragma once |