[libcamera-devel] [PATCH 08/10] libcamera: pipeline: simple: Move converter to SimpleCameraData

Laurent Pinchart laurent.pinchart at ideasonboard.com
Fri Aug 6 00:24:34 CEST 2021


To use multiple cameras at the same time, each camera instance will need
its own converter. Store the converter in SimpleCameraData, and open it
in init().

Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
 src/libcamera/pipeline/simple/simple.cpp | 106 +++++++++++------------
 1 file changed, 51 insertions(+), 55 deletions(-)

diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
index b32369cae701..961262b7803d 100644
--- a/src/libcamera/pipeline/simple/simple.cpp
+++ b/src/libcamera/pipeline/simple/simple.cpp
@@ -226,9 +226,14 @@ public:
 	std::vector<Configuration> configs_;
 	std::map<PixelFormat, const Configuration *> formats_;
 
+	std::unique_ptr<SimpleConverter> converter_;
 	std::vector<std::unique_ptr<FrameBuffer>> converterBuffers_;
 	bool useConverter_;
 	std::queue<std::map<unsigned int, FrameBuffer *>> converterQueue_;
+
+private:
+	void converterInputDone(FrameBuffer *buffer);
+	void converterOutputDone(FrameBuffer *buffer);
 };
 
 class SimpleCameraConfiguration : public CameraConfiguration
@@ -277,7 +282,7 @@ public:
 
 	V4L2VideoDevice *video(const MediaEntity *entity);
 	V4L2Subdevice *subdev(const MediaEntity *entity);
-	SimpleConverter *converter() { return converter_.get(); }
+	MediaDevice *converter() { return converter_; }
 
 protected:
 	int queueRequestDevice(Camera *camera, Request *request) override;
@@ -303,13 +308,11 @@ private:
 	void releasePipeline(SimpleCameraData *data);
 
 	void bufferReady(FrameBuffer *buffer);
-	void converterInputDone(FrameBuffer *buffer);
-	void converterOutputDone(FrameBuffer *buffer);
 
 	MediaDevice *media_;
 	std::map<const MediaEntity *, EntityData> entities_;
 
-	std::unique_ptr<SimpleConverter> converter_;
+	MediaDevice *converter_;
 
 	Camera *activeCamera_;
 };
@@ -417,9 +420,22 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe,
 int SimpleCameraData::init()
 {
 	SimplePipelineHandler *pipe = static_cast<SimplePipelineHandler *>(pipe_);
-	SimpleConverter *converter = pipe->converter();
 	int ret;
 
+	/* Open the converter, if any. */
+	MediaDevice *converter = pipe->converter();
+	if (converter) {
+		converter_ = std::make_unique<SimpleConverter>(converter);
+		if (!converter_->isValid()) {
+			LOG(SimplePipeline, Warning)
+				<< "Failed to create converter, disabling format conversion";
+			converter_.reset();
+		} else {
+			converter_->inputBufferReady.connect(this, &SimpleCameraData::converterInputDone);
+			converter_->outputBufferReady.connect(this, &SimpleCameraData::converterOutputDone);
+		}
+	}
+
 	video_ = pipe->video(entities_.back().entity);
 	ASSERT(video_);
 
@@ -471,12 +487,12 @@ int SimpleCameraData::init()
 			config.captureFormat = pixelFormat;
 			config.captureSize = format.size;
 
-			if (!converter) {
+			if (!converter_) {
 				config.outputFormats = { pixelFormat };
 				config.outputSizes = config.captureSize;
 			} else {
-				config.outputFormats = converter->formats(pixelFormat);
-				config.outputSizes = converter->sizes(format.size);
+				config.outputFormats = converter_->formats(pixelFormat);
+				config.outputSizes = converter_->sizes(format.size);
 			}
 
 			configs_.push_back(config);
@@ -605,6 +621,20 @@ int SimpleCameraData::setupFormats(V4L2SubdeviceFormat *format,
 	return 0;
 }
 
+void SimpleCameraData::converterInputDone(FrameBuffer *buffer)
+{
+	/* Queue the input buffer back for capture. */
+	video_->queueBuffer(buffer);
+}
+
+void SimpleCameraData::converterOutputDone(FrameBuffer *buffer)
+{
+	/* Complete the buffer and the request. */
+	Request *request = buffer->request();
+	if (pipe_->completeBuffer(request, buffer))
+		pipe_->completeRequest(request);
+}
+
 /* -----------------------------------------------------------------------------
  * Camera Configuration
  */
@@ -650,11 +680,9 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()
 		}
 	}
 
-	/* Adjust the requested streams. */
-	SimplePipelineHandler *pipe = static_cast<SimplePipelineHandler *>(data_->pipe_);
-	SimpleConverter *converter = pipe->converter();
-
 	/*
+	 * Adjust the requested streams.
+	 *
 	 * Enable usage of the converter when producing multiple streams, as
 	 * the video capture device can't capture to multiple buffers.
 	 *
@@ -700,7 +728,8 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()
 		/* Set the stride, frameSize and bufferCount. */
 		if (needConversion_) {
 			std::tie(cfg.stride, cfg.frameSize) =
-				converter->strideAndFrameSize(cfg.pixelFormat, cfg.size);
+				data_->converter_->strideAndFrameSize(cfg.pixelFormat,
+								      cfg.size);
 			if (cfg.stride == 0)
 				return Invalid;
 		} else {
@@ -727,7 +756,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()
  */
 
 SimplePipelineHandler::SimplePipelineHandler(CameraManager *manager)
-	: PipelineHandler(manager)
+	: PipelineHandler(manager), converter_(nullptr)
 {
 }
 
@@ -841,7 +870,7 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)
 	inputCfg.stride = captureFormat.planes[0].bpl;
 	inputCfg.bufferCount = kNumInternalBuffers;
 
-	return converter_->configure(inputCfg, outputCfgs);
+	return data->converter_->configure(inputCfg, outputCfgs);
 }
 
 int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream,
@@ -855,8 +884,8 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream,
 	 * whether the converter is used or not.
 	 */
 	if (data->useConverter_)
-		return converter_->exportBuffers(data->streamIndex(stream),
-						 count, buffers);
+		return data->converter_->exportBuffers(data->streamIndex(stream),
+						       count, buffers);
 	else
 		return data->video_->exportBuffers(count, buffers);
 }
@@ -899,7 +928,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL
 	}
 
 	if (data->useConverter_) {
-		ret = converter_->start();
+		ret = data->converter_->start();
 		if (ret < 0) {
 			stop(camera);
 			return ret;
@@ -921,7 +950,7 @@ void SimplePipelineHandler::stop(Camera *camera)
 	V4L2VideoDevice *video = data->video_;
 
 	if (data->useConverter_)
-		converter_->stop();
+		data->converter_->stop();
 
 	video->streamOff();
 	video->releaseBuffers();
@@ -1028,7 +1057,6 @@ std::vector<MediaEntity *> SimplePipelineHandler::locateSensors()
 bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
 {
 	const SimplePipelineInfo *info = nullptr;
-	MediaDevice *converter = nullptr;
 	unsigned int numStreams = 1;
 
 	for (const SimplePipelineInfo &inf : supportedDevices) {
@@ -1045,8 +1073,8 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
 
 	for (const auto &[name, streams] : info->converters) {
 		DeviceMatch converterMatch(name);
-		converter = acquireMediaDevice(enumerator, converterMatch);
-		if (converter) {
+		converter_ = acquireMediaDevice(enumerator, converterMatch);
+		if (converter_) {
 			numStreams = streams;
 			break;
 		}
@@ -1059,19 +1087,6 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
 		return false;
 	}
 
-	/* Open the converter, if any. */
-	if (converter) {
-		converter_ = std::make_unique<SimpleConverter>(converter);
-		if (!converter_->isValid()) {
-			LOG(SimplePipeline, Warning)
-				<< "Failed to create converter, disabling format conversion";
-			converter_.reset();
-		} else {
-			converter_->inputBufferReady.connect(this, &SimplePipelineHandler::converterInputDone);
-			converter_->outputBufferReady.connect(this, &SimplePipelineHandler::converterOutputDone);
-		}
-	}
-
 	/*
 	 * Create one camera data instance for each sensor and gather all
 	 * entities in all pipelines.
@@ -1317,7 +1332,7 @@ void SimplePipelineHandler::bufferReady(FrameBuffer *buffer)
 			return;
 		}
 
-		converter_->queueBuffers(buffer, data->converterQueue_.front());
+		data->converter_->queueBuffers(buffer, data->converterQueue_.front());
 		data->converterQueue_.pop();
 		return;
 	}
@@ -1327,25 +1342,6 @@ void SimplePipelineHandler::bufferReady(FrameBuffer *buffer)
 	completeRequest(request);
 }
 
-void SimplePipelineHandler::converterInputDone(FrameBuffer *buffer)
-{
-	ASSERT(activeCamera_);
-	SimpleCameraData *data = cameraData(activeCamera_);
-
-	/* Queue the input buffer back for capture. */
-	data->video_->queueBuffer(buffer);
-}
-
-void SimplePipelineHandler::converterOutputDone(FrameBuffer *buffer)
-{
-	ASSERT(activeCamera_);
-
-	/* Complete the buffer and the request. */
-	Request *request = buffer->request();
-	if (completeBuffer(request, buffer))
-		completeRequest(request);
-}
-
 REGISTER_PIPELINE_HANDLER(SimplePipelineHandler)
 
 } /* namespace libcamera */
-- 
Regards,

Laurent Pinchart



More information about the libcamera-devel mailing list