Message ID | 20241008231314.744556-5-kieran.bingham@ideasonboard.com |
---|---|
State | New |
Headers | show |
Series |
|
Related | show |
Hi Kieran On 09/10/2024 00:13, Kieran Bingham wrote: > 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 multiplexers that supply multiple cameras, so > make use of the MediaDevice::locateEntities to search for all cameras > and construct a pipeline for each. > > Reviewed-by: Umang Jain <umang.jain@ideasonboard.com> > Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > --- > src/libcamera/pipeline/rkisp1/rkisp1.cpp | 86 +++++++++--------------- > 1 file changed, 32 insertions(+), 54 deletions(-) > > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp > index 2fee84e56d4d..e94f047ba70c 100644 > --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp > +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp > @@ -37,6 +37,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" > @@ -108,6 +109,11 @@ public: > > std::unique_ptr<ipa::rkisp1::IPAProxyRkISP1> ipa_; > > + /* > + * All entities in the pipeline, from the camera sensor to the RkISP1. > + */ > + MediaPipeline pipe_; > + > private: > void paramFilled(unsigned int frame, unsigned int bytesused); > void setSensorControls(unsigned int frame, > @@ -171,8 +177,7 @@ private: > friend RkISP1CameraData; > 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 bufferReady(FrameBuffer *buffer); > @@ -187,7 +192,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_; > @@ -201,8 +205,6 @@ private: > std::queue<FrameBuffer *> availableStatBuffers_; > > Camera *activeCamera_; > - > - const MediaPad *ispSink_; > }; > > RkISP1Frames::RkISP1Frames(PipelineHandler *pipe) > @@ -712,7 +714,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; > > @@ -729,12 +731,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; > @@ -1035,7 +1037,6 @@ int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request) > */ > > int PipelineHandlerRkISP1::initLinks(Camera *camera, > - const CameraSensor *sensor, > const RkISP1CameraConfiguration &config) > { > RkISP1CameraData *data = cameraData(camera); > @@ -1046,31 +1047,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); > @@ -1094,6 +1080,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"); The "rkisp1_isp" entity is a subdevice right? That makes me a bit more wary of things in the last patch, as the impression I got from it was that the design is for sensor subdevice to video device...let me go back to that. > + if (ret) { > + LOG(RkISP1, Error) << "Failed to identify path from sensor to rkisp1_isp"; > + return ret; > + } > + > data->sensor_ = std::make_unique<CameraSensor>(sensor); > ret = data->sensor_->init(); > if (ret) > @@ -1129,6 +1122,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; > @@ -1136,8 +1130,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"); > @@ -1162,22 +1154,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) > @@ -1205,8 +1181,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, Info) << "Identified " << entity->name(); Does this need to be an Info, or would Debug do? Otherwise I think this looks ok: Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com> > + if (!createCamera(entity)) > registered = true; > } >
Quoting Dan Scally (2024-10-24 10:07:32) > Hi Kieran > > On 09/10/2024 00:13, Kieran Bingham wrote: > > 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 multiplexers that supply multiple cameras, so > > make use of the MediaDevice::locateEntities to search for all cameras > > and construct a pipeline for each. > > > > Reviewed-by: Umang Jain <umang.jain@ideasonboard.com> > > Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > > --- > > src/libcamera/pipeline/rkisp1/rkisp1.cpp | 86 +++++++++--------------- > > 1 file changed, 32 insertions(+), 54 deletions(-) > > > > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp > > index 2fee84e56d4d..e94f047ba70c 100644 > > --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp > > +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp > > @@ -37,6 +37,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" > > @@ -108,6 +109,11 @@ public: > > > > std::unique_ptr<ipa::rkisp1::IPAProxyRkISP1> ipa_; > > > > + /* > > + * All entities in the pipeline, from the camera sensor to the RkISP1. > > + */ > > + MediaPipeline pipe_; > > + > > private: > > void paramFilled(unsigned int frame, unsigned int bytesused); > > void setSensorControls(unsigned int frame, > > @@ -171,8 +177,7 @@ private: > > friend RkISP1CameraData; > > 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 bufferReady(FrameBuffer *buffer); > > @@ -187,7 +192,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_; > > @@ -201,8 +205,6 @@ private: > > std::queue<FrameBuffer *> availableStatBuffers_; > > > > Camera *activeCamera_; > > - > > - const MediaPad *ispSink_; > > }; > > > > RkISP1Frames::RkISP1Frames(PipelineHandler *pipe) > > @@ -712,7 +714,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; > > > > @@ -729,12 +731,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; > > @@ -1035,7 +1037,6 @@ int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request) > > */ > > > > int PipelineHandlerRkISP1::initLinks(Camera *camera, > > - const CameraSensor *sensor, > > const RkISP1CameraConfiguration &config) > > { > > RkISP1CameraData *data = cameraData(camera); > > @@ -1046,31 +1047,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); > > @@ -1094,6 +1080,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"); > > The "rkisp1_isp" entity is a subdevice right? That makes me a bit more wary of things in the last > patch, as the impression I got from it was that the design is for sensor subdevice to video > device...let me go back to that. Yes, correct - it's a subdevice. The original code base this came from was the simple pipeline handler which ends at a video device. But the RKISP1 feeds into the ISP. What I want from this series is to abstract a path of connected entities - and make sure that 'segment' is configurable independently regardless of length. In this instance - the raw data path from the sensor into the ISP only. > > > + if (ret) { > > + LOG(RkISP1, Error) << "Failed to identify path from sensor to rkisp1_isp"; > > + return ret; > > + } > > + > > data->sensor_ = std::make_unique<CameraSensor>(sensor); > > ret = data->sensor_->init(); > > if (ret) > > @@ -1129,6 +1122,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; > > @@ -1136,8 +1130,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"); > > @@ -1162,22 +1154,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) > > @@ -1205,8 +1181,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, Info) << "Identified " << entity->name(); > > Does this need to be an Info, or would Debug do? Yes, likely just a debug level is fine here ... We don't want things to be too verbose at startup - though it does help me seeing this at startup at the moment but I think I can manage to set a debug level ;-) > Otherwise I think this looks ok: > > Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com> Thanks > > > + if (!createCamera(entity)) > > registered = true; > > } > >
Hi Kieran On Wed, Oct 09, 2024 at 12:13:14AM +0100, Kieran Bingham wrote: > 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 multiplexers that supply multiple cameras, so > make use of the MediaDevice::locateEntities to search for all cameras > and construct a pipeline for each. > > Reviewed-by: Umang Jain <umang.jain@ideasonboard.com> > Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > --- > src/libcamera/pipeline/rkisp1/rkisp1.cpp | 86 +++++++++--------------- > 1 file changed, 32 insertions(+), 54 deletions(-) > > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp > index 2fee84e56d4d..e94f047ba70c 100644 > --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp > +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp > @@ -37,6 +37,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" > @@ -108,6 +109,11 @@ public: > > std::unique_ptr<ipa::rkisp1::IPAProxyRkISP1> ipa_; > > + /* > + * All entities in the pipeline, from the camera sensor to the RkISP1. > + */ (Almost) fits on 1 line > + MediaPipeline pipe_; > + > private: > void paramFilled(unsigned int frame, unsigned int bytesused); > void setSensorControls(unsigned int frame, > @@ -171,8 +177,7 @@ private: > friend RkISP1CameraData; > 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 bufferReady(FrameBuffer *buffer); > @@ -187,7 +192,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_; > @@ -201,8 +205,6 @@ private: > std::queue<FrameBuffer *> availableStatBuffers_; > > Camera *activeCamera_; > - > - const MediaPad *ispSink_; > }; > > RkISP1Frames::RkISP1Frames(PipelineHandler *pipe) > @@ -712,7 +714,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; > > @@ -729,12 +731,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; Actually the API is not that bad > > + LOG(RkISP1, Debug) << "Configuring ISP with : " << format; > ret = isp_->setFormat(0, &format); > if (ret < 0) > return ret; > @@ -1035,7 +1037,6 @@ int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request) > */ > > int PipelineHandlerRkISP1::initLinks(Camera *camera, > - const CameraSensor *sensor, > const RkISP1CameraConfiguration &config) > { > RkISP1CameraData *data = cameraData(camera); > @@ -1046,31 +1047,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); > @@ -1094,6 +1080,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 rkisp1_isp"; > + return ret; > + } > + > data->sensor_ = std::make_unique<CameraSensor>(sensor); > ret = data->sensor_->init(); > if (ret) > @@ -1129,6 +1122,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; > @@ -1136,8 +1130,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"); > @@ -1162,22 +1154,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) > @@ -1205,8 +1181,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, Info) << "Identified " << entity->name(); > + if (!createCamera(entity)) > registered = true; Looks good Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Thanks j > } > > -- > 2.34.1 >
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 2fee84e56d4d..e94f047ba70c 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -37,6 +37,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" @@ -108,6 +109,11 @@ public: std::unique_ptr<ipa::rkisp1::IPAProxyRkISP1> ipa_; + /* + * All entities in the pipeline, from the camera sensor to the RkISP1. + */ + MediaPipeline pipe_; + private: void paramFilled(unsigned int frame, unsigned int bytesused); void setSensorControls(unsigned int frame, @@ -171,8 +177,7 @@ private: friend RkISP1CameraData; 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 bufferReady(FrameBuffer *buffer); @@ -187,7 +192,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_; @@ -201,8 +205,6 @@ private: std::queue<FrameBuffer *> availableStatBuffers_; Camera *activeCamera_; - - const MediaPad *ispSink_; }; RkISP1Frames::RkISP1Frames(PipelineHandler *pipe) @@ -712,7 +714,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; @@ -729,12 +731,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; @@ -1035,7 +1037,6 @@ int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request) */ int PipelineHandlerRkISP1::initLinks(Camera *camera, - const CameraSensor *sensor, const RkISP1CameraConfiguration &config) { RkISP1CameraData *data = cameraData(camera); @@ -1046,31 +1047,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); @@ -1094,6 +1080,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 rkisp1_isp"; + return ret; + } + data->sensor_ = std::make_unique<CameraSensor>(sensor); ret = data->sensor_->init(); if (ret) @@ -1129,6 +1122,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; @@ -1136,8 +1130,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"); @@ -1162,22 +1154,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) @@ -1205,8 +1181,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, Info) << "Identified " << entity->name(); + if (!createCamera(entity)) registered = true; }