[v3,1/5] libcamera: pipeline_handler: Move waitingRequests_ into camera class
diff mbox series

Message ID 20250717125931.2848300-2-stefan.klug@ideasonboard.com
State New
Headers show
Series
  • rkisp1: Allow usage of more than 4 buffers
Related show

Commit Message

Stefan Klug July 17, 2025, 12:59 p.m. UTC
The waiting requests of one camera should not be able to influence
queuing to another camera. Currently a request that is in the
waitingQueue and waiting for preparation blocks all requests of other
cameras even if they are already prepared. To fix that replace the
single waitingRequests_ queue with one queue per camera.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Umang Jain <uajain@igalia.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Tested-By: Sven Püschel<s.pueschel@pengutronix.de>

---

Changes in v3:
- Collected tag

Changes in v2:
- Fixed capturing on lambda expression
- Added documentation for waitingRequests_
- Improved commit message

Changes in v1:
- Added camera param to doQueueRequests() which allows to remove a loop
---
 include/libcamera/internal/camera.h           |  2 ++
 include/libcamera/internal/pipeline_handler.h |  5 +---
 src/libcamera/camera.cpp                      |  9 +++++++
 src/libcamera/pipeline_handler.cpp            | 26 ++++++++++++-------
 4 files changed, 28 insertions(+), 14 deletions(-)

Patch
diff mbox series

diff --git a/include/libcamera/internal/camera.h b/include/libcamera/internal/camera.h
index 18f5c32a18e4..8a2e9ed5894d 100644
--- a/include/libcamera/internal/camera.h
+++ b/include/libcamera/internal/camera.h
@@ -10,6 +10,7 @@ 
 #include <atomic>
 #include <list>
 #include <memory>
+#include <queue>
 #include <set>
 #include <stdint.h>
 #include <string>
@@ -36,6 +37,7 @@  public:
 	const PipelineHandler *pipe() const { return pipe_.get(); }
 
 	std::list<Request *> queuedRequests_;
+	std::queue<Request *> waitingRequests_;
 	ControlInfoMap controlInfo_;
 	ControlList properties_;
 
diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h
index 972a2fa65310..be017ad47219 100644
--- a/include/libcamera/internal/pipeline_handler.h
+++ b/include/libcamera/internal/pipeline_handler.h
@@ -8,7 +8,6 @@ 
 #pragma once
 
 #include <memory>
-#include <queue>
 #include <string>
 #include <sys/types.h>
 #include <vector>
@@ -89,13 +88,11 @@  private:
 	virtual void disconnect();
 
 	void doQueueRequest(Request *request);
-	void doQueueRequests();
+	void doQueueRequests(Camera *camera);
 
 	std::vector<std::shared_ptr<MediaDevice>> mediaDevices_;
 	std::vector<std::weak_ptr<Camera>> cameras_;
 
-	std::queue<Request *> waitingRequests_;
-
 	const char *name_;
 	unsigned int useCount_;
 
diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp
index c180a5fdde93..2ae50eaeaa5a 100644
--- a/src/libcamera/camera.cpp
+++ b/src/libcamera/camera.cpp
@@ -628,6 +628,15 @@  Camera::Private::~Private()
  * PipelineHandler::completeRequest()
  */
 
+/**
+ * \var Camera::Private::waitingRequests_
+ * \brief The queue of waiting requests
+ *
+ * This queue tracks all requests that can not yet be queued to the device.
+ * Either because they are not yet prepared or because the maximum number of
+ * queued requests was reached.
+ */
+
 /**
  * \var Camera::Private::controlInfo_
  * \brief The set of controls supported by the camera
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index d84dff3c9f19..b50eda5e0f86 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -363,15 +363,16 @@  void PipelineHandler::stop(Camera *camera)
 	/* Stop the pipeline handler and let the queued requests complete. */
 	stopDevice(camera);
 
+	Camera::Private *data = camera->_d();
+
 	/* Cancel and signal as complete all waiting requests. */
-	while (!waitingRequests_.empty()) {
-		Request *request = waitingRequests_.front();
-		waitingRequests_.pop();
+	while (!data->waitingRequests_.empty()) {
+		Request *request = data->waitingRequests_.front();
+		data->waitingRequests_.pop();
 		cancelRequest(request);
 	}
 
 	/* Make sure no requests are pending. */
-	Camera::Private *data = camera->_d();
 	ASSERT(data->queuedRequests_.empty());
 
 	data->requestSequence_ = 0;
@@ -414,7 +415,9 @@  void PipelineHandler::registerRequest(Request *request)
 	 * Connect the request prepared signal to notify the pipeline handler
 	 * when a request is ready to be processed.
 	 */
-	request->_d()->prepared.connect(this, &PipelineHandler::doQueueRequests);
+	request->_d()->prepared.connect(this, [this, request]() {
+		doQueueRequests(request->_d()->camera());
+	});
 }
 
 /**
@@ -444,7 +447,9 @@  void PipelineHandler::queueRequest(Request *request)
 {
 	LIBCAMERA_TRACEPOINT(request_queue, request);
 
-	waitingRequests_.push(request);
+	Camera *camera = request->_d()->camera();
+	Camera::Private *data = camera->_d();
+	data->waitingRequests_.push(request);
 
 	request->_d()->prepare(300ms);
 }
@@ -478,15 +483,16 @@  void PipelineHandler::doQueueRequest(Request *request)
  * Iterate the list of waiting requests and queue them to the device one
  * by one if they have been prepared.
  */
-void PipelineHandler::doQueueRequests()
+void PipelineHandler::doQueueRequests(Camera *camera)
 {
-	while (!waitingRequests_.empty()) {
-		Request *request = waitingRequests_.front();
+	Camera::Private *data = camera->_d();
+	while (!data->waitingRequests_.empty()) {
+		Request *request = data->waitingRequests_.front();
 		if (!request->_d()->prepared_)
 			break;
 
 		doQueueRequest(request);
-		waitingRequests_.pop();
+		data->waitingRequests_.pop();
 	}
 }