9076e88fc3
Previously, since we acquired the libcamera camera upon open(), it was impossible to support multiple open, as any subsequent opens would return error because the camera would already be acquired. To fix this, we first initialize the camera in the first call to V4L2CameraProxy::open(), just to heat up the stream format cache. We then add ownership by a V4L2CameraFile of a V4L2Camera via the V4L2CameraProxy. All vidioc ioctls prior to reqbufs > 0 (except for s_fmt) are able to access the camera without ownership. A call to reqbufs > 0 (and s_fmt) will take ownership, and the ownership will be released at reqbufs = 0. While ownership is assigned, the eventfd that should be signaled (and cleared) by V4L2Camera and V4L2CameraProxy is set to the V4L2CameraFile that has ownership, and is cleared when the ownership is released. In case close() is called without a reqbufs = 0 first, the ownership is also released on close(). We also use the V4L2CameraFile to contain all the information specific to an open instance of the file. This removes the need to keep track of such information within V4L2CameraProxy via multiple maps from int fd to info. Since V4L2 does not expect reqbufs 0 to ever return error, make V4L2CameraProxy::freeBuffers() return void. Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
99 lines
3.1 KiB
C++
99 lines
3.1 KiB
C++
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
/*
|
|
* Copyright (C) 2019, Google Inc.
|
|
*
|
|
* v4l2_camera_proxy.h - Proxy to V4L2 compatibility camera
|
|
*/
|
|
|
|
#ifndef __V4L2_CAMERA_PROXY_H__
|
|
#define __V4L2_CAMERA_PROXY_H__
|
|
|
|
#include <linux/videodev2.h>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <sys/mman.h>
|
|
#include <sys/types.h>
|
|
#include <vector>
|
|
|
|
#include <libcamera/camera.h>
|
|
|
|
#include "v4l2_camera.h"
|
|
|
|
using namespace libcamera;
|
|
|
|
class V4L2CameraFile;
|
|
|
|
class V4L2CameraProxy
|
|
{
|
|
public:
|
|
V4L2CameraProxy(unsigned int index, std::shared_ptr<Camera> camera);
|
|
|
|
int open(V4L2CameraFile *file);
|
|
void close(V4L2CameraFile *file);
|
|
void *mmap(void *addr, size_t length, int prot, int flags, off64_t offset);
|
|
int munmap(void *addr, size_t length);
|
|
|
|
int ioctl(V4L2CameraFile *file, unsigned long request, void *arg);
|
|
|
|
private:
|
|
bool validateBufferType(uint32_t type);
|
|
bool validateMemoryType(uint32_t memory);
|
|
void setFmtFromConfig(StreamConfiguration &streamConfig);
|
|
unsigned int calculateSizeImage(StreamConfiguration &streamConfig);
|
|
void querycap(std::shared_ptr<Camera> camera);
|
|
void tryFormat(struct v4l2_format *arg);
|
|
void updateBuffers();
|
|
void freeBuffers();
|
|
|
|
int vidioc_querycap(struct v4l2_capability *arg);
|
|
int vidioc_enum_fmt(V4L2CameraFile *file, struct v4l2_fmtdesc *arg);
|
|
int vidioc_g_fmt(V4L2CameraFile *file, struct v4l2_format *arg);
|
|
int vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg);
|
|
int vidioc_try_fmt(V4L2CameraFile *file, struct v4l2_format *arg);
|
|
int vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuffers *arg);
|
|
int vidioc_querybuf(V4L2CameraFile *file, struct v4l2_buffer *arg);
|
|
int vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg);
|
|
int vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg);
|
|
int vidioc_streamon(V4L2CameraFile *file, int *arg);
|
|
int vidioc_streamoff(V4L2CameraFile *file, int *arg);
|
|
|
|
bool hasOwnership(V4L2CameraFile *file);
|
|
int acquire(V4L2CameraFile *file);
|
|
void release(V4L2CameraFile *file);
|
|
|
|
static unsigned int bplMultiplier(uint32_t format);
|
|
static unsigned int imageSize(uint32_t format, unsigned int width,
|
|
unsigned int height);
|
|
|
|
static PixelFormat v4l2ToDrm(uint32_t format);
|
|
static uint32_t drmToV4L2(const PixelFormat &format);
|
|
|
|
unsigned int refcount_;
|
|
unsigned int index_;
|
|
|
|
struct v4l2_format curV4L2Format_;
|
|
StreamConfiguration streamConfig_;
|
|
struct v4l2_capability capabilities_;
|
|
unsigned int bufferCount_;
|
|
unsigned int currentBuf_;
|
|
unsigned int sizeimage_;
|
|
|
|
std::vector<struct v4l2_buffer> buffers_;
|
|
std::map<void *, unsigned int> mmaps_;
|
|
|
|
std::unique_ptr<V4L2Camera> vcam_;
|
|
|
|
/*
|
|
* This is the exclusive owner of this V4L2CameraProxy instance.
|
|
* When there is no owner, anybody can call any ioctl before reqbufs.
|
|
* The first file to call reqbufs with count > 0 or s_fmt will become
|
|
* the owner, and when the owner calls reqbufs with count = 0 it will
|
|
* release ownership. Any buffer-related ioctl (except querybuf) or
|
|
* s_fmt that is called by a non-owner while there exists an owner
|
|
* will return -EBUSY.
|
|
*/
|
|
V4L2CameraFile *owner_;
|
|
};
|
|
|
|
#endif /* __V4L2_CAMERA_PROXY_H__ */
|