summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacopo Mondi <jacopo.mondi@ideasonboard.com>2024-08-05 14:26:01 +0200
committerJacopo Mondi <jacopo.mondi@ideasonboard.com>2024-08-09 16:38:10 +0200
commit9fb4d454d2b747cd1e97de363e16dda16934f2e2 (patch)
treee121f3ab541b32db85161833895838432f897e1e
parent5bcd5bb6ca6a0101d767192d53d1bfb62b82df49 (diff)
HACK: acquire media device non-exclusiveleymulticontext/rpi/v3
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
-rw-r--r--include/libcamera/internal/device_enumerator.h1
-rw-r--r--include/libcamera/internal/media_device.h10
-rw-r--r--include/libcamera/internal/pipeline_handler.h2
-rw-r--r--src/libcamera/device_enumerator.cpp17
-rw-r--r--src/libcamera/media_device.cpp34
-rw-r--r--src/libcamera/pipeline/rpi/pisp/pisp.cpp23
-rw-r--r--src/libcamera/pipeline_handler.cpp39
-rw-r--r--src/libcamera/v4l2_videodevice.cpp2
8 files changed, 124 insertions, 4 deletions
diff --git a/include/libcamera/internal/device_enumerator.h b/include/libcamera/internal/device_enumerator.h
index db3532a9..4bc3a27d 100644
--- a/include/libcamera/internal/device_enumerator.h
+++ b/include/libcamera/internal/device_enumerator.h
@@ -42,6 +42,7 @@ public:
virtual int enumerate() = 0;
std::shared_ptr<MediaDevice> search(const DeviceMatch &dm);
+ std::shared_ptr<MediaDevice> searchNonExclusive(const DeviceMatch &dm);
Signal<> devicesAdded;
diff --git a/include/libcamera/internal/media_device.h b/include/libcamera/internal/media_device.h
index 992184ed..bcbedf5c 100644
--- a/include/libcamera/internal/media_device.h
+++ b/include/libcamera/internal/media_device.h
@@ -29,9 +29,14 @@ public:
~MediaDevice();
bool acquire();
+ bool acquireNonExclusive();
void release();
bool busy() const { return acquired_; }
+ /* HACKS */
+ unsigned int get() { return ++users_; }
+ unsigned int put() { return --users_; }
+
bool lock();
void unlock();
@@ -55,6 +60,8 @@ public:
int disableLinks();
int fd() const { return fd_.get(); }
+ int fd(unsigned int context) const { return fds_[context - 1].get(); }
+ unsigned int numContexts() const { return fds_.size(); }
Signal<> disconnected;
@@ -63,6 +70,7 @@ protected:
private:
int open();
+ int openMultiple();
void close();
MediaObject *object(unsigned int id);
@@ -86,8 +94,10 @@ private:
unsigned int hwRevision_;
UniqueFD fd_;
+ std::vector<UniqueFD> fds_;
bool valid_;
bool acquired_;
+ unsigned int users_;
std::map<unsigned int, MediaObject *> objects_;
std::vector<MediaEntity *> entities_;
diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h
index 746a34f8..7c316cb9 100644
--- a/include/libcamera/internal/pipeline_handler.h
+++ b/include/libcamera/internal/pipeline_handler.h
@@ -44,6 +44,8 @@ public:
virtual bool match(DeviceEnumerator *enumerator) = 0;
MediaDevice *acquireMediaDevice(DeviceEnumerator *enumerator,
const DeviceMatch &dm);
+ MediaDevice *acquireMediaDeviceNonExclusive(DeviceEnumerator *enumerator,
+ const DeviceMatch &dm);
bool acquire();
void release(Camera *camera);
diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp
index ae17862f..f8a8a5f6 100644
--- a/src/libcamera/device_enumerator.cpp
+++ b/src/libcamera/device_enumerator.cpp
@@ -325,4 +325,21 @@ std::shared_ptr<MediaDevice> DeviceEnumerator::search(const DeviceMatch &dm)
return nullptr;
}
+/**
+ * HACK
+ */
+std::shared_ptr<MediaDevice> DeviceEnumerator::searchNonExclusive(const DeviceMatch &dm)
+{
+ for (std::shared_ptr<MediaDevice> &media : devices_) {
+ if (dm.match(media.get())) {
+ LOG(DeviceEnumerator, Debug)
+ << "Successful match for media device \""
+ << media->driver() << "\"";
+ return media;
+ }
+ }
+
+ return nullptr;
+}
+
} /* namespace libcamera */
diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp
index bd054552..b8c5aca7 100644
--- a/src/libcamera/media_device.cpp
+++ b/src/libcamera/media_device.cpp
@@ -63,7 +63,7 @@ LOG_DEFINE_CATEGORY(MediaDevice)
* populate() before the media graph can be queried.
*/
MediaDevice::MediaDevice(const std::string &deviceNode)
- : deviceNode_(deviceNode), valid_(false), acquired_(false)
+ : deviceNode_(deviceNode), valid_(false), acquired_(false), users_(0)
{
}
@@ -112,6 +112,15 @@ bool MediaDevice::acquire()
return true;
}
+bool MediaDevice::acquireNonExclusive()
+{
+ if (openMultiple())
+ return false;
+
+ acquired_ = true;
+ return true;
+}
+
/**
* \brief Release a device previously claimed for exclusive use
* \sa acquire(), busy()
@@ -474,7 +483,7 @@ int MediaDevice::open()
{
if (fd_.isValid()) {
LOG(MediaDevice, Error) << "MediaDevice already open";
- return -EBUSY;
+ //return -EBUSY;
}
fd_ = UniqueFD(::open(deviceNode_.c_str(), O_RDWR | O_CLOEXEC));
@@ -489,6 +498,27 @@ int MediaDevice::open()
return 0;
}
+int MediaDevice::openMultiple()
+{
+ auto fd = UniqueFD(::open(deviceNode_.c_str(), O_RDWR | O_CLOEXEC));
+
+ if (!fd.isValid()) {
+ int ret = -errno;
+ LOG(MediaDevice, Error)
+ << "Failed to open media device at "
+ << deviceNode_ << ": " << strerror(-ret);
+ return ret;
+ }
+
+ if (!fd_.isValid())
+ fd_ = UniqueFD(fd.get());
+
+ fds_.push_back(std::move(fd));
+
+ return 0;
+}
+
+
/**
* \brief Close the media device
*
diff --git a/src/libcamera/pipeline/rpi/pisp/pisp.cpp b/src/libcamera/pipeline/rpi/pisp/pisp.cpp
index 09cc0178..a8ec495d 100644
--- a/src/libcamera/pipeline/rpi/pisp/pisp.cpp
+++ b/src/libcamera/pipeline/rpi/pisp/pisp.cpp
@@ -736,6 +736,8 @@ public:
RPi::Device<Cfe, 4> cfe_;
RPi::Device<Isp, 8> isp_;
+ MediaDevice *ispMediaDevice_;
+
const libpisp::PiSPVariant &pispVariant_;
/* Frontend/Backend objects shared with the IPA. */
@@ -875,7 +877,7 @@ bool PipelineHandlerPiSP::match(DeviceEnumerator *enumerator)
isp.add("pispbe-tdn_input");
isp.add("pispbe-stitch_output");
isp.add("pispbe-stitch_input");
- MediaDevice *ispDevice = acquireMediaDevice(enumerator, isp);
+ MediaDevice *ispDevice = acquireMediaDeviceNonExclusive(enumerator, isp);
if (!ispDevice) {
LOG(RPI, Debug) << "Unable to acquire ISP instance";
@@ -906,6 +908,8 @@ bool PipelineHandlerPiSP::match(DeviceEnumerator *enumerator)
PiSPCameraData *pisp =
static_cast<PiSPCameraData *>(cameraData.get());
+ pisp->ispMediaDevice_ = ispDevice;
+
pisp->fe_ = SharedMemObject<FrontEnd>
("pisp_frontend", true, pisp->pispVariant_);
pisp->be_ = SharedMemObject<BackEnd>
@@ -1124,12 +1128,29 @@ int PipelineHandlerPiSP::platformRegister(std::unique_ptr<RPi::CameraData> &came
data->streams_.push_back(&data->isp_[Isp::StitchInput]);
data->streams_.push_back(&data->isp_[Isp::StitchOutput]);
+ LOG(Error);
for (auto stream : data->streams_) {
ret = stream->dev()->open();
if (ret)
return ret;
}
+ LOG(Error);
+
+ unsigned int numContexts = data->ispMediaDevice_->numContexts();
+ LOG(Error) << "CONTEXTS: " << numContexts;
+ unsigned int contextFd = data->ispMediaDevice_->fd(numContexts);
+ LOG(Error) << "CONTEXT FD: " << contextFd;
+
+ data->isp_[Isp::Input].dev()->bindContext(contextFd);
+ data->isp_[Isp::Output0].dev()->bindContext(contextFd);
+ data->isp_[Isp::Output1].dev()->bindContext(contextFd);
+ data->isp_[Isp::Config].dev()->bindContext(contextFd);
+ data->isp_[Isp::TdnInput].dev()->bindContext(contextFd);
+ data->isp_[Isp::TdnOutput].dev()->bindContext(contextFd);
+ data->isp_[Isp::StitchInput].dev()->bindContext(contextFd);
+ data->isp_[Isp::StitchOutput].dev()->bindContext(contextFd);
+ LOG(Error);
/* Write up all the IPA connections. */
data->ipa_->prepareIspComplete.connect(data, &PiSPCameraData::prepareIspComplete);
data->ipa_->processStatsComplete.connect(data, &PiSPCameraData::processStatsComplete);
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index 5ea2ca78..69d88226 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -75,8 +75,12 @@ PipelineHandler::PipelineHandler(CameraManager *manager)
PipelineHandler::~PipelineHandler()
{
- for (std::shared_ptr<MediaDevice> media : mediaDevices_)
+ for (std::shared_ptr<MediaDevice> media : mediaDevices_) {
+ if (media->put())
+ continue;
+
media->release();
+ }
}
/**
@@ -138,6 +142,39 @@ MediaDevice *PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
if (!media->acquire())
return nullptr;
+ media->get();
+ mediaDevices_.push_back(media);
+
+ return media.get();
+}
+
+/**
+ * \brief Search and acquire non-exclusively a MediaDevice matching a device pattern
+ * \param[in] enumerator Enumerator containing all media devices in the system
+ * \param[in] dm Device match pattern
+ *
+ * \todo Just and hack for the PiSP BE
+ *
+ * \return A pointer to the matching MediaDevice, or nullptr if no match is found
+ */
+MediaDevice *PipelineHandler::acquireMediaDeviceNonExclusive(DeviceEnumerator *enumerator,
+ const DeviceMatch &dm)
+{
+ std::shared_ptr<MediaDevice> media = enumerator->searchNonExclusive(dm);
+ if (!media)
+ return nullptr;
+
+ bool busy = media->busy();
+ if (!media->acquireNonExclusive())
+ return nullptr;
+
+ /* If it was busy already, just get it. */
+ if (busy) {
+ media->get();
+ return media.get();
+ }
+
+ /* Otherwise add it to the list of media devs */
mediaDevices_.push_back(media);
return media.get();
diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
index a1d9f0ce..8cc3f5a2 100644
--- a/src/libcamera/v4l2_videodevice.cpp
+++ b/src/libcamera/v4l2_videodevice.cpp
@@ -800,6 +800,8 @@ int V4L2VideoDevice::bindContext(unsigned int context)
{
struct v4l2_context c = {};
+ LOG(Error) << "Bind to context " << context;
+
c.context_fd = context;
int ret = ioctl(VIDIOC_BIND_CONTEXT, &c);
if (ret)