[libcamera-devel] [PATCH] android: Implement flush()

Hirokazu Honda hiroh at chromium.org
Tue Apr 6 11:13:34 CEST 2021


This implements camera3_device_ops::flush().

Signed-off-by: Hirokazu Honda <hiroh at chromium.org>
---
 src/android/camera_device.cpp | 48 +++++++++++++++++++++++++++++++----
 src/android/camera_device.h   |  3 +++
 src/android/camera_ops.cpp    |  3 ++-
 3 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
index 4a3f6f8e..5a56fe4b 100644
--- a/src/android/camera_device.cpp
+++ b/src/android/camera_device.cpp
@@ -2029,20 +2029,22 @@ void CameraDevice::requestComplete(Request *request)
 	camera3_buffer_status status = CAMERA3_BUFFER_STATUS_OK;
 	std::unique_ptr<CameraMetadata> resultMetadata;
 
-	decltype(descriptors_)::node_type node;
+	Camera3RequestDescriptor descriptor;
 	{
 		std::scoped_lock<std::mutex> lock(mutex_);
 		auto it = descriptors_.find(request->cookie());
 		if (it == descriptors_.end()) {
 			LOG(HAL, Fatal)
 				<< "Unknown request: " << request->cookie();
-			status = CAMERA3_BUFFER_STATUS_ERROR;
 			return;
 		}
 
-		node = descriptors_.extract(it);
+		descriptor = std::move(it->second);
+		/* Restore frameNumber_ because it is used in the case of flush
+		 * timeout case.
+		 */
+		it->second.frameNumber_ = descriptor.frameNumber_;
 	}
-	Camera3RequestDescriptor &descriptor = node.mapped();
 
 	if (request->status() != Request::RequestComplete) {
 		LOG(HAL, Error) << "Request not successfully completed: "
@@ -2122,7 +2124,43 @@ void CameraDevice::requestComplete(Request *request)
 			    descriptor.buffers_[0].stream);
 	}
 
-	callbacks_->process_capture_result(callbacks_, &captureResult);
+	{
+		std::scoped_lock<std::mutex> lock(mutex_);
+		if (descriptors_.erase(request->cookie()) == 0) {
+			// flush() cleans up the descriptor due to time out
+			// during a post processing.
+			return;
+		}
+		callbacks_->process_capture_result(callbacks_, &captureResult);
+		conditionVariable_.notify_one();
+	}
+}
+
+int CameraDevice::flush()
+{
+	std::unique_lock<std::mutex> lock(mutex_);
+	/* flush() should return in less than one second. Sets the timeout to 900ms. */
+	auto flushTimeout =
+		std::chrono::system_clock::now() + std::chrono::milliseconds(900);
+	bool completeAllRequests = conditionVariable_.wait_until(
+		lock, flushTimeout, [this]() { return descriptors_.empty(); });
+
+	if (!completeAllRequests) {
+		for (auto &node : descriptors_) {
+			auto &descriptor = node.second;
+			camera3_capture_result_t captureResult{};
+			captureResult.frame_number = descriptor.frameNumber_;
+			for (camera3_stream_buffer_t &buffer : descriptor.buffers_) {
+				buffer.acquire_fence = -1;
+				buffer.release_fence = -1;
+				buffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+			}
+			callbacks_->process_capture_result(callbacks_, &captureResult);
+		}
+		descriptors_.clear();
+	}
+
+	return 0;
 }
 
 std::string CameraDevice::logPrefix() const
diff --git a/src/android/camera_device.h b/src/android/camera_device.h
index c63e8e21..dd5336ee 100644
--- a/src/android/camera_device.h
+++ b/src/android/camera_device.h
@@ -7,6 +7,7 @@
 #ifndef __ANDROID_CAMERA_DEVICE_H__
 #define __ANDROID_CAMERA_DEVICE_H__
 
+#include <condition_variable>
 #include <map>
 #include <memory>
 #include <mutex>
@@ -62,6 +63,7 @@ public:
 	int configureStreams(camera3_stream_configuration_t *stream_list);
 	int processCaptureRequest(camera3_capture_request_t *request);
 	void requestComplete(libcamera::Request *request);
+	int flush();
 
 protected:
 	std::string logPrefix() const override;
@@ -128,6 +130,7 @@ private:
 	std::vector<CameraStream> streams_;
 
 	std::mutex mutex_; /* Protect descriptors_ */
+	std::condition_variable conditionVariable_;
 	std::map<uint64_t, Camera3RequestDescriptor> descriptors_;
 
 	std::string maker_;
diff --git a/src/android/camera_ops.cpp b/src/android/camera_ops.cpp
index 696e8043..1b73af13 100644
--- a/src/android/camera_ops.cpp
+++ b/src/android/camera_ops.cpp
@@ -68,7 +68,8 @@ static void hal_dev_dump([[maybe_unused]] const struct camera3_device *dev,
 
 static int hal_dev_flush([[maybe_unused]] const struct camera3_device *dev)
 {
-	return 0;
+	CameraDevice *camera = reinterpret_cast<CameraDevice *>(dev->priv);
+	return camera->flush();
 }
 
 int hal_dev_close(hw_device_t *hw_device)
-- 
2.31.0.208.g409f899ff0-goog



More information about the libcamera-devel mailing list