Message ID | 20250402073919.183330-4-paul.elder@ideasonboard.com |
---|---|
State | New |
Headers | show |
Series |
|
Related | show |
On Wed, Apr 02, 2025 at 04:39:18PM +0900, Paul Elder wrote: > From: Kieran Bingham <kieran.bingham@ideasonboard.com> > > Use the new MediaPipeline to manage and identify all sensors connected > to complex pipelines that can connect to the CSI2 receiver before the > ISP. > > This can include chained multiplexors that supply multiple cameras, so > make use of the MediaDevice::locateEntities to search for all cameras > and construct a pipeline for each. > > Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > Reviewed-by: Umang Jain <umang.jain@ideasonboard.com> > Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com> > Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> > --- > src/libcamera/pipeline/rkisp1/rkisp1.cpp | 86 +++++++++--------------- > 1 file changed, 32 insertions(+), 54 deletions(-) Nice when that code gets shorter :-) Acked-by: Stefan Klug <stefan.klug@ideasonboard.com> > > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp > index 52633fe3cb85..705615b86b0c 100644 > --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp > +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp > @@ -42,6 +42,7 @@ > #include "libcamera/internal/framebuffer.h" > #include "libcamera/internal/ipa_manager.h" > #include "libcamera/internal/media_device.h" > +#include "libcamera/internal/media_pipeline.h" > #include "libcamera/internal/pipeline_handler.h" > #include "libcamera/internal/v4l2_subdevice.h" > #include "libcamera/internal/v4l2_videodevice.h" > @@ -116,6 +117,11 @@ public: > > ControlInfoMap ipaControls_; > > + /* > + * All entities in the pipeline, from the camera sensor to the RKISP1. > + */ > + MediaPipeline pipe_; > + > private: > void paramsComputed(unsigned int frame, unsigned int bytesused); > void setSensorControls(unsigned int frame, > @@ -180,8 +186,7 @@ private: > friend RkISP1CameraConfiguration; > friend RkISP1Frames; > > - int initLinks(Camera *camera, const CameraSensor *sensor, > - const RkISP1CameraConfiguration &config); > + int initLinks(Camera *camera, const RkISP1CameraConfiguration &config); > int createCamera(MediaEntity *sensor); > void tryCompleteRequest(RkISP1FrameInfo *info); > void imageBufferReady(FrameBuffer *buffer); > @@ -199,7 +204,6 @@ private: > std::unique_ptr<V4L2Subdevice> isp_; > std::unique_ptr<V4L2VideoDevice> param_; > std::unique_ptr<V4L2VideoDevice> stat_; > - std::unique_ptr<V4L2Subdevice> csi_; > > bool hasSelfPath_; > bool isRaw_; > @@ -223,8 +227,6 @@ private: > std::queue<FrameBuffer *> availableStatBuffers_; > > Camera *activeCamera_; > - > - const MediaPad *ispSink_; > }; > > RkISP1Frames::RkISP1Frames(PipelineHandler *pipe) > @@ -798,7 +800,7 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c) > CameraSensor *sensor = data->sensor_.get(); > int ret; > > - ret = initLinks(camera, sensor, *config); > + ret = initLinks(camera, *config); > if (ret) > return ret; > > @@ -821,12 +823,12 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c) > > LOG(RkISP1, Debug) << "Sensor configured with " << format; > > - if (csi_) { > - ret = csi_->setFormat(0, &format); > - if (ret < 0) > - return ret; > - } > + /* Propagate format through the internal media pipeline up to the ISP */ > + ret = data->pipe_.configure(sensor, &format); > + if (ret < 0) > + return ret; > > + LOG(RkISP1, Debug) << "Configuring ISP with : " << format; > ret = isp_->setFormat(0, &format); > if (ret < 0) > return ret; > @@ -1201,7 +1203,6 @@ int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request) > */ > > int PipelineHandlerRkISP1::initLinks(Camera *camera, > - const CameraSensor *sensor, > const RkISP1CameraConfiguration &config) > { > RkISP1CameraData *data = cameraData(camera); > @@ -1212,31 +1213,16 @@ int PipelineHandlerRkISP1::initLinks(Camera *camera, > return ret; > > /* > - * Configure the sensor links: enable the link corresponding to this > - * camera. > + * Configure the sensor links: enable the links corresponding to this > + * pipeline all the way up to the ISP, through any connected CSI receiver. > */ > - for (MediaLink *link : ispSink_->links()) { > - if (link->source()->entity() != sensor->entity()) > - continue; > - > - LOG(RkISP1, Debug) > - << "Enabling link from sensor '" > - << link->source()->entity()->name() > - << "' to ISP"; > - > - ret = link->setEnabled(true); > - if (ret < 0) > - return ret; > - } > - > - if (csi_) { > - MediaLink *link = isp_->entity()->getPadByIndex(0)->links().at(0); > - > - ret = link->setEnabled(true); > - if (ret < 0) > - return ret; > + ret = data->pipe_.initLinks(); > + if (ret) { > + LOG(RkISP1, Error) << "Failed to set up pipe links"; > + return ret; > } > > + /* Configure the paths after the ISP */ > for (const StreamConfiguration &cfg : config) { > if (cfg.stream() == &data->mainPathStream_) > ret = data->mainPath_->setEnabled(true); > @@ -1312,6 +1298,13 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor) > std::make_unique<RkISP1CameraData>(this, &mainPath_, > hasSelfPath_ ? &selfPath_ : nullptr); > > + /* Identify the pipeline path between the sensor and the rkisp1_isp */ > + ret = data->pipe_.init(sensor, "rkisp1_isp"); > + if (ret) { > + LOG(RkISP1, Error) << "Failed to identify path from sensor to sink"; > + return ret; > + } > + > data->sensor_ = CameraSensorFactoryBase::create(sensor); > if (!data->sensor_) > return -ENODEV; > @@ -1347,6 +1340,7 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor) > const std::string &id = data->sensor_->id(); > std::shared_ptr<Camera> camera = > Camera::create(std::move(data), id, streams); > + > registerCamera(std::move(camera)); > > return 0; > @@ -1354,8 +1348,6 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor) > > bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator) > { > - const MediaPad *pad; > - > DeviceMatch dm("rkisp1"); > dm.add("rkisp1_isp"); > dm.add("rkisp1_resizer_mainpath"); > @@ -1380,22 +1372,6 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator) > if (isp_->open() < 0) > return false; > > - /* Locate and open the optional CSI-2 receiver. */ > - ispSink_ = isp_->entity()->getPadByIndex(0); > - if (!ispSink_ || ispSink_->links().empty()) > - return false; > - > - pad = ispSink_->links().at(0)->source(); > - if (pad->entity()->function() == MEDIA_ENT_F_VID_IF_BRIDGE) { > - csi_ = std::make_unique<V4L2Subdevice>(pad->entity()); > - if (csi_->open() < 0) > - return false; > - > - ispSink_ = csi_->entity()->getPadByIndex(0); > - if (!ispSink_) > - return false; > - } > - > /* Locate and open the stats and params video nodes. */ > stat_ = V4L2VideoDevice::fromEntityName(media_, "rkisp1_stats"); > if (stat_->open() < 0) > @@ -1446,8 +1422,10 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator) > * camera instance for each of them. > */ > bool registered = false; > - for (MediaLink *link : ispSink_->links()) { > - if (!createCamera(link->source()->entity())) > + > + for (MediaEntity *entity : media_->locateEntities(MEDIA_ENT_F_CAM_SENSOR)) { > + LOG(RkISP1, Debug) << "Identified " << entity->name(); > + if (!createCamera(entity)) > registered = true; > } > > -- > 2.47.2 >
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 52633fe3cb85..705615b86b0c 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -42,6 +42,7 @@ #include "libcamera/internal/framebuffer.h" #include "libcamera/internal/ipa_manager.h" #include "libcamera/internal/media_device.h" +#include "libcamera/internal/media_pipeline.h" #include "libcamera/internal/pipeline_handler.h" #include "libcamera/internal/v4l2_subdevice.h" #include "libcamera/internal/v4l2_videodevice.h" @@ -116,6 +117,11 @@ public: ControlInfoMap ipaControls_; + /* + * All entities in the pipeline, from the camera sensor to the RKISP1. + */ + MediaPipeline pipe_; + private: void paramsComputed(unsigned int frame, unsigned int bytesused); void setSensorControls(unsigned int frame, @@ -180,8 +186,7 @@ private: friend RkISP1CameraConfiguration; friend RkISP1Frames; - int initLinks(Camera *camera, const CameraSensor *sensor, - const RkISP1CameraConfiguration &config); + int initLinks(Camera *camera, const RkISP1CameraConfiguration &config); int createCamera(MediaEntity *sensor); void tryCompleteRequest(RkISP1FrameInfo *info); void imageBufferReady(FrameBuffer *buffer); @@ -199,7 +204,6 @@ private: std::unique_ptr<V4L2Subdevice> isp_; std::unique_ptr<V4L2VideoDevice> param_; std::unique_ptr<V4L2VideoDevice> stat_; - std::unique_ptr<V4L2Subdevice> csi_; bool hasSelfPath_; bool isRaw_; @@ -223,8 +227,6 @@ private: std::queue<FrameBuffer *> availableStatBuffers_; Camera *activeCamera_; - - const MediaPad *ispSink_; }; RkISP1Frames::RkISP1Frames(PipelineHandler *pipe) @@ -798,7 +800,7 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c) CameraSensor *sensor = data->sensor_.get(); int ret; - ret = initLinks(camera, sensor, *config); + ret = initLinks(camera, *config); if (ret) return ret; @@ -821,12 +823,12 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c) LOG(RkISP1, Debug) << "Sensor configured with " << format; - if (csi_) { - ret = csi_->setFormat(0, &format); - if (ret < 0) - return ret; - } + /* Propagate format through the internal media pipeline up to the ISP */ + ret = data->pipe_.configure(sensor, &format); + if (ret < 0) + return ret; + LOG(RkISP1, Debug) << "Configuring ISP with : " << format; ret = isp_->setFormat(0, &format); if (ret < 0) return ret; @@ -1201,7 +1203,6 @@ int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request) */ int PipelineHandlerRkISP1::initLinks(Camera *camera, - const CameraSensor *sensor, const RkISP1CameraConfiguration &config) { RkISP1CameraData *data = cameraData(camera); @@ -1212,31 +1213,16 @@ int PipelineHandlerRkISP1::initLinks(Camera *camera, return ret; /* - * Configure the sensor links: enable the link corresponding to this - * camera. + * Configure the sensor links: enable the links corresponding to this + * pipeline all the way up to the ISP, through any connected CSI receiver. */ - for (MediaLink *link : ispSink_->links()) { - if (link->source()->entity() != sensor->entity()) - continue; - - LOG(RkISP1, Debug) - << "Enabling link from sensor '" - << link->source()->entity()->name() - << "' to ISP"; - - ret = link->setEnabled(true); - if (ret < 0) - return ret; - } - - if (csi_) { - MediaLink *link = isp_->entity()->getPadByIndex(0)->links().at(0); - - ret = link->setEnabled(true); - if (ret < 0) - return ret; + ret = data->pipe_.initLinks(); + if (ret) { + LOG(RkISP1, Error) << "Failed to set up pipe links"; + return ret; } + /* Configure the paths after the ISP */ for (const StreamConfiguration &cfg : config) { if (cfg.stream() == &data->mainPathStream_) ret = data->mainPath_->setEnabled(true); @@ -1312,6 +1298,13 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor) std::make_unique<RkISP1CameraData>(this, &mainPath_, hasSelfPath_ ? &selfPath_ : nullptr); + /* Identify the pipeline path between the sensor and the rkisp1_isp */ + ret = data->pipe_.init(sensor, "rkisp1_isp"); + if (ret) { + LOG(RkISP1, Error) << "Failed to identify path from sensor to sink"; + return ret; + } + data->sensor_ = CameraSensorFactoryBase::create(sensor); if (!data->sensor_) return -ENODEV; @@ -1347,6 +1340,7 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor) const std::string &id = data->sensor_->id(); std::shared_ptr<Camera> camera = Camera::create(std::move(data), id, streams); + registerCamera(std::move(camera)); return 0; @@ -1354,8 +1348,6 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor) bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator) { - const MediaPad *pad; - DeviceMatch dm("rkisp1"); dm.add("rkisp1_isp"); dm.add("rkisp1_resizer_mainpath"); @@ -1380,22 +1372,6 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator) if (isp_->open() < 0) return false; - /* Locate and open the optional CSI-2 receiver. */ - ispSink_ = isp_->entity()->getPadByIndex(0); - if (!ispSink_ || ispSink_->links().empty()) - return false; - - pad = ispSink_->links().at(0)->source(); - if (pad->entity()->function() == MEDIA_ENT_F_VID_IF_BRIDGE) { - csi_ = std::make_unique<V4L2Subdevice>(pad->entity()); - if (csi_->open() < 0) - return false; - - ispSink_ = csi_->entity()->getPadByIndex(0); - if (!ispSink_) - return false; - } - /* Locate and open the stats and params video nodes. */ stat_ = V4L2VideoDevice::fromEntityName(media_, "rkisp1_stats"); if (stat_->open() < 0) @@ -1446,8 +1422,10 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator) * camera instance for each of them. */ bool registered = false; - for (MediaLink *link : ispSink_->links()) { - if (!createCamera(link->source()->entity())) + + for (MediaEntity *entity : media_->locateEntities(MEDIA_ENT_F_CAM_SENSOR)) { + LOG(RkISP1, Debug) << "Identified " << entity->name(); + if (!createCamera(entity)) registered = true; }