diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libcamera/device_enumerator.cpp | 17 | ||||
-rw-r--r-- | src/libcamera/media_device.cpp | 34 | ||||
-rw-r--r-- | src/libcamera/pipeline/rpi/pisp/pisp.cpp | 23 | ||||
-rw-r--r-- | src/libcamera/pipeline_handler.cpp | 39 | ||||
-rw-r--r-- | src/libcamera/v4l2_videodevice.cpp | 2 |
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) |