summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHirokazu Honda <hiroh@chromium.org>2021-06-10 16:50:22 +0900
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2021-12-04 23:05:04 +0200
commit91dcd719d7c4aba3cd9942a77d03068c3f05c0a5 (patch)
treebfb9151544639a18e10f4444970c8b9cab59a45d
parentc49e888848154741af703596b0e70efdb0e0ec9e (diff)
libcamera: media_device: Manage fd by UniqueFD
Manages a file descriptor owned by MediaDevice for a media device node by UniqueFD. Signed-off-by: Hirokazu Honda <hiroh@chromium.org> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Hirokazu Honda <hiroh@chromium.org> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
-rw-r--r--include/libcamera/internal/media_device.h3
-rw-r--r--src/libcamera/media_device.cpp36
2 files changed, 17 insertions, 22 deletions
diff --git a/include/libcamera/internal/media_device.h b/include/libcamera/internal/media_device.h
index d636e34a..af0b25b7 100644
--- a/include/libcamera/internal/media_device.h
+++ b/include/libcamera/internal/media_device.h
@@ -16,6 +16,7 @@
#include <libcamera/base/log.h>
#include <libcamera/base/signal.h>
+#include <libcamera/base/unique_fd.h>
#include "libcamera/internal/media_object.h"
@@ -82,7 +83,7 @@ private:
unsigned int version_;
unsigned int hwRevision_;
- int fd_;
+ UniqueFD fd_;
bool valid_;
bool acquired_;
bool lockOwner_;
diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp
index aa93da75..4df0a27f 100644
--- a/src/libcamera/media_device.cpp
+++ b/src/libcamera/media_device.cpp
@@ -63,15 +63,14 @@ LOG_DEFINE_CATEGORY(MediaDevice)
* populate() before the media graph can be queried.
*/
MediaDevice::MediaDevice(const std::string &deviceNode)
- : deviceNode_(deviceNode), fd_(-1), valid_(false), acquired_(false),
+ : deviceNode_(deviceNode), valid_(false), acquired_(false),
lockOwner_(false)
{
}
MediaDevice::~MediaDevice()
{
- if (fd_ != -1)
- ::close(fd_);
+ fd_.reset();
clear();
}
@@ -143,14 +142,14 @@ void MediaDevice::release()
*/
bool MediaDevice::lock()
{
- if (fd_ == -1)
+ if (!fd_.isValid())
return false;
/* Do not allow nested locking in the same libcamera instance. */
if (lockOwner_)
return false;
- if (lockf(fd_, F_TLOCK, 0))
+ if (lockf(fd_.get(), F_TLOCK, 0))
return false;
lockOwner_ = true;
@@ -169,7 +168,7 @@ bool MediaDevice::lock()
*/
void MediaDevice::unlock()
{
- if (fd_ == -1)
+ if (!fd_.isValid())
return;
if (!lockOwner_)
@@ -177,7 +176,7 @@ void MediaDevice::unlock()
lockOwner_ = false;
- lockf(fd_, F_ULOCK, 0);
+ lockf(fd_.get(), F_ULOCK, 0);
}
/**
@@ -220,7 +219,7 @@ int MediaDevice::populate()
return ret;
struct media_device_info info = {};
- ret = ioctl(fd_, MEDIA_IOC_DEVICE_INFO, &info);
+ ret = ioctl(fd_.get(), MEDIA_IOC_DEVICE_INFO, &info);
if (ret) {
ret = -errno;
LOG(MediaDevice, Error)
@@ -243,7 +242,7 @@ int MediaDevice::populate()
topology.ptr_links = reinterpret_cast<uintptr_t>(links);
topology.ptr_pads = reinterpret_cast<uintptr_t>(pads);
- ret = ioctl(fd_, MEDIA_IOC_G_TOPOLOGY, &topology);
+ ret = ioctl(fd_.get(), MEDIA_IOC_G_TOPOLOGY, &topology);
if (ret < 0) {
ret = -errno;
LOG(MediaDevice, Error)
@@ -481,20 +480,19 @@ int MediaDevice::disableLinks()
*/
int MediaDevice::open()
{
- if (fd_ != -1) {
+ if (fd_.isValid()) {
LOG(MediaDevice, Error) << "MediaDevice already open";
return -EBUSY;
}
- int ret = ::open(deviceNode_.c_str(), O_RDWR);
- if (ret < 0) {
- ret = -errno;
+ fd_ = UniqueFD(::open(deviceNode_.c_str(), O_RDWR));
+ if (!fd_.isValid()) {
+ int ret = -errno;
LOG(MediaDevice, Error)
<< "Failed to open media device at "
<< deviceNode_ << ": " << strerror(-ret);
return ret;
}
- fd_ = ret;
return 0;
}
@@ -514,11 +512,7 @@ int MediaDevice::open()
*/
void MediaDevice::close()
{
- if (fd_ == -1)
- return;
-
- ::close(fd_);
- fd_ = -1;
+ fd_.reset();
}
/**
@@ -756,7 +750,7 @@ void MediaDevice::fixupEntityFlags(struct media_v2_entity *entity)
struct media_entity_desc desc = {};
desc.id = entity->id;
- int ret = ioctl(fd_, MEDIA_IOC_ENUM_ENTITIES, &desc);
+ int ret = ioctl(fd_.get(), MEDIA_IOC_ENUM_ENTITIES, &desc);
if (ret < 0) {
ret = -errno;
LOG(MediaDevice, Debug)
@@ -799,7 +793,7 @@ int MediaDevice::setupLink(const MediaLink *link, unsigned int flags)
linkDesc.flags = flags;
- int ret = ioctl(fd_, MEDIA_IOC_SETUP_LINK, &linkDesc);
+ int ret = ioctl(fd_.get(), MEDIA_IOC_SETUP_LINK, &linkDesc);
if (ret) {
ret = -errno;
LOG(MediaDevice, Error)
">} const char *card() const { return reinterpret_cast<const char *>(v4l2_capability::card); } const char *bus_info() const { return reinterpret_cast<const char *>(v4l2_capability::bus_info); } unsigned int device_caps() const { return capabilities & V4L2_CAP_DEVICE_CAPS ? v4l2_capability::device_caps : v4l2_capability::capabilities; } bool isMultiplanar() const { return device_caps() & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE); } bool isCapture() const { return device_caps() & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_META_CAPTURE); } bool isOutput() const { return device_caps() & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_META_OUTPUT); } bool isVideo() const { return device_caps() & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE); } bool isM2M() const { return device_caps() & (V4L2_CAP_VIDEO_M2M | V4L2_CAP_VIDEO_M2M_MPLANE); } bool isMeta() const { return device_caps() & (V4L2_CAP_META_CAPTURE | V4L2_CAP_META_OUTPUT); } bool isVideoCapture() const { return isVideo() && isCapture(); } bool isVideoOutput() const { return isVideo() && isOutput(); } bool isMetaCapture() const { return isMeta() && isCapture(); } bool isMetaOutput() const { return isMeta() && isOutput(); } bool hasStreaming() const { return device_caps() & V4L2_CAP_STREAMING; } }; class V4L2BufferCache { public: V4L2BufferCache(unsigned int numEntries); V4L2BufferCache(const std::vector<std::unique_ptr<FrameBuffer>> &buffers); ~V4L2BufferCache(); int get(const FrameBuffer &buffer); void put(unsigned int index); private: class Entry { public: Entry(); Entry(bool free, const FrameBuffer &buffer); bool operator==(const FrameBuffer &buffer); bool free; private: struct Plane { Plane(const FrameBuffer::Plane &plane) : fd(plane.fd.fd()), length(plane.length) { } int fd; unsigned int length; }; std::vector<Plane> planes_; }; std::vector<Entry> cache_; /* \todo Expose the miss counter through an instrumentation API. */ unsigned int missCounter_; }; class V4L2DeviceFormat { public: uint32_t fourcc; Size size; struct { uint32_t size; uint32_t bpl; } planes[3]; unsigned int planesCount; const std::string toString() const; }; class V4L2VideoDevice : public V4L2Device { public: explicit V4L2VideoDevice(const std::string &deviceNode); explicit V4L2VideoDevice(const MediaEntity *entity); V4L2VideoDevice(const V4L2VideoDevice &) = delete; ~V4L2VideoDevice(); V4L2VideoDevice &operator=(const V4L2VideoDevice &) = delete; int open(); int open(int handle, enum v4l2_buf_type type); void close(); const char *driverName() const { return caps_.driver(); } const char *deviceName() const { return caps_.card(); } const char *busName() const { return caps_.bus_info(); } int getFormat(V4L2DeviceFormat *format); int setFormat(V4L2DeviceFormat *format); ImageFormats formats(); int exportBuffers(BufferPool *pool); int importBuffers(BufferPool *pool); int releaseBuffers(); int queueBuffer(Buffer *buffer); std::vector<std::unique_ptr<Buffer>> queueAllBuffers(); Signal<Buffer *> bufferReady; int streamOn(); int streamOff(); static V4L2VideoDevice *fromEntityName(const MediaDevice *media, const std::string &entity); static PixelFormat toPixelFormat(uint32_t v4l2Fourcc); uint32_t toV4L2Fourcc(PixelFormat pixelFormat); static uint32_t toV4L2Fourcc(PixelFormat pixelFormat, bool multiplanar); protected: std::string logPrefix() const; private: int getFormatMeta(V4L2DeviceFormat *format); int setFormatMeta(V4L2DeviceFormat *format); int getFormatMultiplane(V4L2DeviceFormat *format); int setFormatMultiplane(V4L2DeviceFormat *format); int getFormatSingleplane(V4L2DeviceFormat *format); int setFormatSingleplane(V4L2DeviceFormat *format); std::vector<unsigned int> enumPixelformats(); std::vector<SizeRange> enumSizes(unsigned int pixelFormat); int requestBuffers(unsigned int count); int createPlane(BufferMemory *buffer, unsigned int index, unsigned int plane, unsigned int length); FileDescriptor exportDmabufFd(unsigned int index, unsigned int plane); Buffer *dequeueBuffer(); void bufferAvailable(EventNotifier *notifier); V4L2Capability caps_; enum v4l2_buf_type bufferType_; enum v4l2_memory memoryType_; BufferPool *bufferPool_; std::map<unsigned int, Buffer *> queuedBuffers_; EventNotifier *fdEvent_; }; class V4L2M2MDevice { public: V4L2M2MDevice(const std::string &deviceNode); ~V4L2M2MDevice(); int open(); void close(); V4L2VideoDevice *output() { return output_; } V4L2VideoDevice *capture() { return capture_; } private: std::string deviceNode_; V4L2VideoDevice *output_; V4L2VideoDevice *capture_; }; } /* namespace libcamera */ #endif /* __LIBCAMERA_V4L2_VIDEODEVICE_H__ */