[v2,2/4] libcamera: rkisp1: Replace usage of RkISP1FrameInfo
diff mbox series

Message ID 20240311123234.32925-3-jacopo.mondi@ideasonboard.com
State New
Headers show
Series
  • libcamera: Replace IPU3/RkISP1FrameInfo
Related show

Commit Message

Jacopo Mondi March 11, 2024, 12:32 p.m. UTC
Now that the pipeline handler can create a private derived class of
Request::Private, use it to store the pipeline specific data.

In the case of RkISP1 we associate the statistic and paramters buffers
with a Request.

As the IPA sends notifications for paramters and statistics buffer by
identifying them by frame id, associate the frame ids and the Request
in the RkISP1CameraData class.

This replaces the functionalities of RkISP1FrameInfo which can now be
removed.

Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Tested-by: Daniel Scally <dan.scally@ideasonboard.com>
---
 src/libcamera/pipeline/rkisp1/rkisp1.cpp | 359 +++++++++--------------
 1 file changed, 138 insertions(+), 221 deletions(-)

Patch
diff mbox series

diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
index 586b46d64630..0479e243d392 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
@@ -39,6 +39,7 @@ 
 #include "libcamera/internal/ipa_manager.h"
 #include "libcamera/internal/media_device.h"
 #include "libcamera/internal/pipeline_handler.h"
+#include "libcamera/internal/request.h"
 #include "libcamera/internal/v4l2_subdevice.h"
 #include "libcamera/internal/v4l2_videodevice.h"
 
@@ -48,67 +49,63 @@  namespace libcamera {
 
 LOG_DEFINE_CATEGORY(RkISP1)
 
-class PipelineHandlerRkISP1;
-class RkISP1CameraData;
+class RkISP1Request : public Request::Private
+{
+public:
+	RkISP1Request(Camera *camera)
+		: Request::Private(camera)
+	{
+	}
 
-struct RkISP1FrameInfo {
-	unsigned int frame;
-	Request *request;
+	bool hasPendingBuffers(bool isRaw) const;
 
-	FrameBuffer *paramBuffer;
 	FrameBuffer *statBuffer;
-	FrameBuffer *mainPathBuffer;
-	FrameBuffer *selfPathBuffer;
+	FrameBuffer *paramBuffer;
+
+	/* The frame number this request is associated with. */
+	unsigned int frame;
 
 	bool paramDequeued;
 	bool metadataProcessed;
 };
 
-class RkISP1Frames
+bool RkISP1Request::hasPendingBuffers(bool isRaw) const
 {
-public:
-	RkISP1Frames(PipelineHandler *pipe);
-
-	RkISP1FrameInfo *create(const RkISP1CameraData *data, Request *request,
-				bool isRaw);
-	int destroy(unsigned int frame);
-	void clear();
-
-	RkISP1FrameInfo *find(unsigned int frame);
-	RkISP1FrameInfo *find(FrameBuffer *buffer);
-	RkISP1FrameInfo *find(Request *request);
-
-private:
-	PipelineHandlerRkISP1 *pipe_;
-	std::map<unsigned int, RkISP1FrameInfo *> frameInfo_;
-};
+	return Request::Private::hasPendingBuffers() ||
+	       !metadataProcessed || (!isRaw && !paramDequeued);
+}
 
+class PipelineHandlerRkISP1;
 class RkISP1CameraData : public Camera::Private
 {
 public:
 	RkISP1CameraData(PipelineHandler *pipe, RkISP1MainPath *mainPath,
 			 RkISP1SelfPath *selfPath)
-		: Camera::Private(pipe), frame_(0), frameInfo_(pipe),
-		  mainPath_(mainPath), selfPath_(selfPath)
+		: Camera::Private(pipe), frame_(0), mainPath_(mainPath),
+		  selfPath_(selfPath)
 	{
 	}
 
 	PipelineHandlerRkISP1 *pipe();
 	int loadIPA(unsigned int hwRevision);
 
+	void addRequest(RkISP1Request *request);
+
 	Stream mainPathStream_;
 	Stream selfPathStream_;
 	std::unique_ptr<CameraSensor> sensor_;
 	std::unique_ptr<DelayedControls> delayedCtrls_;
 	unsigned int frame_;
 	std::vector<IPABuffer> ipaBuffers_;
-	RkISP1Frames frameInfo_;
 
 	RkISP1MainPath *mainPath_;
 	RkISP1SelfPath *selfPath_;
 
 	std::unique_ptr<ipa::rkisp1::IPAProxyRkISP1> ipa_;
 
+	/* Associate a frame id with a Request. */
+	std::map<unsigned int, RkISP1Request *> requestMap_;
+
 private:
 	void paramFilled(unsigned int frame);
 	void setSensorControls(unsigned int frame,
@@ -157,6 +154,8 @@  public:
 	int start(Camera *camera, const ControlList *controls) override;
 	void stopDevice(Camera *camera) override;
 
+	std::unique_ptr<Request> createRequestDevice(Camera *camera,
+						     uint64_t cookie) override;
 	int queueRequestDevice(Camera *camera, Request *request) override;
 
 	bool match(DeviceEnumerator *enumerator) override;
@@ -169,13 +168,17 @@  private:
 		return static_cast<RkISP1CameraData *>(camera->_d());
 	}
 
+	RkISP1Request *cameraRequest(Request *request)
+	{
+		return static_cast<RkISP1Request *>(request->_d());
+	}
+
 	friend RkISP1CameraData;
-	friend RkISP1Frames;
 
 	int initLinks(Camera *camera, const CameraSensor *sensor,
 		      const RkISP1CameraConfiguration &config);
 	int createCamera(MediaEntity *sensor);
-	void tryCompleteRequest(RkISP1FrameInfo *info);
+	void tryCompleteRequest(RkISP1Request *request);
 	void bufferReady(FrameBuffer *buffer);
 	void paramReady(FrameBuffer *buffer);
 	void statReady(FrameBuffer *buffer);
@@ -206,129 +209,6 @@  private:
 	const MediaPad *ispSink_;
 };
 
-RkISP1Frames::RkISP1Frames(PipelineHandler *pipe)
-	: pipe_(static_cast<PipelineHandlerRkISP1 *>(pipe))
-{
-}
-
-RkISP1FrameInfo *RkISP1Frames::create(const RkISP1CameraData *data, Request *request,
-				      bool isRaw)
-{
-	unsigned int frame = data->frame_;
-
-	FrameBuffer *paramBuffer = nullptr;
-	FrameBuffer *statBuffer = nullptr;
-
-	if (!isRaw) {
-		if (pipe_->availableParamBuffers_.empty()) {
-			LOG(RkISP1, Error) << "Parameters buffer underrun";
-			return nullptr;
-		}
-
-		if (pipe_->availableStatBuffers_.empty()) {
-			LOG(RkISP1, Error) << "Statistic buffer underrun";
-			return nullptr;
-		}
-
-		paramBuffer = pipe_->availableParamBuffers_.front();
-		pipe_->availableParamBuffers_.pop();
-
-		statBuffer = pipe_->availableStatBuffers_.front();
-		pipe_->availableStatBuffers_.pop();
-	}
-
-	FrameBuffer *mainPathBuffer = request->findBuffer(&data->mainPathStream_);
-	FrameBuffer *selfPathBuffer = request->findBuffer(&data->selfPathStream_);
-
-	RkISP1FrameInfo *info = new RkISP1FrameInfo;
-
-	info->frame = frame;
-	info->request = request;
-	info->paramBuffer = paramBuffer;
-	info->mainPathBuffer = mainPathBuffer;
-	info->selfPathBuffer = selfPathBuffer;
-	info->statBuffer = statBuffer;
-	info->paramDequeued = false;
-	info->metadataProcessed = false;
-
-	frameInfo_[frame] = info;
-
-	return info;
-}
-
-int RkISP1Frames::destroy(unsigned int frame)
-{
-	RkISP1FrameInfo *info = find(frame);
-	if (!info)
-		return -ENOENT;
-
-	pipe_->availableParamBuffers_.push(info->paramBuffer);
-	pipe_->availableStatBuffers_.push(info->statBuffer);
-
-	frameInfo_.erase(info->frame);
-
-	delete info;
-
-	return 0;
-}
-
-void RkISP1Frames::clear()
-{
-	for (const auto &entry : frameInfo_) {
-		RkISP1FrameInfo *info = entry.second;
-
-		pipe_->availableParamBuffers_.push(info->paramBuffer);
-		pipe_->availableStatBuffers_.push(info->statBuffer);
-
-		delete info;
-	}
-
-	frameInfo_.clear();
-}
-
-RkISP1FrameInfo *RkISP1Frames::find(unsigned int frame)
-{
-	auto itInfo = frameInfo_.find(frame);
-
-	if (itInfo != frameInfo_.end())
-		return itInfo->second;
-
-	LOG(RkISP1, Fatal) << "Can't locate info from frame";
-
-	return nullptr;
-}
-
-RkISP1FrameInfo *RkISP1Frames::find(FrameBuffer *buffer)
-{
-	for (auto &itInfo : frameInfo_) {
-		RkISP1FrameInfo *info = itInfo.second;
-
-		if (info->paramBuffer == buffer ||
-		    info->statBuffer == buffer ||
-		    info->mainPathBuffer == buffer ||
-		    info->selfPathBuffer == buffer)
-			return info;
-	}
-
-	LOG(RkISP1, Fatal) << "Can't locate info from buffer";
-
-	return nullptr;
-}
-
-RkISP1FrameInfo *RkISP1Frames::find(Request *request)
-{
-	for (auto &itInfo : frameInfo_) {
-		RkISP1FrameInfo *info = itInfo.second;
-
-		if (info->request == request)
-			return info;
-	}
-
-	LOG(RkISP1, Fatal) << "Can't locate info from request";
-
-	return nullptr;
-}
-
 PipelineHandlerRkISP1 *RkISP1CameraData::pipe()
 {
 	return static_cast<PipelineHandlerRkISP1 *>(Camera::Private::pipe());
@@ -379,23 +259,34 @@  int RkISP1CameraData::loadIPA(unsigned int hwRevision)
 	return 0;
 }
 
+void RkISP1CameraData::addRequest(RkISP1Request *request)
+{
+	/* Associate the request and the frame number. */
+	request->frame = frame_;
+	requestMap_[frame_] = request;
+	frame_++;
+}
+
 void RkISP1CameraData::paramFilled(unsigned int frame)
 {
 	PipelineHandlerRkISP1 *pipe = RkISP1CameraData::pipe();
-	RkISP1FrameInfo *info = frameInfo_.find(frame);
-	if (!info)
-		return;
+	RkISP1Request *request = requestMap_.at(frame);
+	ASSERT(request);
 
-	info->paramBuffer->_d()->metadata().planes()[0].bytesused =
+	request->paramBuffer->_d()->metadata().planes()[0].bytesused =
 		sizeof(struct rkisp1_params_cfg);
-	pipe->param_->queueBuffer(info->paramBuffer);
-	pipe->stat_->queueBuffer(info->statBuffer);
-
-	if (info->mainPathBuffer)
-		mainPath_->queueBuffer(info->mainPathBuffer);
-
-	if (selfPath_ && info->selfPathBuffer)
-		selfPath_->queueBuffer(info->selfPathBuffer);
+	pipe->param_->queueBuffer(request->paramBuffer);
+	pipe->stat_->queueBuffer(request->statBuffer);
+
+	FrameBuffer *mainPathBuffer =
+		request->_o<Request>()->findBuffer(&mainPathStream_);
+	if (mainPathBuffer)
+		mainPath_->queueBuffer(mainPathBuffer);
+
+	FrameBuffer *selfPathBuffer =
+		request->_o<Request>()->findBuffer(&selfPathStream_);
+	if (selfPath_ && selfPathBuffer)
+		selfPath_->queueBuffer(selfPathBuffer);
 }
 
 void RkISP1CameraData::setSensorControls([[maybe_unused]] unsigned int frame,
@@ -406,14 +297,13 @@  void RkISP1CameraData::setSensorControls([[maybe_unused]] unsigned int frame,
 
 void RkISP1CameraData::metadataReady(unsigned int frame, const ControlList &metadata)
 {
-	RkISP1FrameInfo *info = frameInfo_.find(frame);
-	if (!info)
-		return;
+	RkISP1Request *request = requestMap_.at(frame);
+	ASSERT(request);
 
-	info->request->metadata().merge(metadata);
-	info->metadataProcessed = true;
+	request->_o<Request>()->metadata().merge(metadata);
+	request->metadataProcessed = true;
 
-	pipe()->tryCompleteRequest(info);
+	pipe()->tryCompleteRequest(request);
 }
 
 /* -----------------------------------------------------------------------------
@@ -1013,34 +903,77 @@  void PipelineHandlerRkISP1::stopDevice(Camera *camera)
 	}
 
 	ASSERT(data->queuedRequests_.empty());
-	data->frameInfo_.clear();
+	data->requestMap_.clear();
 
 	freeBuffers(camera);
 
 	activeCamera_ = nullptr;
 }
 
+std::unique_ptr<Request> PipelineHandlerRkISP1::createRequestDevice(Camera *camera,
+								    uint64_t cookie)
+{
+	auto request = std::make_unique<RkISP1Request>(camera);
+	return Request::create(std::move(request), cookie);
+}
+
 int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request)
 {
 	RkISP1CameraData *data = cameraData(camera);
+	RkISP1Request *rkisp1Request = cameraRequest(request);
 
-	RkISP1FrameInfo *info = data->frameInfo_.create(data, request, isRaw_);
-	if (!info)
-		return -ENOENT;
+	data->addRequest(rkisp1Request);
+	data->ipa_->queueRequest(rkisp1Request->frame, request->controls());
 
-	data->ipa_->queueRequest(data->frame_, request->controls());
+	/*
+	 * If we're operating in RAW mode (only one RAW stream is captured)
+	 * then we simply queue buffers to the video devices as we don't
+	 * need to run the IPA.
+	 */
 	if (isRaw_) {
-		if (info->mainPathBuffer)
-			data->mainPath_->queueBuffer(info->mainPathBuffer);
+		FrameBuffer *mainPathBuffer =
+			request->findBuffer(&data->mainPathStream_);
+		if (mainPathBuffer)
+			data->mainPath_->queueBuffer(mainPathBuffer);
 
-		if (data->selfPath_ && info->selfPathBuffer)
-			data->selfPath_->queueBuffer(info->selfPathBuffer);
-	} else {
-		data->ipa_->fillParamsBuffer(data->frame_,
-					     info->paramBuffer->cookie());
+		FrameBuffer *selfPathBuffer =
+			request->findBuffer(&data->selfPathStream_);
+		if (data->selfPath_ && selfPathBuffer)
+			data->selfPath_->queueBuffer(selfPathBuffer);
+
+		return 0;
+	}
+
+	/*
+	 * If we run the IPA we need to associate a parameters and a statistics
+	 * buffer with the Request and associate the request with the current
+	 * frame number.
+	 *
+	 * Associate the stat and frame buffers to a Request (if available)
+	 * and then run the IPA.
+	 */
+	if (availableParamBuffers_.empty()) {
+		LOG(RkISP1, Error) << "Parameters buffer underrun";
+		return -ENOENT;
+	}
+
+	if (availableStatBuffers_.empty()) {
+		LOG(RkISP1, Error) << "Statistic buffer underrun";
+		return -ENOENT;
 	}
 
-	data->frame_++;
+	rkisp1Request->paramBuffer = availableParamBuffers_.front();
+	rkisp1Request->paramDequeued = false;
+	rkisp1Request->paramBuffer->_d()->setRequest(request);
+	availableParamBuffers_.pop();
+
+	rkisp1Request->statBuffer = availableStatBuffers_.front();
+	rkisp1Request->metadataProcessed = false;
+	rkisp1Request->statBuffer->_d()->setRequest(request);
+	availableStatBuffers_.pop();
+
+	data->ipa_->fillParamsBuffer(rkisp1Request->frame,
+				     rkisp1Request->paramBuffer->cookie());
 
 	return 0;
 }
@@ -1232,37 +1165,28 @@  bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator)
  * Buffer Handling
  */
 
-void PipelineHandlerRkISP1::tryCompleteRequest(RkISP1FrameInfo *info)
+void PipelineHandlerRkISP1::tryCompleteRequest(RkISP1Request *request)
 {
 	RkISP1CameraData *data = cameraData(activeCamera_);
-	Request *request = info->request;
 
-	if (request->hasPendingBuffers())
+	if (request->hasPendingBuffers(isRaw_))
 		return;
 
-	if (!info->metadataProcessed)
-		return;
+	/* Return the stat and param buffers to the pipeline. */
+	availableParamBuffers_.push(request->paramBuffer);
+	availableStatBuffers_.push(request->statBuffer);
+	data->requestMap_.erase(request->frame);
 
-	if (!isRaw_ && !info->paramDequeued)
-		return;
-
-	data->frameInfo_.destroy(info->frame);
-
-	completeRequest(request);
+	completeRequest(request->_o<Request>());
 }
 
 void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer)
 {
 	ASSERT(activeCamera_);
 	RkISP1CameraData *data = cameraData(activeCamera_);
-
-	RkISP1FrameInfo *info = data->frameInfo_.find(buffer);
-	if (!info)
-		return;
+	RkISP1Request *request = cameraRequest(buffer->request());
 
 	const FrameMetadata &metadata = buffer->metadata();
-	Request *request = buffer->request();
-
 	if (metadata.status != FrameMetadata::FrameCancelled) {
 		/*
 		 * Record the sensor's timestamp in the request metadata.
@@ -1270,55 +1194,48 @@  void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer)
 		 * \todo The sensor timestamp should be better estimated by connecting
 		 * to the V4L2Device::frameStart signal.
 		 */
-		request->metadata().set(controls::SensorTimestamp,
-					metadata.timestamp);
+		request->_o<Request>()->metadata().set(controls::SensorTimestamp,
+						       metadata.timestamp);
 
 		if (isRaw_) {
 			const ControlList &ctrls =
 				data->delayedCtrls_->get(metadata.sequence);
-			data->ipa_->processStatsBuffer(info->frame, 0, ctrls);
+			data->ipa_->processStatsBuffer(request->frame, 0, ctrls);
 		}
 	} else {
 		if (isRaw_)
-			info->metadataProcessed = true;
+			request->metadataProcessed = true;
 	}
 
-	completeBuffer(request, buffer);
-	tryCompleteRequest(info);
+	completeBuffer(request->_o<Request>(), buffer);
+	tryCompleteRequest(request);
 }
 
 void PipelineHandlerRkISP1::paramReady(FrameBuffer *buffer)
 {
 	ASSERT(activeCamera_);
-	RkISP1CameraData *data = cameraData(activeCamera_);
+	RkISP1Request *request = cameraRequest(buffer->request());
 
-	RkISP1FrameInfo *info = data->frameInfo_.find(buffer);
-	if (!info)
-		return;
-
-	info->paramDequeued = true;
-	tryCompleteRequest(info);
+	request->paramDequeued = true;
+	tryCompleteRequest(request);
 }
 
 void PipelineHandlerRkISP1::statReady(FrameBuffer *buffer)
 {
 	ASSERT(activeCamera_);
 	RkISP1CameraData *data = cameraData(activeCamera_);
-
-	RkISP1FrameInfo *info = data->frameInfo_.find(buffer);
-	if (!info)
-		return;
+	RkISP1Request *request = cameraRequest(buffer->request());
 
 	if (buffer->metadata().status == FrameMetadata::FrameCancelled) {
-		info->metadataProcessed = true;
-		tryCompleteRequest(info);
+		request->metadataProcessed = true;
+		tryCompleteRequest(request);
 		return;
 	}
 
 	if (data->frame_ <= buffer->metadata().sequence)
 		data->frame_ = buffer->metadata().sequence + 1;
 
-	data->ipa_->processStatsBuffer(info->frame, info->statBuffer->cookie(),
+	data->ipa_->processStatsBuffer(request->frame, request->statBuffer->cookie(),
 				       data->delayedCtrls_->get(buffer->metadata().sequence));
 }