v4l2: Remove internal thread
Now that libcamera creates threads internally and doesn't rely on an application-provided event loop, remove the thread from the V4L2 compatibility layer. The split between the V4L2CameraProxy and V4L2Camera classes is still kept to separate the V4L2 adaptation from camera operation. This may be further refactored later. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
This commit is contained in:
parent
b3b0d0a2e9
commit
8a8502ec0e
4 changed files with 31 additions and 75 deletions
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
using namespace libcamera;
|
using namespace libcamera;
|
||||||
|
|
||||||
class V4L2Camera : public Object
|
class V4L2Camera
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct Buffer {
|
struct Buffer {
|
||||||
|
|
|
@ -41,8 +41,7 @@ int V4L2CameraProxy::open(bool nonBlocking)
|
||||||
{
|
{
|
||||||
LOG(V4L2Compat, Debug) << "Servicing open";
|
LOG(V4L2Compat, Debug) << "Servicing open";
|
||||||
|
|
||||||
int ret = vcam_->invokeMethod(&V4L2Camera::open,
|
int ret = vcam_->open();
|
||||||
ConnectionTypeBlocking);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
errno = -ret;
|
errno = -ret;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -50,8 +49,7 @@ int V4L2CameraProxy::open(bool nonBlocking)
|
||||||
|
|
||||||
nonBlocking_ = nonBlocking;
|
nonBlocking_ = nonBlocking;
|
||||||
|
|
||||||
vcam_->invokeMethod(&V4L2Camera::getStreamConfig,
|
vcam_->getStreamConfig(&streamConfig_);
|
||||||
ConnectionTypeBlocking, &streamConfig_);
|
|
||||||
setFmtFromConfig(streamConfig_);
|
setFmtFromConfig(streamConfig_);
|
||||||
sizeimage_ = calculateSizeImage(streamConfig_);
|
sizeimage_ = calculateSizeImage(streamConfig_);
|
||||||
|
|
||||||
|
@ -72,7 +70,7 @@ void V4L2CameraProxy::close()
|
||||||
if (--refcount_ > 0)
|
if (--refcount_ > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vcam_->invokeMethod(&V4L2Camera::close, ConnectionTypeBlocking);
|
vcam_->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void *V4L2CameraProxy::mmap(void *addr, size_t length, int prot, int flags,
|
void *V4L2CameraProxy::mmap(void *addr, size_t length, int prot, int flags,
|
||||||
|
@ -284,11 +282,9 @@ int V4L2CameraProxy::vidioc_s_fmt(struct v4l2_format *arg)
|
||||||
tryFormat(arg);
|
tryFormat(arg);
|
||||||
|
|
||||||
Size size(arg->fmt.pix.width, arg->fmt.pix.height);
|
Size size(arg->fmt.pix.width, arg->fmt.pix.height);
|
||||||
int ret = vcam_->invokeMethod(&V4L2Camera::configure,
|
int ret = vcam_->configure(&streamConfig_, size,
|
||||||
ConnectionTypeBlocking,
|
v4l2ToDrm(arg->fmt.pix.pixelformat),
|
||||||
&streamConfig_, size,
|
bufferCount_);
|
||||||
v4l2ToDrm(arg->fmt.pix.pixelformat),
|
|
||||||
bufferCount_);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -319,13 +315,12 @@ int V4L2CameraProxy::freeBuffers()
|
||||||
{
|
{
|
||||||
LOG(V4L2Compat, Debug) << "Freeing libcamera bufs";
|
LOG(V4L2Compat, Debug) << "Freeing libcamera bufs";
|
||||||
|
|
||||||
int ret = vcam_->invokeMethod(&V4L2Camera::streamOff,
|
int ret = vcam_->streamOff();
|
||||||
ConnectionTypeBlocking);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
LOG(V4L2Compat, Error) << "Failed to stop stream";
|
LOG(V4L2Compat, Error) << "Failed to stop stream";
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
vcam_->invokeMethod(&V4L2Camera::freeBuffers, ConnectionTypeBlocking);
|
vcam_->freeBuffers();
|
||||||
bufferCount_ = 0;
|
bufferCount_ = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -349,11 +344,9 @@ int V4L2CameraProxy::vidioc_reqbufs(struct v4l2_requestbuffers *arg)
|
||||||
return freeBuffers();
|
return freeBuffers();
|
||||||
|
|
||||||
Size size(curV4L2Format_.fmt.pix.width, curV4L2Format_.fmt.pix.height);
|
Size size(curV4L2Format_.fmt.pix.width, curV4L2Format_.fmt.pix.height);
|
||||||
ret = vcam_->invokeMethod(&V4L2Camera::configure,
|
ret = vcam_->configure(&streamConfig_, size,
|
||||||
ConnectionTypeBlocking,
|
v4l2ToDrm(curV4L2Format_.fmt.pix.pixelformat),
|
||||||
&streamConfig_, size,
|
arg->count);
|
||||||
v4l2ToDrm(curV4L2Format_.fmt.pix.pixelformat),
|
|
||||||
arg->count);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -366,8 +359,7 @@ int V4L2CameraProxy::vidioc_reqbufs(struct v4l2_requestbuffers *arg)
|
||||||
arg->count = streamConfig_.bufferCount;
|
arg->count = streamConfig_.bufferCount;
|
||||||
bufferCount_ = arg->count;
|
bufferCount_ = arg->count;
|
||||||
|
|
||||||
ret = vcam_->invokeMethod(&V4L2Camera::allocBuffers,
|
ret = vcam_->allocBuffers(arg->count);
|
||||||
ConnectionTypeBlocking, arg->count);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
arg->count = 0;
|
arg->count = 0;
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -415,8 +407,7 @@ int V4L2CameraProxy::vidioc_qbuf(struct v4l2_buffer *arg)
|
||||||
arg->index >= bufferCount_)
|
arg->index >= bufferCount_)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
int ret = vcam_->invokeMethod(&V4L2Camera::qbuf, ConnectionTypeBlocking,
|
int ret = vcam_->qbuf(arg->index);
|
||||||
arg->index);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -459,10 +450,7 @@ int V4L2CameraProxy::vidioc_streamon(int *arg)
|
||||||
if (!validateBufferType(*arg))
|
if (!validateBufferType(*arg))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
int ret = vcam_->invokeMethod(&V4L2Camera::streamOn,
|
return vcam_->streamOn();
|
||||||
ConnectionTypeBlocking);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int V4L2CameraProxy::vidioc_streamoff(int *arg)
|
int V4L2CameraProxy::vidioc_streamoff(int *arg)
|
||||||
|
@ -472,8 +460,7 @@ int V4L2CameraProxy::vidioc_streamoff(int *arg)
|
||||||
if (!validateBufferType(*arg))
|
if (!validateBufferType(*arg))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
int ret = vcam_->invokeMethod(&V4L2Camera::streamOff,
|
int ret = vcam_->streamOff();
|
||||||
ConnectionTypeBlocking);
|
|
||||||
|
|
||||||
for (struct v4l2_buffer &buf : buffers_)
|
for (struct v4l2_buffer &buf : buffers_)
|
||||||
buf.flags &= ~(V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE);
|
buf.flags &= ~(V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE);
|
||||||
|
|
|
@ -37,7 +37,7 @@ void get_symbol(T &func, const char *name)
|
||||||
} /* namespace */
|
} /* namespace */
|
||||||
|
|
||||||
V4L2CompatManager::V4L2CompatManager()
|
V4L2CompatManager::V4L2CompatManager()
|
||||||
: cm_(nullptr), initialized_(false)
|
: cm_(nullptr)
|
||||||
{
|
{
|
||||||
get_symbol(fops_.openat, "openat");
|
get_symbol(fops_.openat, "openat");
|
||||||
get_symbol(fops_.dup, "dup");
|
get_symbol(fops_.dup, "dup");
|
||||||
|
@ -52,24 +52,15 @@ V4L2CompatManager::~V4L2CompatManager()
|
||||||
devices_.clear();
|
devices_.clear();
|
||||||
mmaps_.clear();
|
mmaps_.clear();
|
||||||
|
|
||||||
if (isRunning()) {
|
if (cm_) {
|
||||||
exit(0);
|
proxies_.clear();
|
||||||
/* \todo Wait with a timeout, just in case. */
|
cm_->stop();
|
||||||
wait();
|
delete cm_;
|
||||||
|
cm_ = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int V4L2CompatManager::init()
|
int V4L2CompatManager::start()
|
||||||
{
|
|
||||||
start();
|
|
||||||
|
|
||||||
MutexLocker locker(mutex_);
|
|
||||||
cv_.wait(locker, [&] { return initialized_; });
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void V4L2CompatManager::run()
|
|
||||||
{
|
{
|
||||||
cm_ = new CameraManager();
|
cm_ = new CameraManager();
|
||||||
|
|
||||||
|
@ -77,7 +68,9 @@ void V4L2CompatManager::run()
|
||||||
if (ret) {
|
if (ret) {
|
||||||
LOG(V4L2Compat, Error) << "Failed to start camera manager: "
|
LOG(V4L2Compat, Error) << "Failed to start camera manager: "
|
||||||
<< strerror(-ret);
|
<< strerror(-ret);
|
||||||
return;
|
delete cm_;
|
||||||
|
cm_ = nullptr;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(V4L2Compat, Debug) << "Started camera manager";
|
LOG(V4L2Compat, Debug) << "Started camera manager";
|
||||||
|
@ -93,22 +86,7 @@ void V4L2CompatManager::run()
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
return 0;
|
||||||
* libcamera has been initialized. Unlock the init() caller as we're
|
|
||||||
* now ready to handle calls from the framework.
|
|
||||||
*/
|
|
||||||
mutex_.lock();
|
|
||||||
initialized_ = true;
|
|
||||||
mutex_.unlock();
|
|
||||||
cv_.notify_one();
|
|
||||||
|
|
||||||
/* Now start processing events and messages. */
|
|
||||||
exec();
|
|
||||||
|
|
||||||
proxies_.clear();
|
|
||||||
cm_->stop();
|
|
||||||
delete cm_;
|
|
||||||
cm_ = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
V4L2CompatManager *V4L2CompatManager::instance()
|
V4L2CompatManager *V4L2CompatManager::instance()
|
||||||
|
@ -159,8 +137,8 @@ int V4L2CompatManager::openat(int dirfd, const char *path, int oflag, mode_t mod
|
||||||
major(statbuf.st_rdev) != 81)
|
major(statbuf.st_rdev) != 81)
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
if (!isRunning())
|
if (!cm_)
|
||||||
init();
|
start();
|
||||||
|
|
||||||
ret = getCameraIndex(fd);
|
ret = getCameraIndex(fd);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
|
|
@ -8,22 +8,19 @@
|
||||||
#ifndef __V4L2_COMPAT_MANAGER_H__
|
#ifndef __V4L2_COMPAT_MANAGER_H__
|
||||||
#define __V4L2_COMPAT_MANAGER_H__
|
#define __V4L2_COMPAT_MANAGER_H__
|
||||||
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <libcamera/camera_manager.h>
|
#include <libcamera/camera_manager.h>
|
||||||
|
|
||||||
#include "thread.h"
|
|
||||||
#include "v4l2_camera_proxy.h"
|
#include "v4l2_camera_proxy.h"
|
||||||
|
|
||||||
using namespace libcamera;
|
using namespace libcamera;
|
||||||
|
|
||||||
class V4L2CompatManager : public Thread
|
class V4L2CompatManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct FileOperations {
|
struct FileOperations {
|
||||||
|
@ -46,8 +43,6 @@ public:
|
||||||
|
|
||||||
static V4L2CompatManager *instance();
|
static V4L2CompatManager *instance();
|
||||||
|
|
||||||
int init();
|
|
||||||
|
|
||||||
V4L2CameraProxy *getProxy(int fd);
|
V4L2CameraProxy *getProxy(int fd);
|
||||||
const FileOperations &fops() const { return fops_; }
|
const FileOperations &fops() const { return fops_; }
|
||||||
|
|
||||||
|
@ -64,17 +59,13 @@ private:
|
||||||
V4L2CompatManager();
|
V4L2CompatManager();
|
||||||
~V4L2CompatManager();
|
~V4L2CompatManager();
|
||||||
|
|
||||||
void run() override;
|
int start();
|
||||||
int getCameraIndex(int fd);
|
int getCameraIndex(int fd);
|
||||||
|
|
||||||
FileOperations fops_;
|
FileOperations fops_;
|
||||||
|
|
||||||
CameraManager *cm_;
|
CameraManager *cm_;
|
||||||
|
|
||||||
std::mutex mutex_;
|
|
||||||
std::condition_variable cv_;
|
|
||||||
bool initialized_;
|
|
||||||
|
|
||||||
std::vector<std::unique_ptr<V4L2CameraProxy>> proxies_;
|
std::vector<std::unique_ptr<V4L2CameraProxy>> proxies_;
|
||||||
std::map<int, V4L2CameraProxy *> devices_;
|
std::map<int, V4L2CameraProxy *> devices_;
|
||||||
std::map<void *, V4L2CameraProxy *> mmaps_;
|
std::map<void *, V4L2CameraProxy *> mmaps_;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue