[libcamera-devel,v2,1/7] libcamera: Camera: Add RequestCompletionMode to configure the completion order
diff mbox series

Message ID 20220812090838.1784703-2-hanlinchen@chromium.org
State New
Headers show
Series
  • Implement Android Partial Result Featrue
Related show

Commit Message

Hanlin Chen Aug. 12, 2022, 9:08 a.m. UTC
Add enum RequestCompletionMode to Camera with two value: InSubmissionOrder and
Immediately. The purpose is to allow the application configure the order of
signaling requestCompleted. The InSubmissionOrder mode is the default mode which
signals according to the request submission order. The Immediately mode allows
the pipeline handler to signal as soon as a request is completed. Applications
need to reconstruct the order by self.

Signed-off-by: Han-Lin Chen <hanlinchen@chromium.org>
---
 include/libcamera/camera.h          |  8 ++++
 include/libcamera/internal/camera.h |  4 ++
 src/libcamera/camera.cpp            | 68 ++++++++++++++++++++++++++++-
 src/libcamera/pipeline_handler.cpp  | 20 ++++++---
 4 files changed, 92 insertions(+), 8 deletions(-)

Patch
diff mbox series

diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h
index 5bb06584..5aa4bf69 100644
--- a/include/libcamera/camera.h
+++ b/include/libcamera/camera.h
@@ -88,6 +88,11 @@  class Camera final : public Object, public std::enable_shared_from_this<Camera>,
 	LIBCAMERA_DECLARE_PRIVATE()
 
 public:
+	enum RequestCompletionMode {
+		InSubmissionOrder,
+		Immediately,
+	};
+
 	static std::shared_ptr<Camera> create(std::unique_ptr<Private> d,
 					      const std::string &id,
 					      const std::set<Stream *> &streams);
@@ -101,6 +106,9 @@  public:
 	int acquire();
 	int release();
 
+	int setRequestCompletionMode(RequestCompletionMode order);
+	RequestCompletionMode requestCompletionMode() const;
+
 	const ControlInfoMap &controls() const;
 	const ControlList &properties() const;
 
diff --git a/include/libcamera/internal/camera.h b/include/libcamera/internal/camera.h
index 597426a6..68e8d952 100644
--- a/include/libcamera/internal/camera.h
+++ b/include/libcamera/internal/camera.h
@@ -33,6 +33,9 @@  public:
 
 	PipelineHandler *pipe() { return pipe_.get(); }
 
+	void setRequestCompletionMode(RequestCompletionMode mode);
+	RequestCompletionMode requestCompletionMode() const;
+
 	std::list<Request *> queuedRequests_;
 	ControlInfoMap controlInfo_;
 	ControlList properties_;
@@ -67,6 +70,7 @@  private:
 
 	bool disconnected_;
 	std::atomic<State> state_;
+	RequestCompletionMode requestCompletionMode_;
 
 	std::unique_ptr<CameraControlValidator> validator_;
 };
diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp
index 2a8ef60e..4d3523e2 100644
--- a/src/libcamera/camera.cpp
+++ b/src/libcamera/camera.cpp
@@ -435,7 +435,8 @@  CameraConfiguration::Status CameraConfiguration::validateColorSpaces(ColorSpaceF
  */
 Camera::Private::Private(PipelineHandler *pipe)
 	: requestSequence_(0), pipe_(pipe->shared_from_this()),
-	  disconnected_(false), state_(CameraAvailable)
+	  disconnected_(false), state_(CameraAvailable),
+	  requestCompletionMode_(Camera::InSubmissionOrder)
 {
 }
 
@@ -573,6 +574,28 @@  void Camera::Private::setState(State state)
 	state_.store(state, std::memory_order_release);
 }
 
+/**
+ * \brief Set the request completion mode
+ * \param[in] mode The RequestCompletionMode
+ *
+ * This function set the request completion mode.
+ * InSubmissionOrder is the default mode.
+ */
+void Camera::Private::setRequestCompletionMode(RequestCompletionMode mode)
+{
+	requestCompletionMode_ = mode;
+}
+
+/**
+ * \brief Get the request completion mode
+ *
+ * \return The current RequestCompletionMode.
+ */
+Camera::RequestCompletionMode Camera::Private::requestCompletionMode() const
+{
+	return requestCompletionMode_;
+}
+
 /**
  * \class Camera
  * \brief Camera device
@@ -702,6 +725,15 @@  std::shared_ptr<Camera> Camera::create(std::unique_ptr<Private> d,
 	return std::shared_ptr<Camera>(camera, Deleter());
 }
 
+/**
+ * \enum Camera::RequestCompletionMode
+ * \brief The mode of request completion behavior
+ * \var Camera::RequestCompletionMode::InSubmissionOrder
+ * \brief requestCompleted will be emited according to the request submission order
+ * \var Camera::RequestCompletionMode::Immediately
+ * \brief requestCompleted will be emited immediately when a request is completed.
+ */
+
 /**
  * \brief Retrieve the ID of the camera
  *
@@ -1237,6 +1269,40 @@  int Camera::stop()
 	return 0;
 }
 
+/**
+ * \brief Set the request completion mode
+ * \param[in] mode The RequestCompletionMode
+ *
+ * This function set the request completion mode.
+ * InSubmissionOrder is the default mode.
+ *
+ * \return 0 on success or a negative error code otherwise
+ * \retval -EACCES The camera is running so can't change the behavior
+ */
+int Camera::setRequestCompletionMode(RequestCompletionMode mode)
+{
+	Private *const d = _d();
+
+	int ret = d->isAccessAllowed(Private::CameraAvailable,
+				     Private::CameraConfigured);
+	if (ret < 0)
+		return -EACCES;
+
+	d->setRequestCompletionMode(mode);
+
+	return 0;
+}
+
+/**
+ * \brief Get the request completion mode
+ *
+ * \return The current RequestCompletionMode.
+ */
+Camera::RequestCompletionMode Camera::requestCompletionMode() const
+{
+	return _d()->requestCompletionMode();
+}
+
 /**
  * \brief Handle request completion and notify application
  * \param[in] request The request that has completed
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index 67540533..7c180a8e 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -494,14 +494,20 @@  void PipelineHandler::completeRequest(Request *request)
 
 	Camera::Private *data = camera->_d();
 
-	while (!data->queuedRequests_.empty()) {
-		Request *req = data->queuedRequests_.front();
-		if (req->status() == Request::RequestPending)
-			break;
+	auto iter = data->queuedRequests_.begin();
+	while (iter != data->queuedRequests_.end()) {
+		if ((*iter)->status() != Request::RequestPending) {
+			ASSERT(!(*iter)->hasPendingBuffers());
+			camera->requestComplete((*iter));
+			iter = data->queuedRequests_.erase(iter);
+			continue;
+		}
 
-		ASSERT(!req->hasPendingBuffers());
-		data->queuedRequests_.pop_front();
-		camera->requestComplete(req);
+		/* Break at the pending result to reflect the submission order */
+		if (camera->requestCompletionMode() == Camera::InSubmissionOrder) {
+			break;
+		}
+		iter++;
 	}
 }