[2/3] libcamera: pipeline: utilise shared MediaDevice pointers
diff mbox series

Message ID 20250404074624.2975182-3-paul.elder@ideasonboard.com
State New
Headers show
Series
  • libcamera: pipeline: Use shared pointers for MediaDevice
Related show

Commit Message

Paul Elder April 4, 2025, 7:46 a.m. UTC
From: Kieran Bingham <kieran.bingham@ideasonboard.com>

Adapt the PipelineHandler::acquireMediaDevice() support function to
return a shared pointer instead of the underlying raw pointer.

Propagate this update to all pipeline handlers that use the MediaDevice
and store a std::shared_ptr<MediaDevice> accordingly.

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
---
 include/libcamera/internal/pipeline_handler.h      |  8 ++++----
 src/libcamera/pipeline/imx8-isi/imx8-isi.cpp       |  2 +-
 src/libcamera/pipeline/ipu3/cio2.cpp               |  2 +-
 src/libcamera/pipeline/ipu3/cio2.h                 |  2 +-
 src/libcamera/pipeline/ipu3/imgu.cpp               |  3 ++-
 src/libcamera/pipeline/ipu3/imgu.h                 |  4 ++--
 src/libcamera/pipeline/ipu3/ipu3.cpp               |  4 ++--
 src/libcamera/pipeline/mali-c55/mali-c55.cpp       |  2 +-
 src/libcamera/pipeline/rkisp1/rkisp1.cpp           |  2 +-
 src/libcamera/pipeline/rkisp1/rkisp1_path.cpp      |  2 +-
 src/libcamera/pipeline/rkisp1/rkisp1_path.h        |  2 +-
 .../pipeline/rpi/common/pipeline_base.cpp          |  6 ++++--
 src/libcamera/pipeline/rpi/common/pipeline_base.h  |  9 ++++++---
 src/libcamera/pipeline/rpi/pisp/pisp.cpp           | 10 ++++++----
 src/libcamera/pipeline/rpi/vc4/vc4.cpp             | 13 +++++++++----
 src/libcamera/pipeline/simple/simple.cpp           | 13 +++++++------
 src/libcamera/pipeline/uvcvideo/uvcvideo.cpp       |  6 +++---
 src/libcamera/pipeline/vimc/vimc.cpp               |  6 +++---
 src/libcamera/pipeline_handler.cpp                 | 14 ++++++++------
 test/delayed_controls.cpp                          |  2 +-
 test/libtest/buffer_source.cpp                     |  2 +-
 21 files changed, 65 insertions(+), 49 deletions(-)

Comments

Jacopo Mondi April 6, 2025, 4:53 p.m. UTC | #1
Hi Paul

On Fri, Apr 04, 2025 at 04:46:22PM +0900, Paul Elder wrote:
> From: Kieran Bingham <kieran.bingham@ideasonboard.com>
>
> Adapt the PipelineHandler::acquireMediaDevice() support function to
> return a shared pointer instead of the underlying raw pointer.

It seems nice, but I wonder if it really is better ? The
PipelineHandler base class already stores a shared_ptr<> instance for
each acquired media device. Is passing it around by value and storing
a copy as classes member in derived classes worth it ?

Or is this about an ownership issue I am missing ?

>
> Propagate this update to all pipeline handlers that use the MediaDevice
> and store a std::shared_ptr<MediaDevice> accordingly.
>
> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
> ---
>  include/libcamera/internal/pipeline_handler.h      |  8 ++++----
>  src/libcamera/pipeline/imx8-isi/imx8-isi.cpp       |  2 +-
>  src/libcamera/pipeline/ipu3/cio2.cpp               |  2 +-
>  src/libcamera/pipeline/ipu3/cio2.h                 |  2 +-
>  src/libcamera/pipeline/ipu3/imgu.cpp               |  3 ++-
>  src/libcamera/pipeline/ipu3/imgu.h                 |  4 ++--
>  src/libcamera/pipeline/ipu3/ipu3.cpp               |  4 ++--
>  src/libcamera/pipeline/mali-c55/mali-c55.cpp       |  2 +-
>  src/libcamera/pipeline/rkisp1/rkisp1.cpp           |  2 +-
>  src/libcamera/pipeline/rkisp1/rkisp1_path.cpp      |  2 +-
>  src/libcamera/pipeline/rkisp1/rkisp1_path.h        |  2 +-
>  .../pipeline/rpi/common/pipeline_base.cpp          |  6 ++++--
>  src/libcamera/pipeline/rpi/common/pipeline_base.h  |  9 ++++++---
>  src/libcamera/pipeline/rpi/pisp/pisp.cpp           | 10 ++++++----
>  src/libcamera/pipeline/rpi/vc4/vc4.cpp             | 13 +++++++++----
>  src/libcamera/pipeline/simple/simple.cpp           | 13 +++++++------
>  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp       |  6 +++---
>  src/libcamera/pipeline/vimc/vimc.cpp               |  6 +++---
>  src/libcamera/pipeline_handler.cpp                 | 14 ++++++++------
>  test/delayed_controls.cpp                          |  2 +-
>  test/libtest/buffer_source.cpp                     |  2 +-
>  21 files changed, 65 insertions(+), 49 deletions(-)
>
> diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h
> index 5fa8bc2f66ee..0199ab7911c0 100644
> --- a/include/libcamera/internal/pipeline_handler.h
> +++ b/include/libcamera/internal/pipeline_handler.h
> @@ -38,8 +38,8 @@ public:
>  	virtual ~PipelineHandler();
>
>  	virtual bool match(DeviceEnumerator *enumerator) = 0;
> -	MediaDevice *acquireMediaDevice(DeviceEnumerator *enumerator,
> -					const DeviceMatch &dm);
> +	std::shared_ptr<MediaDevice> acquireMediaDevice(DeviceEnumerator *enumerator,
> +							const DeviceMatch &dm);
>
>  	bool acquire(Camera *camera);
>  	void release(Camera *camera);
> @@ -74,7 +74,7 @@ protected:
>  	void clearMediaDevices();
>
>  	void registerCamera(std::shared_ptr<Camera> camera);
> -	void hotplugMediaDevice(MediaDevice *media);
> +	void hotplugMediaDevice(std::shared_ptr<MediaDevice> media);
>
>  	virtual int queueRequestDevice(Camera *camera, Request *request) = 0;
>  	virtual void stopDevice(Camera *camera) = 0;
> @@ -87,7 +87,7 @@ protected:
>  private:
>  	void unlockMediaDevices();
>
> -	void mediaDeviceDisconnected(MediaDevice *media);
> +	void mediaDeviceDisconnected(std::shared_ptr<MediaDevice> media);
>  	virtual void disconnect();
>
>  	void doQueueRequest(Request *request);
> diff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
> index 4e66b3368d5a..850dbfcdc64b 100644
> --- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
> +++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
> @@ -139,7 +139,7 @@ private:
>
>  	void bufferReady(FrameBuffer *buffer);
>
> -	MediaDevice *isiDev_;
> +	std::shared_ptr<MediaDevice> isiDev_;
>
>  	std::unique_ptr<V4L2Subdevice> crossbar_;
>  	std::vector<Pipe> pipes_;
> diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp
> index aa544d7b0303..ebbd424c56ea 100644
> --- a/src/libcamera/pipeline/ipu3/cio2.cpp
> +++ b/src/libcamera/pipeline/ipu3/cio2.cpp
> @@ -112,7 +112,7 @@ std::vector<SizeRange> CIO2Device::sizes(const PixelFormat &format) const
>   * \return 0 on success or a negative error code otherwise
>   * \retval -ENODEV No supported image sensor is connected to this CIO2 instance
>   */
> -int CIO2Device::init(const MediaDevice *media, unsigned int index)
> +int CIO2Device::init(std::shared_ptr<const MediaDevice> media, unsigned int index)
>  {
>  	int ret;
>
> diff --git a/src/libcamera/pipeline/ipu3/cio2.h b/src/libcamera/pipeline/ipu3/cio2.h
> index 963c2f6b93a4..fdf85f2655f0 100644
> --- a/src/libcamera/pipeline/ipu3/cio2.h
> +++ b/src/libcamera/pipeline/ipu3/cio2.h
> @@ -38,7 +38,7 @@ public:
>  	std::vector<PixelFormat> formats() const;
>  	std::vector<SizeRange> sizes(const PixelFormat &format) const;
>
> -	int init(const MediaDevice *media, unsigned int index);
> +	int init(std::shared_ptr<const MediaDevice> media, unsigned int index);
>  	int configure(const Size &size, const Transform &transform,
>  		      V4L2DeviceFormat *outputFormat);
>
> diff --git a/src/libcamera/pipeline/ipu3/imgu.cpp b/src/libcamera/pipeline/ipu3/imgu.cpp
> index 7be780913fae..391e000f6e12 100644
> --- a/src/libcamera/pipeline/ipu3/imgu.cpp
> +++ b/src/libcamera/pipeline/ipu3/imgu.cpp
> @@ -330,7 +330,8 @@ FOV calcFOV(const Size &in, const ImgUDevice::PipeConfig &pipe)
>   *
>   * \return 0 on success or a negative error code otherwise
>   */
> -int ImgUDevice::init(MediaDevice *media, unsigned int index)
> +int ImgUDevice::init(std::shared_ptr<libcamera::MediaDevice> media,
> +		     unsigned int index)
>  {
>  	int ret;
>
> diff --git a/src/libcamera/pipeline/ipu3/imgu.h b/src/libcamera/pipeline/ipu3/imgu.h
> index fa508316b301..272f861f98c4 100644
> --- a/src/libcamera/pipeline/ipu3/imgu.h
> +++ b/src/libcamera/pipeline/ipu3/imgu.h
> @@ -64,7 +64,7 @@ public:
>  		Size viewfinder;
>  	};
>
> -	int init(MediaDevice *media, unsigned int index);
> +	int init(std::shared_ptr<MediaDevice> media, unsigned int index);
>
>  	PipeConfig calculatePipeConfig(Pipe *pipe);
>
> @@ -118,7 +118,7 @@ private:
>  				 V4L2DeviceFormat *outputFormat);
>
>  	std::string name_;
> -	MediaDevice *media_;
> +	std::shared_ptr<MediaDevice> media_;
>  };
>
>  } /* namespace libcamera */
> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> index e31e3879dcc9..17205f96446a 100644
> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> @@ -164,8 +164,8 @@ private:
>
>  	ImgUDevice imgu0_;
>  	ImgUDevice imgu1_;
> -	MediaDevice *cio2MediaDev_;
> -	MediaDevice *imguMediaDev_;
> +	std::shared_ptr<MediaDevice> cio2MediaDev_;
> +	std::shared_ptr<MediaDevice> imguMediaDev_;
>
>  	std::vector<IPABuffer> ipaBuffers_;
>  };
> diff --git a/src/libcamera/pipeline/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp
> index a05e11fccf8d..7615122d907b 100644
> --- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp
> +++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp
> @@ -684,7 +684,7 @@ private:
>  	bool registerTPGCamera(MediaLink *link);
>  	bool registerSensorCamera(MediaLink *link);
>
> -	MediaDevice *media_;
> +	std::shared_ptr<MediaDevice> media_;
>  	std::unique_ptr<V4L2Subdevice> isp_;
>  	std::unique_ptr<V4L2VideoDevice> stats_;
>  	std::unique_ptr<V4L2VideoDevice> params_;
> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> index 705615b86b0c..d4ec538f478b 100644
> --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> @@ -200,7 +200,7 @@ private:
>
>  	int updateControls(RkISP1CameraData *data);
>
> -	MediaDevice *media_;
> +	std::shared_ptr<MediaDevice> media_;
>  	std::unique_ptr<V4L2Subdevice> isp_;
>  	std::unique_ptr<V4L2VideoDevice> param_;
>  	std::unique_ptr<V4L2VideoDevice> stat_;
> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> index eee5b09e2ff0..2e567ace0b78 100644
> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> @@ -59,7 +59,7 @@ RkISP1Path::RkISP1Path(const char *name, const Span<const PixelFormat> &formats)
>  {
>  }
>
> -bool RkISP1Path::init(MediaDevice *media)
> +bool RkISP1Path::init(std::shared_ptr<MediaDevice> media)
>  {
>  	std::string resizer = std::string("rkisp1_resizer_") + name_ + "path";
>  	std::string video = std::string("rkisp1_") + name_ + "path";
> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> index 2a1ef0abe6d1..154310ac37c1 100644
> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> @@ -36,7 +36,7 @@ class RkISP1Path
>  public:
>  	RkISP1Path(const char *name, const Span<const PixelFormat> &formats);
>
> -	bool init(MediaDevice *media);
> +	bool init(std::shared_ptr<MediaDevice> media);
>
>  	int setEnabled(bool enable) { return link_->setEnabled(enable); }
>  	bool isEnabled() const { return link_->flags() & MEDIA_LNK_FL_ENABLED; }
> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> index 1f13e5230fae..23ce54eca144 100644
> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> @@ -784,8 +784,10 @@ int PipelineHandlerBase::queueRequestDevice(Camera *camera, Request *request)
>  }
>
>  int PipelineHandlerBase::registerCamera(std::unique_ptr<RPi::CameraData> &cameraData,
> -					MediaDevice *frontend, const std::string &frontendName,
> -					MediaDevice *backend, MediaEntity *sensorEntity)
> +					std::shared_ptr<MediaDevice> frontend,
> +					const std::string &frontendName,
> +					std::shared_ptr<MediaDevice> backend,
> +					MediaEntity *sensorEntity)
>  {
>  	CameraData *data = cameraData.get();
>  	int ret;
> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.h b/src/libcamera/pipeline/rpi/common/pipeline_base.h
> index aae0c2f35888..e422bbf7405f 100644
> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.h
> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.h
> @@ -229,13 +229,16 @@ public:
>
>  protected:
>  	int registerCamera(std::unique_ptr<RPi::CameraData> &cameraData,
> -			   MediaDevice *frontent, const std::string &frontendName,
> -			   MediaDevice *backend, MediaEntity *sensorEntity);
> +			   std::shared_ptr<MediaDevice> frontend,
> +			   const std::string &frontendName,
> +			   std::shared_ptr<MediaDevice> backend,
> +			   MediaEntity *sensorEntity);
>
>  	void mapBuffers(Camera *camera, const BufferMap &buffers, unsigned int mask);
>
>  	virtual int platformRegister(std::unique_ptr<CameraData> &cameraData,
> -				     MediaDevice *unicam, MediaDevice *isp) = 0;
> +				     std::shared_ptr<MediaDevice> unicam,
> +				     std::shared_ptr<MediaDevice> isp) = 0;
>
>  private:
>  	CameraData *cameraData(Camera *camera)
> diff --git a/src/libcamera/pipeline/rpi/pisp/pisp.cpp b/src/libcamera/pipeline/rpi/pisp/pisp.cpp
> index 91e7f4c94d96..d0cb71b49e11 100644
> --- a/src/libcamera/pipeline/rpi/pisp/pisp.cpp
> +++ b/src/libcamera/pipeline/rpi/pisp/pisp.cpp
> @@ -866,7 +866,8 @@ private:
>
>  	int prepareBuffers(Camera *camera) override;
>  	int platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
> -			     MediaDevice *cfe, MediaDevice *isp) override;
> +			     std::shared_ptr<MediaDevice> cfe,
> +			     std::shared_ptr<MediaDevice> isp) override;
>  };
>
>  bool PipelineHandlerPiSP::match(DeviceEnumerator *enumerator)
> @@ -884,7 +885,7 @@ bool PipelineHandlerPiSP::match(DeviceEnumerator *enumerator)
>  		cfe.add("rp1-cfe-fe-image0");
>  		cfe.add("rp1-cfe-fe-stats");
>  		cfe.add("rp1-cfe-fe-config");
> -		MediaDevice *cfeDevice = acquireMediaDevice(enumerator, cfe);
> +		std::shared_ptr<MediaDevice> cfeDevice = acquireMediaDevice(enumerator, cfe);
>
>  		if (!cfeDevice) {
>  			LOG(RPI, Debug) << "Unable to acquire a CFE instance";
> @@ -900,7 +901,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);
> +		std::shared_ptr<MediaDevice> ispDevice = acquireMediaDevice(enumerator, isp);
>
>  		if (!ispDevice) {
>  			LOG(RPI, Debug) << "Unable to acquire ISP instance";
> @@ -1065,7 +1066,8 @@ int PipelineHandlerPiSP::prepareBuffers(Camera *camera)
>  }
>
>  int PipelineHandlerPiSP::platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
> -					  MediaDevice *cfe, MediaDevice *isp)
> +					  std::shared_ptr<MediaDevice> cfe,
> +					  std::shared_ptr<MediaDevice> isp)
>  {
>  	PiSPCameraData *data = static_cast<PiSPCameraData *>(cameraData.get());
>  	int ret;
> diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> index fe910bdf2ff9..d58035ecd198 100644
> --- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> +++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> @@ -5,6 +5,8 @@
>   * Pipeline handler for VC4-based Raspberry Pi devices
>   */
>
> +#include <memory>
> +
>  #include <linux/bcm2835-isp.h>
>  #include <linux/v4l2-controls.h>
>  #include <linux/videodev2.h>
> @@ -158,7 +160,8 @@ private:
>
>  	int prepareBuffers(Camera *camera) override;
>  	int platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
> -			     MediaDevice *unicam, MediaDevice *isp) override;
> +			     std::shared_ptr<MediaDevice> unicam,
> +			     std::shared_ptr<MediaDevice> isp) override;
>  };
>
>  bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)
> @@ -173,7 +176,7 @@ bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)
>  	 */
>  	for (unsigned int i = 0; i < numUnicamDevices; i++) {
>  		DeviceMatch unicam("unicam");
> -		MediaDevice *unicamDevice = acquireMediaDevice(enumerator, unicam);
> +		std::shared_ptr<MediaDevice> unicamDevice = acquireMediaDevice(enumerator, unicam);
>
>  		if (!unicamDevice) {
>  			LOG(RPI, Debug) << "Unable to acquire a Unicam instance";
> @@ -181,7 +184,7 @@ bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)
>  		}
>
>  		DeviceMatch isp("bcm2835-isp");
> -		MediaDevice *ispDevice = acquireMediaDevice(enumerator, isp);
> +		std::shared_ptr<MediaDevice> ispDevice = acquireMediaDevice(enumerator, isp);
>
>  		if (!ispDevice) {
>  			LOG(RPI, Debug) << "Unable to acquire ISP instance";
> @@ -303,7 +306,9 @@ int PipelineHandlerVc4::prepareBuffers(Camera *camera)
>  	return 0;
>  }
>
> -int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &cameraData, MediaDevice *unicam, MediaDevice *isp)
> +int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
> +					 std::shared_ptr<MediaDevice> unicam,
> +					 std::shared_ptr<MediaDevice> isp)
>  {
>  	Vc4CameraData *data = static_cast<Vc4CameraData *>(cameraData.get());
>
> diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
> index 451491f5608e..feaa16094b65 100644
> --- a/src/libcamera/pipeline/simple/simple.cpp
> +++ b/src/libcamera/pipeline/simple/simple.cpp
> @@ -407,7 +407,7 @@ public:
>
>  	V4L2VideoDevice *video(const MediaEntity *entity);
>  	V4L2Subdevice *subdev(const MediaEntity *entity);
> -	MediaDevice *converter() { return converter_; }
> +	MediaDevice *converter() { return converter_.get(); }
>  	bool swIspEnabled() const { return swIspEnabled_; }
>
>  protected:
> @@ -427,7 +427,8 @@ private:
>  		return static_cast<SimpleCameraData *>(camera->_d());
>  	}
>
> -	bool matchDevice(MediaDevice *media, const SimplePipelineInfo &info,
> +	bool matchDevice(std::shared_ptr<MediaDevice> media,
> +			 const SimplePipelineInfo &info,
>  			 DeviceEnumerator *enumerator);
>
>  	std::vector<MediaEntity *> locateSensors(MediaDevice *media);
> @@ -438,7 +439,7 @@ private:
>
>  	std::map<const MediaEntity *, EntityData> entities_;
>
> -	MediaDevice *converter_;
> +	std::shared_ptr<MediaDevice> converter_;
>  	bool swIspEnabled_;
>  };
>
> @@ -1663,7 +1664,7 @@ int SimplePipelineHandler::resetRoutingTable(V4L2Subdevice *subdev)
>  	return 0;
>  }
>
> -bool SimplePipelineHandler::matchDevice(MediaDevice *media,
> +bool SimplePipelineHandler::matchDevice(std::shared_ptr<MediaDevice> media,
>  					const SimplePipelineInfo &info,
>  					DeviceEnumerator *enumerator)
>  {
> @@ -1681,7 +1682,7 @@ bool SimplePipelineHandler::matchDevice(MediaDevice *media,
>  	swIspEnabled_ = info.swIspEnabled;
>
>  	/* Locate the sensors. */
> -	std::vector<MediaEntity *> sensors = locateSensors(media);
> +	std::vector<MediaEntity *> sensors = locateSensors(media.get());
>  	if (sensors.empty()) {
>  		LOG(SimplePipeline, Info) << "No sensor found for " << media->deviceNode();
>  		return false;
> @@ -1799,7 +1800,7 @@ bool SimplePipelineHandler::matchDevice(MediaDevice *media,
>
>  bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
>  {
> -	MediaDevice *media;
> +	std::shared_ptr<MediaDevice> media;
>
>  	for (const SimplePipelineInfo &inf : supportedDevices) {
>  		DeviceMatch dm(inf.driver);
> diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> index 5adc89fdb29c..a1e036a32d5f 100644
> --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> @@ -46,7 +46,7 @@ public:
>  	{
>  	}
>
> -	int init(MediaDevice *media);
> +	int init(std::shared_ptr<MediaDevice> media);
>  	void addControl(uint32_t cid, const ControlInfo &v4l2info,
>  			ControlInfoMap::Map *ctrls);
>  	void imageBufferReady(FrameBuffer *buffer);
> @@ -449,7 +449,7 @@ int PipelineHandlerUVC::queueRequestDevice(Camera *camera, Request *request)
>
>  bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
>  {
> -	MediaDevice *media;
> +	std::shared_ptr<MediaDevice> media;
>  	DeviceMatch dm("uvcvideo");
>
>  	media = acquireMediaDevice(enumerator, dm);
> @@ -491,7 +491,7 @@ void PipelineHandlerUVC::releaseDevice(Camera *camera)
>  	data->video_->close();
>  }
>
> -int UVCCameraData::init(MediaDevice *media)
> +int UVCCameraData::init(std::shared_ptr<MediaDevice> media)
>  {
>  	int ret;
>
> diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp
> index 07273bd2b6c3..59c564b8a9f6 100644
> --- a/src/libcamera/pipeline/vimc/vimc.cpp
> +++ b/src/libcamera/pipeline/vimc/vimc.cpp
> @@ -49,7 +49,7 @@ LOG_DEFINE_CATEGORY(VIMC)
>  class VimcCameraData : public Camera::Private
>  {
>  public:
> -	VimcCameraData(PipelineHandler *pipe, MediaDevice *media)
> +	VimcCameraData(PipelineHandler *pipe, std::shared_ptr<MediaDevice> media)
>  		: Camera::Private(pipe), media_(media)
>  	{
>  	}
> @@ -59,7 +59,7 @@ public:
>  	void imageBufferReady(FrameBuffer *buffer);
>  	void paramsComputed(unsigned int id, const Flags<ipa::vimc::TestFlag> flags);
>
> -	MediaDevice *media_;
> +	std::shared_ptr<MediaDevice> media_;
>  	std::unique_ptr<CameraSensor> sensor_;
>  	std::unique_ptr<V4L2Subdevice> debayer_;
>  	std::unique_ptr<V4L2Subdevice> scaler_;
> @@ -476,7 +476,7 @@ bool PipelineHandlerVimc::match(DeviceEnumerator *enumerator)
>  	dm.add("RGB/YUV Input");
>  	dm.add("Scaler");
>
> -	MediaDevice *media = acquireMediaDevice(enumerator, dm);
> +	std::shared_ptr<MediaDevice> media = acquireMediaDevice(enumerator, dm);
>  	if (!media)
>  		return false;
>
> diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
> index 8f12957b75fa..5fe2c64c8bc6 100644
> --- a/src/libcamera/pipeline_handler.cpp
> +++ b/src/libcamera/pipeline_handler.cpp
> @@ -125,10 +125,12 @@ PipelineHandler::~PipelineHandler()
>   *
>   * \context This function shall be called from the CameraManager thread.
>   *
> - * \return A pointer to the matching MediaDevice, or nullptr if no match is found
> + * \return A shared pointer to the matching MediaDevice, or nullptr if no match
> + * is found
>   */
> -MediaDevice *PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
> -						 const DeviceMatch &dm)
> +std::shared_ptr<MediaDevice>
> +PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
> +				    const DeviceMatch &dm)
>  {
>  	std::shared_ptr<MediaDevice> media = enumerator->search(dm);
>  	if (!media)
> @@ -139,7 +141,7 @@ MediaDevice *PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
>
>  	mediaDevices_.push_back(media);
>
> -	return media.get();
> +	return media;
>  }
>
>  /**
> @@ -712,7 +714,7 @@ void PipelineHandler::registerCamera(std::shared_ptr<Camera> camera)
>   * handler gets notified and automatically disconnects all the cameras it has
>   * registered without requiring any manual intervention.
>   */
> -void PipelineHandler::hotplugMediaDevice(MediaDevice *media)
> +void PipelineHandler::hotplugMediaDevice(std::shared_ptr<MediaDevice> media)
>  {
>  	media->disconnected.connect(this, [this, media] { mediaDeviceDisconnected(media); });
>  }
> @@ -720,7 +722,7 @@ void PipelineHandler::hotplugMediaDevice(MediaDevice *media)
>  /**
>   * \brief Slot for the MediaDevice disconnected signal
>   */
> -void PipelineHandler::mediaDeviceDisconnected(MediaDevice *media)
> +void PipelineHandler::mediaDeviceDisconnected(std::shared_ptr<MediaDevice> media)
>  {
>  	media->disconnected.disconnect(this);
>
> diff --git a/test/delayed_controls.cpp b/test/delayed_controls.cpp
> index 7bd30e7aead8..b305be48aafc 100644
> --- a/test/delayed_controls.cpp
> +++ b/test/delayed_controls.cpp
> @@ -47,7 +47,7 @@ protected:
>  			return TestSkip;
>  		}
>
> -		dev_ = V4L2VideoDevice::fromEntityName(media_.get(), "vivid-000-vid-cap");
> +		dev_ = V4L2VideoDevice::fromEntityName(media_, "vivid-000-vid-cap");
>  		if (dev_->open()) {
>  			cerr << "Failed to open video device" << endl;
>  			return TestFail;
> diff --git a/test/libtest/buffer_source.cpp b/test/libtest/buffer_source.cpp
> index dde11f365e43..19b25fed50a0 100644
> --- a/test/libtest/buffer_source.cpp
> +++ b/test/libtest/buffer_source.cpp
> @@ -52,7 +52,7 @@ int BufferSource::allocate(const StreamConfiguration &config)
>  		return TestSkip;
>  	}
>
> -	std::unique_ptr<V4L2VideoDevice> video = V4L2VideoDevice::fromEntityName(media_.get(), videoDeviceName);
> +	std::unique_ptr<V4L2VideoDevice> video = V4L2VideoDevice::fromEntityName(media_, videoDeviceName);
>  	if (!video) {
>  		std::cout << "Failed to get video device from entity "
>  			  << videoDeviceName << std::endl;
> --
> 2.47.2
>
Laurent Pinchart April 6, 2025, 6:16 p.m. UTC | #2
On Sun, Apr 06, 2025 at 06:53:34PM +0200, Jacopo Mondi wrote:
> On Fri, Apr 04, 2025 at 04:46:22PM +0900, Paul Elder wrote:
> > From: Kieran Bingham <kieran.bingham@ideasonboard.com>
> >
> > Adapt the PipelineHandler::acquireMediaDevice() support function to
> > return a shared pointer instead of the underlying raw pointer.
> 
> It seems nice, but I wonder if it really is better ? The
> PipelineHandler base class already stores a shared_ptr<> instance for
> each acquired media device. Is passing it around by value and storing
> a copy as classes member in derived classes worth it ?
> 
> Or is this about an ownership issue I am missing ?

I'm also wondering the same. Paul, could you explain the rationale for
this patch series ?

> > Propagate this update to all pipeline handlers that use the MediaDevice
> > and store a std::shared_ptr<MediaDevice> accordingly.
> >
> > Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
> > ---
> >  include/libcamera/internal/pipeline_handler.h      |  8 ++++----
> >  src/libcamera/pipeline/imx8-isi/imx8-isi.cpp       |  2 +-
> >  src/libcamera/pipeline/ipu3/cio2.cpp               |  2 +-
> >  src/libcamera/pipeline/ipu3/cio2.h                 |  2 +-
> >  src/libcamera/pipeline/ipu3/imgu.cpp               |  3 ++-
> >  src/libcamera/pipeline/ipu3/imgu.h                 |  4 ++--
> >  src/libcamera/pipeline/ipu3/ipu3.cpp               |  4 ++--
> >  src/libcamera/pipeline/mali-c55/mali-c55.cpp       |  2 +-
> >  src/libcamera/pipeline/rkisp1/rkisp1.cpp           |  2 +-
> >  src/libcamera/pipeline/rkisp1/rkisp1_path.cpp      |  2 +-
> >  src/libcamera/pipeline/rkisp1/rkisp1_path.h        |  2 +-
> >  .../pipeline/rpi/common/pipeline_base.cpp          |  6 ++++--
> >  src/libcamera/pipeline/rpi/common/pipeline_base.h  |  9 ++++++---
> >  src/libcamera/pipeline/rpi/pisp/pisp.cpp           | 10 ++++++----
> >  src/libcamera/pipeline/rpi/vc4/vc4.cpp             | 13 +++++++++----
> >  src/libcamera/pipeline/simple/simple.cpp           | 13 +++++++------
> >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp       |  6 +++---
> >  src/libcamera/pipeline/vimc/vimc.cpp               |  6 +++---
> >  src/libcamera/pipeline_handler.cpp                 | 14 ++++++++------
> >  test/delayed_controls.cpp                          |  2 +-
> >  test/libtest/buffer_source.cpp                     |  2 +-
> >  21 files changed, 65 insertions(+), 49 deletions(-)
> >
> > diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h
> > index 5fa8bc2f66ee..0199ab7911c0 100644
> > --- a/include/libcamera/internal/pipeline_handler.h
> > +++ b/include/libcamera/internal/pipeline_handler.h
> > @@ -38,8 +38,8 @@ public:
> >  	virtual ~PipelineHandler();
> >
> >  	virtual bool match(DeviceEnumerator *enumerator) = 0;
> > -	MediaDevice *acquireMediaDevice(DeviceEnumerator *enumerator,
> > -					const DeviceMatch &dm);
> > +	std::shared_ptr<MediaDevice> acquireMediaDevice(DeviceEnumerator *enumerator,
> > +							const DeviceMatch &dm);
> >
> >  	bool acquire(Camera *camera);
> >  	void release(Camera *camera);
> > @@ -74,7 +74,7 @@ protected:
> >  	void clearMediaDevices();
> >
> >  	void registerCamera(std::shared_ptr<Camera> camera);
> > -	void hotplugMediaDevice(MediaDevice *media);
> > +	void hotplugMediaDevice(std::shared_ptr<MediaDevice> media);
> >
> >  	virtual int queueRequestDevice(Camera *camera, Request *request) = 0;
> >  	virtual void stopDevice(Camera *camera) = 0;
> > @@ -87,7 +87,7 @@ protected:
> >  private:
> >  	void unlockMediaDevices();
> >
> > -	void mediaDeviceDisconnected(MediaDevice *media);
> > +	void mediaDeviceDisconnected(std::shared_ptr<MediaDevice> media);
> >  	virtual void disconnect();
> >
> >  	void doQueueRequest(Request *request);
> > diff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
> > index 4e66b3368d5a..850dbfcdc64b 100644
> > --- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
> > +++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
> > @@ -139,7 +139,7 @@ private:
> >
> >  	void bufferReady(FrameBuffer *buffer);
> >
> > -	MediaDevice *isiDev_;
> > +	std::shared_ptr<MediaDevice> isiDev_;
> >
> >  	std::unique_ptr<V4L2Subdevice> crossbar_;
> >  	std::vector<Pipe> pipes_;
> > diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp
> > index aa544d7b0303..ebbd424c56ea 100644
> > --- a/src/libcamera/pipeline/ipu3/cio2.cpp
> > +++ b/src/libcamera/pipeline/ipu3/cio2.cpp
> > @@ -112,7 +112,7 @@ std::vector<SizeRange> CIO2Device::sizes(const PixelFormat &format) const
> >   * \return 0 on success or a negative error code otherwise
> >   * \retval -ENODEV No supported image sensor is connected to this CIO2 instance
> >   */
> > -int CIO2Device::init(const MediaDevice *media, unsigned int index)
> > +int CIO2Device::init(std::shared_ptr<const MediaDevice> media, unsigned int index)
> >  {
> >  	int ret;
> >
> > diff --git a/src/libcamera/pipeline/ipu3/cio2.h b/src/libcamera/pipeline/ipu3/cio2.h
> > index 963c2f6b93a4..fdf85f2655f0 100644
> > --- a/src/libcamera/pipeline/ipu3/cio2.h
> > +++ b/src/libcamera/pipeline/ipu3/cio2.h
> > @@ -38,7 +38,7 @@ public:
> >  	std::vector<PixelFormat> formats() const;
> >  	std::vector<SizeRange> sizes(const PixelFormat &format) const;
> >
> > -	int init(const MediaDevice *media, unsigned int index);
> > +	int init(std::shared_ptr<const MediaDevice> media, unsigned int index);
> >  	int configure(const Size &size, const Transform &transform,
> >  		      V4L2DeviceFormat *outputFormat);
> >
> > diff --git a/src/libcamera/pipeline/ipu3/imgu.cpp b/src/libcamera/pipeline/ipu3/imgu.cpp
> > index 7be780913fae..391e000f6e12 100644
> > --- a/src/libcamera/pipeline/ipu3/imgu.cpp
> > +++ b/src/libcamera/pipeline/ipu3/imgu.cpp
> > @@ -330,7 +330,8 @@ FOV calcFOV(const Size &in, const ImgUDevice::PipeConfig &pipe)
> >   *
> >   * \return 0 on success or a negative error code otherwise
> >   */
> > -int ImgUDevice::init(MediaDevice *media, unsigned int index)
> > +int ImgUDevice::init(std::shared_ptr<libcamera::MediaDevice> media,
> > +		     unsigned int index)
> >  {
> >  	int ret;
> >
> > diff --git a/src/libcamera/pipeline/ipu3/imgu.h b/src/libcamera/pipeline/ipu3/imgu.h
> > index fa508316b301..272f861f98c4 100644
> > --- a/src/libcamera/pipeline/ipu3/imgu.h
> > +++ b/src/libcamera/pipeline/ipu3/imgu.h
> > @@ -64,7 +64,7 @@ public:
> >  		Size viewfinder;
> >  	};
> >
> > -	int init(MediaDevice *media, unsigned int index);
> > +	int init(std::shared_ptr<MediaDevice> media, unsigned int index);
> >
> >  	PipeConfig calculatePipeConfig(Pipe *pipe);
> >
> > @@ -118,7 +118,7 @@ private:
> >  				 V4L2DeviceFormat *outputFormat);
> >
> >  	std::string name_;
> > -	MediaDevice *media_;
> > +	std::shared_ptr<MediaDevice> media_;
> >  };
> >
> >  } /* namespace libcamera */
> > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> > index e31e3879dcc9..17205f96446a 100644
> > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> > @@ -164,8 +164,8 @@ private:
> >
> >  	ImgUDevice imgu0_;
> >  	ImgUDevice imgu1_;
> > -	MediaDevice *cio2MediaDev_;
> > -	MediaDevice *imguMediaDev_;
> > +	std::shared_ptr<MediaDevice> cio2MediaDev_;
> > +	std::shared_ptr<MediaDevice> imguMediaDev_;
> >
> >  	std::vector<IPABuffer> ipaBuffers_;
> >  };
> > diff --git a/src/libcamera/pipeline/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp
> > index a05e11fccf8d..7615122d907b 100644
> > --- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp
> > +++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp
> > @@ -684,7 +684,7 @@ private:
> >  	bool registerTPGCamera(MediaLink *link);
> >  	bool registerSensorCamera(MediaLink *link);
> >
> > -	MediaDevice *media_;
> > +	std::shared_ptr<MediaDevice> media_;
> >  	std::unique_ptr<V4L2Subdevice> isp_;
> >  	std::unique_ptr<V4L2VideoDevice> stats_;
> >  	std::unique_ptr<V4L2VideoDevice> params_;
> > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> > index 705615b86b0c..d4ec538f478b 100644
> > --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> > +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> > @@ -200,7 +200,7 @@ private:
> >
> >  	int updateControls(RkISP1CameraData *data);
> >
> > -	MediaDevice *media_;
> > +	std::shared_ptr<MediaDevice> media_;
> >  	std::unique_ptr<V4L2Subdevice> isp_;
> >  	std::unique_ptr<V4L2VideoDevice> param_;
> >  	std::unique_ptr<V4L2VideoDevice> stat_;
> > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> > index eee5b09e2ff0..2e567ace0b78 100644
> > --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> > +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> > @@ -59,7 +59,7 @@ RkISP1Path::RkISP1Path(const char *name, const Span<const PixelFormat> &formats)
> >  {
> >  }
> >
> > -bool RkISP1Path::init(MediaDevice *media)
> > +bool RkISP1Path::init(std::shared_ptr<MediaDevice> media)
> >  {
> >  	std::string resizer = std::string("rkisp1_resizer_") + name_ + "path";
> >  	std::string video = std::string("rkisp1_") + name_ + "path";
> > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> > index 2a1ef0abe6d1..154310ac37c1 100644
> > --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> > +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> > @@ -36,7 +36,7 @@ class RkISP1Path
> >  public:
> >  	RkISP1Path(const char *name, const Span<const PixelFormat> &formats);
> >
> > -	bool init(MediaDevice *media);
> > +	bool init(std::shared_ptr<MediaDevice> media);
> >
> >  	int setEnabled(bool enable) { return link_->setEnabled(enable); }
> >  	bool isEnabled() const { return link_->flags() & MEDIA_LNK_FL_ENABLED; }
> > diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> > index 1f13e5230fae..23ce54eca144 100644
> > --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> > +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> > @@ -784,8 +784,10 @@ int PipelineHandlerBase::queueRequestDevice(Camera *camera, Request *request)
> >  }
> >
> >  int PipelineHandlerBase::registerCamera(std::unique_ptr<RPi::CameraData> &cameraData,
> > -					MediaDevice *frontend, const std::string &frontendName,
> > -					MediaDevice *backend, MediaEntity *sensorEntity)
> > +					std::shared_ptr<MediaDevice> frontend,
> > +					const std::string &frontendName,
> > +					std::shared_ptr<MediaDevice> backend,
> > +					MediaEntity *sensorEntity)
> >  {
> >  	CameraData *data = cameraData.get();
> >  	int ret;
> > diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.h b/src/libcamera/pipeline/rpi/common/pipeline_base.h
> > index aae0c2f35888..e422bbf7405f 100644
> > --- a/src/libcamera/pipeline/rpi/common/pipeline_base.h
> > +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.h
> > @@ -229,13 +229,16 @@ public:
> >
> >  protected:
> >  	int registerCamera(std::unique_ptr<RPi::CameraData> &cameraData,
> > -			   MediaDevice *frontent, const std::string &frontendName,
> > -			   MediaDevice *backend, MediaEntity *sensorEntity);
> > +			   std::shared_ptr<MediaDevice> frontend,
> > +			   const std::string &frontendName,
> > +			   std::shared_ptr<MediaDevice> backend,
> > +			   MediaEntity *sensorEntity);
> >
> >  	void mapBuffers(Camera *camera, const BufferMap &buffers, unsigned int mask);
> >
> >  	virtual int platformRegister(std::unique_ptr<CameraData> &cameraData,
> > -				     MediaDevice *unicam, MediaDevice *isp) = 0;
> > +				     std::shared_ptr<MediaDevice> unicam,
> > +				     std::shared_ptr<MediaDevice> isp) = 0;
> >
> >  private:
> >  	CameraData *cameraData(Camera *camera)
> > diff --git a/src/libcamera/pipeline/rpi/pisp/pisp.cpp b/src/libcamera/pipeline/rpi/pisp/pisp.cpp
> > index 91e7f4c94d96..d0cb71b49e11 100644
> > --- a/src/libcamera/pipeline/rpi/pisp/pisp.cpp
> > +++ b/src/libcamera/pipeline/rpi/pisp/pisp.cpp
> > @@ -866,7 +866,8 @@ private:
> >
> >  	int prepareBuffers(Camera *camera) override;
> >  	int platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
> > -			     MediaDevice *cfe, MediaDevice *isp) override;
> > +			     std::shared_ptr<MediaDevice> cfe,
> > +			     std::shared_ptr<MediaDevice> isp) override;
> >  };
> >
> >  bool PipelineHandlerPiSP::match(DeviceEnumerator *enumerator)
> > @@ -884,7 +885,7 @@ bool PipelineHandlerPiSP::match(DeviceEnumerator *enumerator)
> >  		cfe.add("rp1-cfe-fe-image0");
> >  		cfe.add("rp1-cfe-fe-stats");
> >  		cfe.add("rp1-cfe-fe-config");
> > -		MediaDevice *cfeDevice = acquireMediaDevice(enumerator, cfe);
> > +		std::shared_ptr<MediaDevice> cfeDevice = acquireMediaDevice(enumerator, cfe);
> >
> >  		if (!cfeDevice) {
> >  			LOG(RPI, Debug) << "Unable to acquire a CFE instance";
> > @@ -900,7 +901,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);
> > +		std::shared_ptr<MediaDevice> ispDevice = acquireMediaDevice(enumerator, isp);
> >
> >  		if (!ispDevice) {
> >  			LOG(RPI, Debug) << "Unable to acquire ISP instance";
> > @@ -1065,7 +1066,8 @@ int PipelineHandlerPiSP::prepareBuffers(Camera *camera)
> >  }
> >
> >  int PipelineHandlerPiSP::platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
> > -					  MediaDevice *cfe, MediaDevice *isp)
> > +					  std::shared_ptr<MediaDevice> cfe,
> > +					  std::shared_ptr<MediaDevice> isp)
> >  {
> >  	PiSPCameraData *data = static_cast<PiSPCameraData *>(cameraData.get());
> >  	int ret;
> > diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> > index fe910bdf2ff9..d58035ecd198 100644
> > --- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> > +++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> > @@ -5,6 +5,8 @@
> >   * Pipeline handler for VC4-based Raspberry Pi devices
> >   */
> >
> > +#include <memory>
> > +
> >  #include <linux/bcm2835-isp.h>
> >  #include <linux/v4l2-controls.h>
> >  #include <linux/videodev2.h>
> > @@ -158,7 +160,8 @@ private:
> >
> >  	int prepareBuffers(Camera *camera) override;
> >  	int platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
> > -			     MediaDevice *unicam, MediaDevice *isp) override;
> > +			     std::shared_ptr<MediaDevice> unicam,
> > +			     std::shared_ptr<MediaDevice> isp) override;
> >  };
> >
> >  bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)
> > @@ -173,7 +176,7 @@ bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)
> >  	 */
> >  	for (unsigned int i = 0; i < numUnicamDevices; i++) {
> >  		DeviceMatch unicam("unicam");
> > -		MediaDevice *unicamDevice = acquireMediaDevice(enumerator, unicam);
> > +		std::shared_ptr<MediaDevice> unicamDevice = acquireMediaDevice(enumerator, unicam);
> >
> >  		if (!unicamDevice) {
> >  			LOG(RPI, Debug) << "Unable to acquire a Unicam instance";
> > @@ -181,7 +184,7 @@ bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)
> >  		}
> >
> >  		DeviceMatch isp("bcm2835-isp");
> > -		MediaDevice *ispDevice = acquireMediaDevice(enumerator, isp);
> > +		std::shared_ptr<MediaDevice> ispDevice = acquireMediaDevice(enumerator, isp);
> >
> >  		if (!ispDevice) {
> >  			LOG(RPI, Debug) << "Unable to acquire ISP instance";
> > @@ -303,7 +306,9 @@ int PipelineHandlerVc4::prepareBuffers(Camera *camera)
> >  	return 0;
> >  }
> >
> > -int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &cameraData, MediaDevice *unicam, MediaDevice *isp)
> > +int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
> > +					 std::shared_ptr<MediaDevice> unicam,
> > +					 std::shared_ptr<MediaDevice> isp)
> >  {
> >  	Vc4CameraData *data = static_cast<Vc4CameraData *>(cameraData.get());
> >
> > diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
> > index 451491f5608e..feaa16094b65 100644
> > --- a/src/libcamera/pipeline/simple/simple.cpp
> > +++ b/src/libcamera/pipeline/simple/simple.cpp
> > @@ -407,7 +407,7 @@ public:
> >
> >  	V4L2VideoDevice *video(const MediaEntity *entity);
> >  	V4L2Subdevice *subdev(const MediaEntity *entity);
> > -	MediaDevice *converter() { return converter_; }
> > +	MediaDevice *converter() { return converter_.get(); }
> >  	bool swIspEnabled() const { return swIspEnabled_; }
> >
> >  protected:
> > @@ -427,7 +427,8 @@ private:
> >  		return static_cast<SimpleCameraData *>(camera->_d());
> >  	}
> >
> > -	bool matchDevice(MediaDevice *media, const SimplePipelineInfo &info,
> > +	bool matchDevice(std::shared_ptr<MediaDevice> media,
> > +			 const SimplePipelineInfo &info,
> >  			 DeviceEnumerator *enumerator);
> >
> >  	std::vector<MediaEntity *> locateSensors(MediaDevice *media);
> > @@ -438,7 +439,7 @@ private:
> >
> >  	std::map<const MediaEntity *, EntityData> entities_;
> >
> > -	MediaDevice *converter_;
> > +	std::shared_ptr<MediaDevice> converter_;
> >  	bool swIspEnabled_;
> >  };
> >
> > @@ -1663,7 +1664,7 @@ int SimplePipelineHandler::resetRoutingTable(V4L2Subdevice *subdev)
> >  	return 0;
> >  }
> >
> > -bool SimplePipelineHandler::matchDevice(MediaDevice *media,
> > +bool SimplePipelineHandler::matchDevice(std::shared_ptr<MediaDevice> media,
> >  					const SimplePipelineInfo &info,
> >  					DeviceEnumerator *enumerator)
> >  {
> > @@ -1681,7 +1682,7 @@ bool SimplePipelineHandler::matchDevice(MediaDevice *media,
> >  	swIspEnabled_ = info.swIspEnabled;
> >
> >  	/* Locate the sensors. */
> > -	std::vector<MediaEntity *> sensors = locateSensors(media);
> > +	std::vector<MediaEntity *> sensors = locateSensors(media.get());
> >  	if (sensors.empty()) {
> >  		LOG(SimplePipeline, Info) << "No sensor found for " << media->deviceNode();
> >  		return false;
> > @@ -1799,7 +1800,7 @@ bool SimplePipelineHandler::matchDevice(MediaDevice *media,
> >
> >  bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
> >  {
> > -	MediaDevice *media;
> > +	std::shared_ptr<MediaDevice> media;
> >
> >  	for (const SimplePipelineInfo &inf : supportedDevices) {
> >  		DeviceMatch dm(inf.driver);
> > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > index 5adc89fdb29c..a1e036a32d5f 100644
> > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > @@ -46,7 +46,7 @@ public:
> >  	{
> >  	}
> >
> > -	int init(MediaDevice *media);
> > +	int init(std::shared_ptr<MediaDevice> media);
> >  	void addControl(uint32_t cid, const ControlInfo &v4l2info,
> >  			ControlInfoMap::Map *ctrls);
> >  	void imageBufferReady(FrameBuffer *buffer);
> > @@ -449,7 +449,7 @@ int PipelineHandlerUVC::queueRequestDevice(Camera *camera, Request *request)
> >
> >  bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
> >  {
> > -	MediaDevice *media;
> > +	std::shared_ptr<MediaDevice> media;
> >  	DeviceMatch dm("uvcvideo");
> >
> >  	media = acquireMediaDevice(enumerator, dm);
> > @@ -491,7 +491,7 @@ void PipelineHandlerUVC::releaseDevice(Camera *camera)
> >  	data->video_->close();
> >  }
> >
> > -int UVCCameraData::init(MediaDevice *media)
> > +int UVCCameraData::init(std::shared_ptr<MediaDevice> media)
> >  {
> >  	int ret;
> >
> > diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp
> > index 07273bd2b6c3..59c564b8a9f6 100644
> > --- a/src/libcamera/pipeline/vimc/vimc.cpp
> > +++ b/src/libcamera/pipeline/vimc/vimc.cpp
> > @@ -49,7 +49,7 @@ LOG_DEFINE_CATEGORY(VIMC)
> >  class VimcCameraData : public Camera::Private
> >  {
> >  public:
> > -	VimcCameraData(PipelineHandler *pipe, MediaDevice *media)
> > +	VimcCameraData(PipelineHandler *pipe, std::shared_ptr<MediaDevice> media)
> >  		: Camera::Private(pipe), media_(media)
> >  	{
> >  	}
> > @@ -59,7 +59,7 @@ public:
> >  	void imageBufferReady(FrameBuffer *buffer);
> >  	void paramsComputed(unsigned int id, const Flags<ipa::vimc::TestFlag> flags);
> >
> > -	MediaDevice *media_;
> > +	std::shared_ptr<MediaDevice> media_;
> >  	std::unique_ptr<CameraSensor> sensor_;
> >  	std::unique_ptr<V4L2Subdevice> debayer_;
> >  	std::unique_ptr<V4L2Subdevice> scaler_;
> > @@ -476,7 +476,7 @@ bool PipelineHandlerVimc::match(DeviceEnumerator *enumerator)
> >  	dm.add("RGB/YUV Input");
> >  	dm.add("Scaler");
> >
> > -	MediaDevice *media = acquireMediaDevice(enumerator, dm);
> > +	std::shared_ptr<MediaDevice> media = acquireMediaDevice(enumerator, dm);
> >  	if (!media)
> >  		return false;
> >
> > diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
> > index 8f12957b75fa..5fe2c64c8bc6 100644
> > --- a/src/libcamera/pipeline_handler.cpp
> > +++ b/src/libcamera/pipeline_handler.cpp
> > @@ -125,10 +125,12 @@ PipelineHandler::~PipelineHandler()
> >   *
> >   * \context This function shall be called from the CameraManager thread.
> >   *
> > - * \return A pointer to the matching MediaDevice, or nullptr if no match is found
> > + * \return A shared pointer to the matching MediaDevice, or nullptr if no match
> > + * is found
> >   */
> > -MediaDevice *PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
> > -						 const DeviceMatch &dm)
> > +std::shared_ptr<MediaDevice>
> > +PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
> > +				    const DeviceMatch &dm)
> >  {
> >  	std::shared_ptr<MediaDevice> media = enumerator->search(dm);
> >  	if (!media)
> > @@ -139,7 +141,7 @@ MediaDevice *PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
> >
> >  	mediaDevices_.push_back(media);
> >
> > -	return media.get();
> > +	return media;
> >  }
> >
> >  /**
> > @@ -712,7 +714,7 @@ void PipelineHandler::registerCamera(std::shared_ptr<Camera> camera)
> >   * handler gets notified and automatically disconnects all the cameras it has
> >   * registered without requiring any manual intervention.
> >   */
> > -void PipelineHandler::hotplugMediaDevice(MediaDevice *media)
> > +void PipelineHandler::hotplugMediaDevice(std::shared_ptr<MediaDevice> media)
> >  {
> >  	media->disconnected.connect(this, [this, media] { mediaDeviceDisconnected(media); });
> >  }
> > @@ -720,7 +722,7 @@ void PipelineHandler::hotplugMediaDevice(MediaDevice *media)
> >  /**
> >   * \brief Slot for the MediaDevice disconnected signal
> >   */
> > -void PipelineHandler::mediaDeviceDisconnected(MediaDevice *media)
> > +void PipelineHandler::mediaDeviceDisconnected(std::shared_ptr<MediaDevice> media)
> >  {
> >  	media->disconnected.disconnect(this);
> >
> > diff --git a/test/delayed_controls.cpp b/test/delayed_controls.cpp
> > index 7bd30e7aead8..b305be48aafc 100644
> > --- a/test/delayed_controls.cpp
> > +++ b/test/delayed_controls.cpp
> > @@ -47,7 +47,7 @@ protected:
> >  			return TestSkip;
> >  		}
> >
> > -		dev_ = V4L2VideoDevice::fromEntityName(media_.get(), "vivid-000-vid-cap");
> > +		dev_ = V4L2VideoDevice::fromEntityName(media_, "vivid-000-vid-cap");
> >  		if (dev_->open()) {
> >  			cerr << "Failed to open video device" << endl;
> >  			return TestFail;
> > diff --git a/test/libtest/buffer_source.cpp b/test/libtest/buffer_source.cpp
> > index dde11f365e43..19b25fed50a0 100644
> > --- a/test/libtest/buffer_source.cpp
> > +++ b/test/libtest/buffer_source.cpp
> > @@ -52,7 +52,7 @@ int BufferSource::allocate(const StreamConfiguration &config)
> >  		return TestSkip;
> >  	}
> >
> > -	std::unique_ptr<V4L2VideoDevice> video = V4L2VideoDevice::fromEntityName(media_.get(), videoDeviceName);
> > +	std::unique_ptr<V4L2VideoDevice> video = V4L2VideoDevice::fromEntityName(media_, videoDeviceName);
> >  	if (!video) {
> >  		std::cout << "Failed to get video device from entity "
> >  			  << videoDeviceName << std::endl;
Paul Elder April 22, 2025, 9:39 a.m. UTC | #3
Hi Jacopo and Laurent,

On Sun, Apr 06, 2025 at 09:16:29PM +0300, Laurent Pinchart wrote:
> On Sun, Apr 06, 2025 at 06:53:34PM +0200, Jacopo Mondi wrote:
> > On Fri, Apr 04, 2025 at 04:46:22PM +0900, Paul Elder wrote:
> > > From: Kieran Bingham <kieran.bingham@ideasonboard.com>
> > >
> > > Adapt the PipelineHandler::acquireMediaDevice() support function to
> > > return a shared pointer instead of the underlying raw pointer.
> > 
> > It seems nice, but I wonder if it really is better ? The
> > PipelineHandler base class already stores a shared_ptr<> instance for
> > each acquired media device. Is passing it around by value and storing
> > a copy as classes member in derived classes worth it ?
> > 
> > Or is this about an ownership issue I am missing ?
> 
> I'm also wondering the same. Paul, could you explain the rationale for
> this patch series ?

I thought I did in the cover letter... oh that's really short huh...

We had a platform with a really complex media graph that could be
summarized as a simple pipeline and an rkisp1 pipeline combined via a
mux in between the sensors and the CSI receivers. The correct long-term
solution is modular pipeline handlers, but since we're not there yet we
settled with creating a simple pipeline handler inside the rkisp1
pipeline handler.

To prevent both pipeline handlers from trying to acquire the media
devices that are shared between the two paths, it was better to change
ownership of the media devices to shared so that we could register the
media devices in the second pipeline handler without having to
re-acquire and manage the lifetime.

It seemed useful to upstream at least this portion.


Paul

> > > Propagate this update to all pipeline handlers that use the MediaDevice
> > > and store a std::shared_ptr<MediaDevice> accordingly.
> > >
> > > Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> > > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
> > > ---
> > >  include/libcamera/internal/pipeline_handler.h      |  8 ++++----
> > >  src/libcamera/pipeline/imx8-isi/imx8-isi.cpp       |  2 +-
> > >  src/libcamera/pipeline/ipu3/cio2.cpp               |  2 +-
> > >  src/libcamera/pipeline/ipu3/cio2.h                 |  2 +-
> > >  src/libcamera/pipeline/ipu3/imgu.cpp               |  3 ++-
> > >  src/libcamera/pipeline/ipu3/imgu.h                 |  4 ++--
> > >  src/libcamera/pipeline/ipu3/ipu3.cpp               |  4 ++--
> > >  src/libcamera/pipeline/mali-c55/mali-c55.cpp       |  2 +-
> > >  src/libcamera/pipeline/rkisp1/rkisp1.cpp           |  2 +-
> > >  src/libcamera/pipeline/rkisp1/rkisp1_path.cpp      |  2 +-
> > >  src/libcamera/pipeline/rkisp1/rkisp1_path.h        |  2 +-
> > >  .../pipeline/rpi/common/pipeline_base.cpp          |  6 ++++--
> > >  src/libcamera/pipeline/rpi/common/pipeline_base.h  |  9 ++++++---
> > >  src/libcamera/pipeline/rpi/pisp/pisp.cpp           | 10 ++++++----
> > >  src/libcamera/pipeline/rpi/vc4/vc4.cpp             | 13 +++++++++----
> > >  src/libcamera/pipeline/simple/simple.cpp           | 13 +++++++------
> > >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp       |  6 +++---
> > >  src/libcamera/pipeline/vimc/vimc.cpp               |  6 +++---
> > >  src/libcamera/pipeline_handler.cpp                 | 14 ++++++++------
> > >  test/delayed_controls.cpp                          |  2 +-
> > >  test/libtest/buffer_source.cpp                     |  2 +-
> > >  21 files changed, 65 insertions(+), 49 deletions(-)
> > >
> > > diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h
> > > index 5fa8bc2f66ee..0199ab7911c0 100644
> > > --- a/include/libcamera/internal/pipeline_handler.h
> > > +++ b/include/libcamera/internal/pipeline_handler.h
> > > @@ -38,8 +38,8 @@ public:
> > >  	virtual ~PipelineHandler();
> > >
> > >  	virtual bool match(DeviceEnumerator *enumerator) = 0;
> > > -	MediaDevice *acquireMediaDevice(DeviceEnumerator *enumerator,
> > > -					const DeviceMatch &dm);
> > > +	std::shared_ptr<MediaDevice> acquireMediaDevice(DeviceEnumerator *enumerator,
> > > +							const DeviceMatch &dm);
> > >
> > >  	bool acquire(Camera *camera);
> > >  	void release(Camera *camera);
> > > @@ -74,7 +74,7 @@ protected:
> > >  	void clearMediaDevices();
> > >
> > >  	void registerCamera(std::shared_ptr<Camera> camera);
> > > -	void hotplugMediaDevice(MediaDevice *media);
> > > +	void hotplugMediaDevice(std::shared_ptr<MediaDevice> media);
> > >
> > >  	virtual int queueRequestDevice(Camera *camera, Request *request) = 0;
> > >  	virtual void stopDevice(Camera *camera) = 0;
> > > @@ -87,7 +87,7 @@ protected:
> > >  private:
> > >  	void unlockMediaDevices();
> > >
> > > -	void mediaDeviceDisconnected(MediaDevice *media);
> > > +	void mediaDeviceDisconnected(std::shared_ptr<MediaDevice> media);
> > >  	virtual void disconnect();
> > >
> > >  	void doQueueRequest(Request *request);
> > > diff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
> > > index 4e66b3368d5a..850dbfcdc64b 100644
> > > --- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
> > > +++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
> > > @@ -139,7 +139,7 @@ private:
> > >
> > >  	void bufferReady(FrameBuffer *buffer);
> > >
> > > -	MediaDevice *isiDev_;
> > > +	std::shared_ptr<MediaDevice> isiDev_;
> > >
> > >  	std::unique_ptr<V4L2Subdevice> crossbar_;
> > >  	std::vector<Pipe> pipes_;
> > > diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp
> > > index aa544d7b0303..ebbd424c56ea 100644
> > > --- a/src/libcamera/pipeline/ipu3/cio2.cpp
> > > +++ b/src/libcamera/pipeline/ipu3/cio2.cpp
> > > @@ -112,7 +112,7 @@ std::vector<SizeRange> CIO2Device::sizes(const PixelFormat &format) const
> > >   * \return 0 on success or a negative error code otherwise
> > >   * \retval -ENODEV No supported image sensor is connected to this CIO2 instance
> > >   */
> > > -int CIO2Device::init(const MediaDevice *media, unsigned int index)
> > > +int CIO2Device::init(std::shared_ptr<const MediaDevice> media, unsigned int index)
> > >  {
> > >  	int ret;
> > >
> > > diff --git a/src/libcamera/pipeline/ipu3/cio2.h b/src/libcamera/pipeline/ipu3/cio2.h
> > > index 963c2f6b93a4..fdf85f2655f0 100644
> > > --- a/src/libcamera/pipeline/ipu3/cio2.h
> > > +++ b/src/libcamera/pipeline/ipu3/cio2.h
> > > @@ -38,7 +38,7 @@ public:
> > >  	std::vector<PixelFormat> formats() const;
> > >  	std::vector<SizeRange> sizes(const PixelFormat &format) const;
> > >
> > > -	int init(const MediaDevice *media, unsigned int index);
> > > +	int init(std::shared_ptr<const MediaDevice> media, unsigned int index);
> > >  	int configure(const Size &size, const Transform &transform,
> > >  		      V4L2DeviceFormat *outputFormat);
> > >
> > > diff --git a/src/libcamera/pipeline/ipu3/imgu.cpp b/src/libcamera/pipeline/ipu3/imgu.cpp
> > > index 7be780913fae..391e000f6e12 100644
> > > --- a/src/libcamera/pipeline/ipu3/imgu.cpp
> > > +++ b/src/libcamera/pipeline/ipu3/imgu.cpp
> > > @@ -330,7 +330,8 @@ FOV calcFOV(const Size &in, const ImgUDevice::PipeConfig &pipe)
> > >   *
> > >   * \return 0 on success or a negative error code otherwise
> > >   */
> > > -int ImgUDevice::init(MediaDevice *media, unsigned int index)
> > > +int ImgUDevice::init(std::shared_ptr<libcamera::MediaDevice> media,
> > > +		     unsigned int index)
> > >  {
> > >  	int ret;
> > >
> > > diff --git a/src/libcamera/pipeline/ipu3/imgu.h b/src/libcamera/pipeline/ipu3/imgu.h
> > > index fa508316b301..272f861f98c4 100644
> > > --- a/src/libcamera/pipeline/ipu3/imgu.h
> > > +++ b/src/libcamera/pipeline/ipu3/imgu.h
> > > @@ -64,7 +64,7 @@ public:
> > >  		Size viewfinder;
> > >  	};
> > >
> > > -	int init(MediaDevice *media, unsigned int index);
> > > +	int init(std::shared_ptr<MediaDevice> media, unsigned int index);
> > >
> > >  	PipeConfig calculatePipeConfig(Pipe *pipe);
> > >
> > > @@ -118,7 +118,7 @@ private:
> > >  				 V4L2DeviceFormat *outputFormat);
> > >
> > >  	std::string name_;
> > > -	MediaDevice *media_;
> > > +	std::shared_ptr<MediaDevice> media_;
> > >  };
> > >
> > >  } /* namespace libcamera */
> > > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> > > index e31e3879dcc9..17205f96446a 100644
> > > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> > > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> > > @@ -164,8 +164,8 @@ private:
> > >
> > >  	ImgUDevice imgu0_;
> > >  	ImgUDevice imgu1_;
> > > -	MediaDevice *cio2MediaDev_;
> > > -	MediaDevice *imguMediaDev_;
> > > +	std::shared_ptr<MediaDevice> cio2MediaDev_;
> > > +	std::shared_ptr<MediaDevice> imguMediaDev_;
> > >
> > >  	std::vector<IPABuffer> ipaBuffers_;
> > >  };
> > > diff --git a/src/libcamera/pipeline/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp
> > > index a05e11fccf8d..7615122d907b 100644
> > > --- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp
> > > +++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp
> > > @@ -684,7 +684,7 @@ private:
> > >  	bool registerTPGCamera(MediaLink *link);
> > >  	bool registerSensorCamera(MediaLink *link);
> > >
> > > -	MediaDevice *media_;
> > > +	std::shared_ptr<MediaDevice> media_;
> > >  	std::unique_ptr<V4L2Subdevice> isp_;
> > >  	std::unique_ptr<V4L2VideoDevice> stats_;
> > >  	std::unique_ptr<V4L2VideoDevice> params_;
> > > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> > > index 705615b86b0c..d4ec538f478b 100644
> > > --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> > > +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> > > @@ -200,7 +200,7 @@ private:
> > >
> > >  	int updateControls(RkISP1CameraData *data);
> > >
> > > -	MediaDevice *media_;
> > > +	std::shared_ptr<MediaDevice> media_;
> > >  	std::unique_ptr<V4L2Subdevice> isp_;
> > >  	std::unique_ptr<V4L2VideoDevice> param_;
> > >  	std::unique_ptr<V4L2VideoDevice> stat_;
> > > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> > > index eee5b09e2ff0..2e567ace0b78 100644
> > > --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> > > +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> > > @@ -59,7 +59,7 @@ RkISP1Path::RkISP1Path(const char *name, const Span<const PixelFormat> &formats)
> > >  {
> > >  }
> > >
> > > -bool RkISP1Path::init(MediaDevice *media)
> > > +bool RkISP1Path::init(std::shared_ptr<MediaDevice> media)
> > >  {
> > >  	std::string resizer = std::string("rkisp1_resizer_") + name_ + "path";
> > >  	std::string video = std::string("rkisp1_") + name_ + "path";
> > > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> > > index 2a1ef0abe6d1..154310ac37c1 100644
> > > --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> > > +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> > > @@ -36,7 +36,7 @@ class RkISP1Path
> > >  public:
> > >  	RkISP1Path(const char *name, const Span<const PixelFormat> &formats);
> > >
> > > -	bool init(MediaDevice *media);
> > > +	bool init(std::shared_ptr<MediaDevice> media);
> > >
> > >  	int setEnabled(bool enable) { return link_->setEnabled(enable); }
> > >  	bool isEnabled() const { return link_->flags() & MEDIA_LNK_FL_ENABLED; }
> > > diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> > > index 1f13e5230fae..23ce54eca144 100644
> > > --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> > > +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> > > @@ -784,8 +784,10 @@ int PipelineHandlerBase::queueRequestDevice(Camera *camera, Request *request)
> > >  }
> > >
> > >  int PipelineHandlerBase::registerCamera(std::unique_ptr<RPi::CameraData> &cameraData,
> > > -					MediaDevice *frontend, const std::string &frontendName,
> > > -					MediaDevice *backend, MediaEntity *sensorEntity)
> > > +					std::shared_ptr<MediaDevice> frontend,
> > > +					const std::string &frontendName,
> > > +					std::shared_ptr<MediaDevice> backend,
> > > +					MediaEntity *sensorEntity)
> > >  {
> > >  	CameraData *data = cameraData.get();
> > >  	int ret;
> > > diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.h b/src/libcamera/pipeline/rpi/common/pipeline_base.h
> > > index aae0c2f35888..e422bbf7405f 100644
> > > --- a/src/libcamera/pipeline/rpi/common/pipeline_base.h
> > > +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.h
> > > @@ -229,13 +229,16 @@ public:
> > >
> > >  protected:
> > >  	int registerCamera(std::unique_ptr<RPi::CameraData> &cameraData,
> > > -			   MediaDevice *frontent, const std::string &frontendName,
> > > -			   MediaDevice *backend, MediaEntity *sensorEntity);
> > > +			   std::shared_ptr<MediaDevice> frontend,
> > > +			   const std::string &frontendName,
> > > +			   std::shared_ptr<MediaDevice> backend,
> > > +			   MediaEntity *sensorEntity);
> > >
> > >  	void mapBuffers(Camera *camera, const BufferMap &buffers, unsigned int mask);
> > >
> > >  	virtual int platformRegister(std::unique_ptr<CameraData> &cameraData,
> > > -				     MediaDevice *unicam, MediaDevice *isp) = 0;
> > > +				     std::shared_ptr<MediaDevice> unicam,
> > > +				     std::shared_ptr<MediaDevice> isp) = 0;
> > >
> > >  private:
> > >  	CameraData *cameraData(Camera *camera)
> > > diff --git a/src/libcamera/pipeline/rpi/pisp/pisp.cpp b/src/libcamera/pipeline/rpi/pisp/pisp.cpp
> > > index 91e7f4c94d96..d0cb71b49e11 100644
> > > --- a/src/libcamera/pipeline/rpi/pisp/pisp.cpp
> > > +++ b/src/libcamera/pipeline/rpi/pisp/pisp.cpp
> > > @@ -866,7 +866,8 @@ private:
> > >
> > >  	int prepareBuffers(Camera *camera) override;
> > >  	int platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
> > > -			     MediaDevice *cfe, MediaDevice *isp) override;
> > > +			     std::shared_ptr<MediaDevice> cfe,
> > > +			     std::shared_ptr<MediaDevice> isp) override;
> > >  };
> > >
> > >  bool PipelineHandlerPiSP::match(DeviceEnumerator *enumerator)
> > > @@ -884,7 +885,7 @@ bool PipelineHandlerPiSP::match(DeviceEnumerator *enumerator)
> > >  		cfe.add("rp1-cfe-fe-image0");
> > >  		cfe.add("rp1-cfe-fe-stats");
> > >  		cfe.add("rp1-cfe-fe-config");
> > > -		MediaDevice *cfeDevice = acquireMediaDevice(enumerator, cfe);
> > > +		std::shared_ptr<MediaDevice> cfeDevice = acquireMediaDevice(enumerator, cfe);
> > >
> > >  		if (!cfeDevice) {
> > >  			LOG(RPI, Debug) << "Unable to acquire a CFE instance";
> > > @@ -900,7 +901,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);
> > > +		std::shared_ptr<MediaDevice> ispDevice = acquireMediaDevice(enumerator, isp);
> > >
> > >  		if (!ispDevice) {
> > >  			LOG(RPI, Debug) << "Unable to acquire ISP instance";
> > > @@ -1065,7 +1066,8 @@ int PipelineHandlerPiSP::prepareBuffers(Camera *camera)
> > >  }
> > >
> > >  int PipelineHandlerPiSP::platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
> > > -					  MediaDevice *cfe, MediaDevice *isp)
> > > +					  std::shared_ptr<MediaDevice> cfe,
> > > +					  std::shared_ptr<MediaDevice> isp)
> > >  {
> > >  	PiSPCameraData *data = static_cast<PiSPCameraData *>(cameraData.get());
> > >  	int ret;
> > > diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> > > index fe910bdf2ff9..d58035ecd198 100644
> > > --- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> > > +++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> > > @@ -5,6 +5,8 @@
> > >   * Pipeline handler for VC4-based Raspberry Pi devices
> > >   */
> > >
> > > +#include <memory>
> > > +
> > >  #include <linux/bcm2835-isp.h>
> > >  #include <linux/v4l2-controls.h>
> > >  #include <linux/videodev2.h>
> > > @@ -158,7 +160,8 @@ private:
> > >
> > >  	int prepareBuffers(Camera *camera) override;
> > >  	int platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
> > > -			     MediaDevice *unicam, MediaDevice *isp) override;
> > > +			     std::shared_ptr<MediaDevice> unicam,
> > > +			     std::shared_ptr<MediaDevice> isp) override;
> > >  };
> > >
> > >  bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)
> > > @@ -173,7 +176,7 @@ bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)
> > >  	 */
> > >  	for (unsigned int i = 0; i < numUnicamDevices; i++) {
> > >  		DeviceMatch unicam("unicam");
> > > -		MediaDevice *unicamDevice = acquireMediaDevice(enumerator, unicam);
> > > +		std::shared_ptr<MediaDevice> unicamDevice = acquireMediaDevice(enumerator, unicam);
> > >
> > >  		if (!unicamDevice) {
> > >  			LOG(RPI, Debug) << "Unable to acquire a Unicam instance";
> > > @@ -181,7 +184,7 @@ bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)
> > >  		}
> > >
> > >  		DeviceMatch isp("bcm2835-isp");
> > > -		MediaDevice *ispDevice = acquireMediaDevice(enumerator, isp);
> > > +		std::shared_ptr<MediaDevice> ispDevice = acquireMediaDevice(enumerator, isp);
> > >
> > >  		if (!ispDevice) {
> > >  			LOG(RPI, Debug) << "Unable to acquire ISP instance";
> > > @@ -303,7 +306,9 @@ int PipelineHandlerVc4::prepareBuffers(Camera *camera)
> > >  	return 0;
> > >  }
> > >
> > > -int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &cameraData, MediaDevice *unicam, MediaDevice *isp)
> > > +int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
> > > +					 std::shared_ptr<MediaDevice> unicam,
> > > +					 std::shared_ptr<MediaDevice> isp)
> > >  {
> > >  	Vc4CameraData *data = static_cast<Vc4CameraData *>(cameraData.get());
> > >
> > > diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
> > > index 451491f5608e..feaa16094b65 100644
> > > --- a/src/libcamera/pipeline/simple/simple.cpp
> > > +++ b/src/libcamera/pipeline/simple/simple.cpp
> > > @@ -407,7 +407,7 @@ public:
> > >
> > >  	V4L2VideoDevice *video(const MediaEntity *entity);
> > >  	V4L2Subdevice *subdev(const MediaEntity *entity);
> > > -	MediaDevice *converter() { return converter_; }
> > > +	MediaDevice *converter() { return converter_.get(); }
> > >  	bool swIspEnabled() const { return swIspEnabled_; }
> > >
> > >  protected:
> > > @@ -427,7 +427,8 @@ private:
> > >  		return static_cast<SimpleCameraData *>(camera->_d());
> > >  	}
> > >
> > > -	bool matchDevice(MediaDevice *media, const SimplePipelineInfo &info,
> > > +	bool matchDevice(std::shared_ptr<MediaDevice> media,
> > > +			 const SimplePipelineInfo &info,
> > >  			 DeviceEnumerator *enumerator);
> > >
> > >  	std::vector<MediaEntity *> locateSensors(MediaDevice *media);
> > > @@ -438,7 +439,7 @@ private:
> > >
> > >  	std::map<const MediaEntity *, EntityData> entities_;
> > >
> > > -	MediaDevice *converter_;
> > > +	std::shared_ptr<MediaDevice> converter_;
> > >  	bool swIspEnabled_;
> > >  };
> > >
> > > @@ -1663,7 +1664,7 @@ int SimplePipelineHandler::resetRoutingTable(V4L2Subdevice *subdev)
> > >  	return 0;
> > >  }
> > >
> > > -bool SimplePipelineHandler::matchDevice(MediaDevice *media,
> > > +bool SimplePipelineHandler::matchDevice(std::shared_ptr<MediaDevice> media,
> > >  					const SimplePipelineInfo &info,
> > >  					DeviceEnumerator *enumerator)
> > >  {
> > > @@ -1681,7 +1682,7 @@ bool SimplePipelineHandler::matchDevice(MediaDevice *media,
> > >  	swIspEnabled_ = info.swIspEnabled;
> > >
> > >  	/* Locate the sensors. */
> > > -	std::vector<MediaEntity *> sensors = locateSensors(media);
> > > +	std::vector<MediaEntity *> sensors = locateSensors(media.get());
> > >  	if (sensors.empty()) {
> > >  		LOG(SimplePipeline, Info) << "No sensor found for " << media->deviceNode();
> > >  		return false;
> > > @@ -1799,7 +1800,7 @@ bool SimplePipelineHandler::matchDevice(MediaDevice *media,
> > >
> > >  bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
> > >  {
> > > -	MediaDevice *media;
> > > +	std::shared_ptr<MediaDevice> media;
> > >
> > >  	for (const SimplePipelineInfo &inf : supportedDevices) {
> > >  		DeviceMatch dm(inf.driver);
> > > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > > index 5adc89fdb29c..a1e036a32d5f 100644
> > > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > > @@ -46,7 +46,7 @@ public:
> > >  	{
> > >  	}
> > >
> > > -	int init(MediaDevice *media);
> > > +	int init(std::shared_ptr<MediaDevice> media);
> > >  	void addControl(uint32_t cid, const ControlInfo &v4l2info,
> > >  			ControlInfoMap::Map *ctrls);
> > >  	void imageBufferReady(FrameBuffer *buffer);
> > > @@ -449,7 +449,7 @@ int PipelineHandlerUVC::queueRequestDevice(Camera *camera, Request *request)
> > >
> > >  bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
> > >  {
> > > -	MediaDevice *media;
> > > +	std::shared_ptr<MediaDevice> media;
> > >  	DeviceMatch dm("uvcvideo");
> > >
> > >  	media = acquireMediaDevice(enumerator, dm);
> > > @@ -491,7 +491,7 @@ void PipelineHandlerUVC::releaseDevice(Camera *camera)
> > >  	data->video_->close();
> > >  }
> > >
> > > -int UVCCameraData::init(MediaDevice *media)
> > > +int UVCCameraData::init(std::shared_ptr<MediaDevice> media)
> > >  {
> > >  	int ret;
> > >
> > > diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp
> > > index 07273bd2b6c3..59c564b8a9f6 100644
> > > --- a/src/libcamera/pipeline/vimc/vimc.cpp
> > > +++ b/src/libcamera/pipeline/vimc/vimc.cpp
> > > @@ -49,7 +49,7 @@ LOG_DEFINE_CATEGORY(VIMC)
> > >  class VimcCameraData : public Camera::Private
> > >  {
> > >  public:
> > > -	VimcCameraData(PipelineHandler *pipe, MediaDevice *media)
> > > +	VimcCameraData(PipelineHandler *pipe, std::shared_ptr<MediaDevice> media)
> > >  		: Camera::Private(pipe), media_(media)
> > >  	{
> > >  	}
> > > @@ -59,7 +59,7 @@ public:
> > >  	void imageBufferReady(FrameBuffer *buffer);
> > >  	void paramsComputed(unsigned int id, const Flags<ipa::vimc::TestFlag> flags);
> > >
> > > -	MediaDevice *media_;
> > > +	std::shared_ptr<MediaDevice> media_;
> > >  	std::unique_ptr<CameraSensor> sensor_;
> > >  	std::unique_ptr<V4L2Subdevice> debayer_;
> > >  	std::unique_ptr<V4L2Subdevice> scaler_;
> > > @@ -476,7 +476,7 @@ bool PipelineHandlerVimc::match(DeviceEnumerator *enumerator)
> > >  	dm.add("RGB/YUV Input");
> > >  	dm.add("Scaler");
> > >
> > > -	MediaDevice *media = acquireMediaDevice(enumerator, dm);
> > > +	std::shared_ptr<MediaDevice> media = acquireMediaDevice(enumerator, dm);
> > >  	if (!media)
> > >  		return false;
> > >
> > > diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
> > > index 8f12957b75fa..5fe2c64c8bc6 100644
> > > --- a/src/libcamera/pipeline_handler.cpp
> > > +++ b/src/libcamera/pipeline_handler.cpp
> > > @@ -125,10 +125,12 @@ PipelineHandler::~PipelineHandler()
> > >   *
> > >   * \context This function shall be called from the CameraManager thread.
> > >   *
> > > - * \return A pointer to the matching MediaDevice, or nullptr if no match is found
> > > + * \return A shared pointer to the matching MediaDevice, or nullptr if no match
> > > + * is found
> > >   */
> > > -MediaDevice *PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
> > > -						 const DeviceMatch &dm)
> > > +std::shared_ptr<MediaDevice>
> > > +PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
> > > +				    const DeviceMatch &dm)
> > >  {
> > >  	std::shared_ptr<MediaDevice> media = enumerator->search(dm);
> > >  	if (!media)
> > > @@ -139,7 +141,7 @@ MediaDevice *PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
> > >
> > >  	mediaDevices_.push_back(media);
> > >
> > > -	return media.get();
> > > +	return media;
> > >  }
> > >
> > >  /**
> > > @@ -712,7 +714,7 @@ void PipelineHandler::registerCamera(std::shared_ptr<Camera> camera)
> > >   * handler gets notified and automatically disconnects all the cameras it has
> > >   * registered without requiring any manual intervention.
> > >   */
> > > -void PipelineHandler::hotplugMediaDevice(MediaDevice *media)
> > > +void PipelineHandler::hotplugMediaDevice(std::shared_ptr<MediaDevice> media)
> > >  {
> > >  	media->disconnected.connect(this, [this, media] { mediaDeviceDisconnected(media); });
> > >  }
> > > @@ -720,7 +722,7 @@ void PipelineHandler::hotplugMediaDevice(MediaDevice *media)
> > >  /**
> > >   * \brief Slot for the MediaDevice disconnected signal
> > >   */
> > > -void PipelineHandler::mediaDeviceDisconnected(MediaDevice *media)
> > > +void PipelineHandler::mediaDeviceDisconnected(std::shared_ptr<MediaDevice> media)
> > >  {
> > >  	media->disconnected.disconnect(this);
> > >
> > > diff --git a/test/delayed_controls.cpp b/test/delayed_controls.cpp
> > > index 7bd30e7aead8..b305be48aafc 100644
> > > --- a/test/delayed_controls.cpp
> > > +++ b/test/delayed_controls.cpp
> > > @@ -47,7 +47,7 @@ protected:
> > >  			return TestSkip;
> > >  		}
> > >
> > > -		dev_ = V4L2VideoDevice::fromEntityName(media_.get(), "vivid-000-vid-cap");
> > > +		dev_ = V4L2VideoDevice::fromEntityName(media_, "vivid-000-vid-cap");
> > >  		if (dev_->open()) {
> > >  			cerr << "Failed to open video device" << endl;
> > >  			return TestFail;
> > > diff --git a/test/libtest/buffer_source.cpp b/test/libtest/buffer_source.cpp
> > > index dde11f365e43..19b25fed50a0 100644
> > > --- a/test/libtest/buffer_source.cpp
> > > +++ b/test/libtest/buffer_source.cpp
> > > @@ -52,7 +52,7 @@ int BufferSource::allocate(const StreamConfiguration &config)
> > >  		return TestSkip;
> > >  	}
> > >
> > > -	std::unique_ptr<V4L2VideoDevice> video = V4L2VideoDevice::fromEntityName(media_.get(), videoDeviceName);
> > > +	std::unique_ptr<V4L2VideoDevice> video = V4L2VideoDevice::fromEntityName(media_, videoDeviceName);
> > >  	if (!video) {
> > >  		std::cout << "Failed to get video device from entity "
> > >  			  << videoDeviceName << std::endl;

Patch
diff mbox series

diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h
index 5fa8bc2f66ee..0199ab7911c0 100644
--- a/include/libcamera/internal/pipeline_handler.h
+++ b/include/libcamera/internal/pipeline_handler.h
@@ -38,8 +38,8 @@  public:
 	virtual ~PipelineHandler();
 
 	virtual bool match(DeviceEnumerator *enumerator) = 0;
-	MediaDevice *acquireMediaDevice(DeviceEnumerator *enumerator,
-					const DeviceMatch &dm);
+	std::shared_ptr<MediaDevice> acquireMediaDevice(DeviceEnumerator *enumerator,
+							const DeviceMatch &dm);
 
 	bool acquire(Camera *camera);
 	void release(Camera *camera);
@@ -74,7 +74,7 @@  protected:
 	void clearMediaDevices();
 
 	void registerCamera(std::shared_ptr<Camera> camera);
-	void hotplugMediaDevice(MediaDevice *media);
+	void hotplugMediaDevice(std::shared_ptr<MediaDevice> media);
 
 	virtual int queueRequestDevice(Camera *camera, Request *request) = 0;
 	virtual void stopDevice(Camera *camera) = 0;
@@ -87,7 +87,7 @@  protected:
 private:
 	void unlockMediaDevices();
 
-	void mediaDeviceDisconnected(MediaDevice *media);
+	void mediaDeviceDisconnected(std::shared_ptr<MediaDevice> media);
 	virtual void disconnect();
 
 	void doQueueRequest(Request *request);
diff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
index 4e66b3368d5a..850dbfcdc64b 100644
--- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
+++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
@@ -139,7 +139,7 @@  private:
 
 	void bufferReady(FrameBuffer *buffer);
 
-	MediaDevice *isiDev_;
+	std::shared_ptr<MediaDevice> isiDev_;
 
 	std::unique_ptr<V4L2Subdevice> crossbar_;
 	std::vector<Pipe> pipes_;
diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp
index aa544d7b0303..ebbd424c56ea 100644
--- a/src/libcamera/pipeline/ipu3/cio2.cpp
+++ b/src/libcamera/pipeline/ipu3/cio2.cpp
@@ -112,7 +112,7 @@  std::vector<SizeRange> CIO2Device::sizes(const PixelFormat &format) const
  * \return 0 on success or a negative error code otherwise
  * \retval -ENODEV No supported image sensor is connected to this CIO2 instance
  */
-int CIO2Device::init(const MediaDevice *media, unsigned int index)
+int CIO2Device::init(std::shared_ptr<const MediaDevice> media, unsigned int index)
 {
 	int ret;
 
diff --git a/src/libcamera/pipeline/ipu3/cio2.h b/src/libcamera/pipeline/ipu3/cio2.h
index 963c2f6b93a4..fdf85f2655f0 100644
--- a/src/libcamera/pipeline/ipu3/cio2.h
+++ b/src/libcamera/pipeline/ipu3/cio2.h
@@ -38,7 +38,7 @@  public:
 	std::vector<PixelFormat> formats() const;
 	std::vector<SizeRange> sizes(const PixelFormat &format) const;
 
-	int init(const MediaDevice *media, unsigned int index);
+	int init(std::shared_ptr<const MediaDevice> media, unsigned int index);
 	int configure(const Size &size, const Transform &transform,
 		      V4L2DeviceFormat *outputFormat);
 
diff --git a/src/libcamera/pipeline/ipu3/imgu.cpp b/src/libcamera/pipeline/ipu3/imgu.cpp
index 7be780913fae..391e000f6e12 100644
--- a/src/libcamera/pipeline/ipu3/imgu.cpp
+++ b/src/libcamera/pipeline/ipu3/imgu.cpp
@@ -330,7 +330,8 @@  FOV calcFOV(const Size &in, const ImgUDevice::PipeConfig &pipe)
  *
  * \return 0 on success or a negative error code otherwise
  */
-int ImgUDevice::init(MediaDevice *media, unsigned int index)
+int ImgUDevice::init(std::shared_ptr<libcamera::MediaDevice> media,
+		     unsigned int index)
 {
 	int ret;
 
diff --git a/src/libcamera/pipeline/ipu3/imgu.h b/src/libcamera/pipeline/ipu3/imgu.h
index fa508316b301..272f861f98c4 100644
--- a/src/libcamera/pipeline/ipu3/imgu.h
+++ b/src/libcamera/pipeline/ipu3/imgu.h
@@ -64,7 +64,7 @@  public:
 		Size viewfinder;
 	};
 
-	int init(MediaDevice *media, unsigned int index);
+	int init(std::shared_ptr<MediaDevice> media, unsigned int index);
 
 	PipeConfig calculatePipeConfig(Pipe *pipe);
 
@@ -118,7 +118,7 @@  private:
 				 V4L2DeviceFormat *outputFormat);
 
 	std::string name_;
-	MediaDevice *media_;
+	std::shared_ptr<MediaDevice> media_;
 };
 
 } /* namespace libcamera */
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index e31e3879dcc9..17205f96446a 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -164,8 +164,8 @@  private:
 
 	ImgUDevice imgu0_;
 	ImgUDevice imgu1_;
-	MediaDevice *cio2MediaDev_;
-	MediaDevice *imguMediaDev_;
+	std::shared_ptr<MediaDevice> cio2MediaDev_;
+	std::shared_ptr<MediaDevice> imguMediaDev_;
 
 	std::vector<IPABuffer> ipaBuffers_;
 };
diff --git a/src/libcamera/pipeline/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp
index a05e11fccf8d..7615122d907b 100644
--- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp
+++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp
@@ -684,7 +684,7 @@  private:
 	bool registerTPGCamera(MediaLink *link);
 	bool registerSensorCamera(MediaLink *link);
 
-	MediaDevice *media_;
+	std::shared_ptr<MediaDevice> media_;
 	std::unique_ptr<V4L2Subdevice> isp_;
 	std::unique_ptr<V4L2VideoDevice> stats_;
 	std::unique_ptr<V4L2VideoDevice> params_;
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
index 705615b86b0c..d4ec538f478b 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
@@ -200,7 +200,7 @@  private:
 
 	int updateControls(RkISP1CameraData *data);
 
-	MediaDevice *media_;
+	std::shared_ptr<MediaDevice> media_;
 	std::unique_ptr<V4L2Subdevice> isp_;
 	std::unique_ptr<V4L2VideoDevice> param_;
 	std::unique_ptr<V4L2VideoDevice> stat_;
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
index eee5b09e2ff0..2e567ace0b78 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
@@ -59,7 +59,7 @@  RkISP1Path::RkISP1Path(const char *name, const Span<const PixelFormat> &formats)
 {
 }
 
-bool RkISP1Path::init(MediaDevice *media)
+bool RkISP1Path::init(std::shared_ptr<MediaDevice> media)
 {
 	std::string resizer = std::string("rkisp1_resizer_") + name_ + "path";
 	std::string video = std::string("rkisp1_") + name_ + "path";
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
index 2a1ef0abe6d1..154310ac37c1 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h
+++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
@@ -36,7 +36,7 @@  class RkISP1Path
 public:
 	RkISP1Path(const char *name, const Span<const PixelFormat> &formats);
 
-	bool init(MediaDevice *media);
+	bool init(std::shared_ptr<MediaDevice> media);
 
 	int setEnabled(bool enable) { return link_->setEnabled(enable); }
 	bool isEnabled() const { return link_->flags() & MEDIA_LNK_FL_ENABLED; }
diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
index 1f13e5230fae..23ce54eca144 100644
--- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
+++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
@@ -784,8 +784,10 @@  int PipelineHandlerBase::queueRequestDevice(Camera *camera, Request *request)
 }
 
 int PipelineHandlerBase::registerCamera(std::unique_ptr<RPi::CameraData> &cameraData,
-					MediaDevice *frontend, const std::string &frontendName,
-					MediaDevice *backend, MediaEntity *sensorEntity)
+					std::shared_ptr<MediaDevice> frontend,
+					const std::string &frontendName,
+					std::shared_ptr<MediaDevice> backend,
+					MediaEntity *sensorEntity)
 {
 	CameraData *data = cameraData.get();
 	int ret;
diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.h b/src/libcamera/pipeline/rpi/common/pipeline_base.h
index aae0c2f35888..e422bbf7405f 100644
--- a/src/libcamera/pipeline/rpi/common/pipeline_base.h
+++ b/src/libcamera/pipeline/rpi/common/pipeline_base.h
@@ -229,13 +229,16 @@  public:
 
 protected:
 	int registerCamera(std::unique_ptr<RPi::CameraData> &cameraData,
-			   MediaDevice *frontent, const std::string &frontendName,
-			   MediaDevice *backend, MediaEntity *sensorEntity);
+			   std::shared_ptr<MediaDevice> frontend,
+			   const std::string &frontendName,
+			   std::shared_ptr<MediaDevice> backend,
+			   MediaEntity *sensorEntity);
 
 	void mapBuffers(Camera *camera, const BufferMap &buffers, unsigned int mask);
 
 	virtual int platformRegister(std::unique_ptr<CameraData> &cameraData,
-				     MediaDevice *unicam, MediaDevice *isp) = 0;
+				     std::shared_ptr<MediaDevice> unicam,
+				     std::shared_ptr<MediaDevice> isp) = 0;
 
 private:
 	CameraData *cameraData(Camera *camera)
diff --git a/src/libcamera/pipeline/rpi/pisp/pisp.cpp b/src/libcamera/pipeline/rpi/pisp/pisp.cpp
index 91e7f4c94d96..d0cb71b49e11 100644
--- a/src/libcamera/pipeline/rpi/pisp/pisp.cpp
+++ b/src/libcamera/pipeline/rpi/pisp/pisp.cpp
@@ -866,7 +866,8 @@  private:
 
 	int prepareBuffers(Camera *camera) override;
 	int platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
-			     MediaDevice *cfe, MediaDevice *isp) override;
+			     std::shared_ptr<MediaDevice> cfe,
+			     std::shared_ptr<MediaDevice> isp) override;
 };
 
 bool PipelineHandlerPiSP::match(DeviceEnumerator *enumerator)
@@ -884,7 +885,7 @@  bool PipelineHandlerPiSP::match(DeviceEnumerator *enumerator)
 		cfe.add("rp1-cfe-fe-image0");
 		cfe.add("rp1-cfe-fe-stats");
 		cfe.add("rp1-cfe-fe-config");
-		MediaDevice *cfeDevice = acquireMediaDevice(enumerator, cfe);
+		std::shared_ptr<MediaDevice> cfeDevice = acquireMediaDevice(enumerator, cfe);
 
 		if (!cfeDevice) {
 			LOG(RPI, Debug) << "Unable to acquire a CFE instance";
@@ -900,7 +901,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);
+		std::shared_ptr<MediaDevice> ispDevice = acquireMediaDevice(enumerator, isp);
 
 		if (!ispDevice) {
 			LOG(RPI, Debug) << "Unable to acquire ISP instance";
@@ -1065,7 +1066,8 @@  int PipelineHandlerPiSP::prepareBuffers(Camera *camera)
 }
 
 int PipelineHandlerPiSP::platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
-					  MediaDevice *cfe, MediaDevice *isp)
+					  std::shared_ptr<MediaDevice> cfe,
+					  std::shared_ptr<MediaDevice> isp)
 {
 	PiSPCameraData *data = static_cast<PiSPCameraData *>(cameraData.get());
 	int ret;
diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
index fe910bdf2ff9..d58035ecd198 100644
--- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp
+++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
@@ -5,6 +5,8 @@ 
  * Pipeline handler for VC4-based Raspberry Pi devices
  */
 
+#include <memory>
+
 #include <linux/bcm2835-isp.h>
 #include <linux/v4l2-controls.h>
 #include <linux/videodev2.h>
@@ -158,7 +160,8 @@  private:
 
 	int prepareBuffers(Camera *camera) override;
 	int platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
-			     MediaDevice *unicam, MediaDevice *isp) override;
+			     std::shared_ptr<MediaDevice> unicam,
+			     std::shared_ptr<MediaDevice> isp) override;
 };
 
 bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)
@@ -173,7 +176,7 @@  bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)
 	 */
 	for (unsigned int i = 0; i < numUnicamDevices; i++) {
 		DeviceMatch unicam("unicam");
-		MediaDevice *unicamDevice = acquireMediaDevice(enumerator, unicam);
+		std::shared_ptr<MediaDevice> unicamDevice = acquireMediaDevice(enumerator, unicam);
 
 		if (!unicamDevice) {
 			LOG(RPI, Debug) << "Unable to acquire a Unicam instance";
@@ -181,7 +184,7 @@  bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)
 		}
 
 		DeviceMatch isp("bcm2835-isp");
-		MediaDevice *ispDevice = acquireMediaDevice(enumerator, isp);
+		std::shared_ptr<MediaDevice> ispDevice = acquireMediaDevice(enumerator, isp);
 
 		if (!ispDevice) {
 			LOG(RPI, Debug) << "Unable to acquire ISP instance";
@@ -303,7 +306,9 @@  int PipelineHandlerVc4::prepareBuffers(Camera *camera)
 	return 0;
 }
 
-int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &cameraData, MediaDevice *unicam, MediaDevice *isp)
+int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
+					 std::shared_ptr<MediaDevice> unicam,
+					 std::shared_ptr<MediaDevice> isp)
 {
 	Vc4CameraData *data = static_cast<Vc4CameraData *>(cameraData.get());
 
diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
index 451491f5608e..feaa16094b65 100644
--- a/src/libcamera/pipeline/simple/simple.cpp
+++ b/src/libcamera/pipeline/simple/simple.cpp
@@ -407,7 +407,7 @@  public:
 
 	V4L2VideoDevice *video(const MediaEntity *entity);
 	V4L2Subdevice *subdev(const MediaEntity *entity);
-	MediaDevice *converter() { return converter_; }
+	MediaDevice *converter() { return converter_.get(); }
 	bool swIspEnabled() const { return swIspEnabled_; }
 
 protected:
@@ -427,7 +427,8 @@  private:
 		return static_cast<SimpleCameraData *>(camera->_d());
 	}
 
-	bool matchDevice(MediaDevice *media, const SimplePipelineInfo &info,
+	bool matchDevice(std::shared_ptr<MediaDevice> media,
+			 const SimplePipelineInfo &info,
 			 DeviceEnumerator *enumerator);
 
 	std::vector<MediaEntity *> locateSensors(MediaDevice *media);
@@ -438,7 +439,7 @@  private:
 
 	std::map<const MediaEntity *, EntityData> entities_;
 
-	MediaDevice *converter_;
+	std::shared_ptr<MediaDevice> converter_;
 	bool swIspEnabled_;
 };
 
@@ -1663,7 +1664,7 @@  int SimplePipelineHandler::resetRoutingTable(V4L2Subdevice *subdev)
 	return 0;
 }
 
-bool SimplePipelineHandler::matchDevice(MediaDevice *media,
+bool SimplePipelineHandler::matchDevice(std::shared_ptr<MediaDevice> media,
 					const SimplePipelineInfo &info,
 					DeviceEnumerator *enumerator)
 {
@@ -1681,7 +1682,7 @@  bool SimplePipelineHandler::matchDevice(MediaDevice *media,
 	swIspEnabled_ = info.swIspEnabled;
 
 	/* Locate the sensors. */
-	std::vector<MediaEntity *> sensors = locateSensors(media);
+	std::vector<MediaEntity *> sensors = locateSensors(media.get());
 	if (sensors.empty()) {
 		LOG(SimplePipeline, Info) << "No sensor found for " << media->deviceNode();
 		return false;
@@ -1799,7 +1800,7 @@  bool SimplePipelineHandler::matchDevice(MediaDevice *media,
 
 bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
 {
-	MediaDevice *media;
+	std::shared_ptr<MediaDevice> media;
 
 	for (const SimplePipelineInfo &inf : supportedDevices) {
 		DeviceMatch dm(inf.driver);
diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
index 5adc89fdb29c..a1e036a32d5f 100644
--- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
+++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
@@ -46,7 +46,7 @@  public:
 	{
 	}
 
-	int init(MediaDevice *media);
+	int init(std::shared_ptr<MediaDevice> media);
 	void addControl(uint32_t cid, const ControlInfo &v4l2info,
 			ControlInfoMap::Map *ctrls);
 	void imageBufferReady(FrameBuffer *buffer);
@@ -449,7 +449,7 @@  int PipelineHandlerUVC::queueRequestDevice(Camera *camera, Request *request)
 
 bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
 {
-	MediaDevice *media;
+	std::shared_ptr<MediaDevice> media;
 	DeviceMatch dm("uvcvideo");
 
 	media = acquireMediaDevice(enumerator, dm);
@@ -491,7 +491,7 @@  void PipelineHandlerUVC::releaseDevice(Camera *camera)
 	data->video_->close();
 }
 
-int UVCCameraData::init(MediaDevice *media)
+int UVCCameraData::init(std::shared_ptr<MediaDevice> media)
 {
 	int ret;
 
diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp
index 07273bd2b6c3..59c564b8a9f6 100644
--- a/src/libcamera/pipeline/vimc/vimc.cpp
+++ b/src/libcamera/pipeline/vimc/vimc.cpp
@@ -49,7 +49,7 @@  LOG_DEFINE_CATEGORY(VIMC)
 class VimcCameraData : public Camera::Private
 {
 public:
-	VimcCameraData(PipelineHandler *pipe, MediaDevice *media)
+	VimcCameraData(PipelineHandler *pipe, std::shared_ptr<MediaDevice> media)
 		: Camera::Private(pipe), media_(media)
 	{
 	}
@@ -59,7 +59,7 @@  public:
 	void imageBufferReady(FrameBuffer *buffer);
 	void paramsComputed(unsigned int id, const Flags<ipa::vimc::TestFlag> flags);
 
-	MediaDevice *media_;
+	std::shared_ptr<MediaDevice> media_;
 	std::unique_ptr<CameraSensor> sensor_;
 	std::unique_ptr<V4L2Subdevice> debayer_;
 	std::unique_ptr<V4L2Subdevice> scaler_;
@@ -476,7 +476,7 @@  bool PipelineHandlerVimc::match(DeviceEnumerator *enumerator)
 	dm.add("RGB/YUV Input");
 	dm.add("Scaler");
 
-	MediaDevice *media = acquireMediaDevice(enumerator, dm);
+	std::shared_ptr<MediaDevice> media = acquireMediaDevice(enumerator, dm);
 	if (!media)
 		return false;
 
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index 8f12957b75fa..5fe2c64c8bc6 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -125,10 +125,12 @@  PipelineHandler::~PipelineHandler()
  *
  * \context This function shall be called from the CameraManager thread.
  *
- * \return A pointer to the matching MediaDevice, or nullptr if no match is found
+ * \return A shared pointer to the matching MediaDevice, or nullptr if no match
+ * is found
  */
-MediaDevice *PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
-						 const DeviceMatch &dm)
+std::shared_ptr<MediaDevice>
+PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
+				    const DeviceMatch &dm)
 {
 	std::shared_ptr<MediaDevice> media = enumerator->search(dm);
 	if (!media)
@@ -139,7 +141,7 @@  MediaDevice *PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
 
 	mediaDevices_.push_back(media);
 
-	return media.get();
+	return media;
 }
 
 /**
@@ -712,7 +714,7 @@  void PipelineHandler::registerCamera(std::shared_ptr<Camera> camera)
  * handler gets notified and automatically disconnects all the cameras it has
  * registered without requiring any manual intervention.
  */
-void PipelineHandler::hotplugMediaDevice(MediaDevice *media)
+void PipelineHandler::hotplugMediaDevice(std::shared_ptr<MediaDevice> media)
 {
 	media->disconnected.connect(this, [this, media] { mediaDeviceDisconnected(media); });
 }
@@ -720,7 +722,7 @@  void PipelineHandler::hotplugMediaDevice(MediaDevice *media)
 /**
  * \brief Slot for the MediaDevice disconnected signal
  */
-void PipelineHandler::mediaDeviceDisconnected(MediaDevice *media)
+void PipelineHandler::mediaDeviceDisconnected(std::shared_ptr<MediaDevice> media)
 {
 	media->disconnected.disconnect(this);
 
diff --git a/test/delayed_controls.cpp b/test/delayed_controls.cpp
index 7bd30e7aead8..b305be48aafc 100644
--- a/test/delayed_controls.cpp
+++ b/test/delayed_controls.cpp
@@ -47,7 +47,7 @@  protected:
 			return TestSkip;
 		}
 
-		dev_ = V4L2VideoDevice::fromEntityName(media_.get(), "vivid-000-vid-cap");
+		dev_ = V4L2VideoDevice::fromEntityName(media_, "vivid-000-vid-cap");
 		if (dev_->open()) {
 			cerr << "Failed to open video device" << endl;
 			return TestFail;
diff --git a/test/libtest/buffer_source.cpp b/test/libtest/buffer_source.cpp
index dde11f365e43..19b25fed50a0 100644
--- a/test/libtest/buffer_source.cpp
+++ b/test/libtest/buffer_source.cpp
@@ -52,7 +52,7 @@  int BufferSource::allocate(const StreamConfiguration &config)
 		return TestSkip;
 	}
 
-	std::unique_ptr<V4L2VideoDevice> video = V4L2VideoDevice::fromEntityName(media_.get(), videoDeviceName);
+	std::unique_ptr<V4L2VideoDevice> video = V4L2VideoDevice::fromEntityName(media_, videoDeviceName);
 	if (!video) {
 		std::cout << "Failed to get video device from entity "
 			  << videoDeviceName << std::endl;