summaryrefslogtreecommitdiff
path: root/src
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 /src
parent5bcd5bb6ca6a0101d767192d53d1bfb62b82df49 (diff)
HACK: acquire media device non-exclusiveleymulticontext/rpi/v3
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Diffstat (limited to 'src')
-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
5 files changed, 111 insertions, 4 deletions
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)