summaryrefslogtreecommitdiff
path: root/src/android/camera_device.cpp
diff options
context:
space:
mode:
authorJacopo Mondi <jacopo@jmondi.org>2021-05-10 10:13:36 +0200
committerJacopo Mondi <jacopo@jmondi.org>2021-06-14 12:26:28 +0200
commitefd5fb7288a7a9c72f3ae7b1256c2b808aaf525f (patch)
tree7e034a7a29c2be7b4c6ca423fbd67a3349226bc9 /src/android/camera_device.cpp
parent103dfb85a7e12c00c1a41eef69f45faa8f5c7597 (diff)
android: Implement flush() camera operation
Implement the flush() camera operation in the CameraDevice class and make it available to the camera framework by implementing the operation wrapper in camera_ops.cpp. Introduce a new camera state State::Flushing to handle concurrent flush() and process_capture_request() calls. As flush() can race with processCaptureRequest() protect it by introducing a new State::Flushing state that processCaptureRequest() inspects before queuing the Request to the Camera. If flush() is in progress while processCaptureRequest() is called, return the current Request immediately in error state. If flush() has completed and a new call to processCaptureRequest() is made just after, start the camera again before queuing the request. Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Hirokazu Honda <hiroh@chromium.org> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'src/android/camera_device.cpp')
-rw-r--r--src/android/camera_device.cpp77
1 files changed, 61 insertions, 16 deletions
diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
index b29c1edc..52317037 100644
--- a/src/android/camera_device.cpp
+++ b/src/android/camera_device.cpp
@@ -798,6 +798,23 @@ void CameraDevice::close()
camera_->release();
}
+void CameraDevice::flush()
+{
+ {
+ MutexLocker stateLock(stateMutex_);
+ if (state_ != State::Running)
+ return;
+
+ state_ = State::Flushing;
+ }
+
+ worker_.stop();
+ camera_->stop();
+
+ MutexLocker stateLock(stateMutex_);
+ state_ = State::Stopped;
+}
+
void CameraDevice::stop()
{
MutexLocker stateLock(stateMutex_);
@@ -1896,27 +1913,31 @@ int CameraDevice::processControls(Camera3RequestDescriptor *descriptor)
return 0;
}
-int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Request)
+void CameraDevice::abortRequest(camera3_capture_request_t *request)
{
- if (!isValidRequest(camera3Request))
- return -EINVAL;
+ notifyError(request->frame_number, nullptr, CAMERA3_MSG_ERROR_REQUEST);
- {
- MutexLocker stateLock(stateMutex_);
+ camera3_capture_result_t result = {};
+ result.num_output_buffers = request->num_output_buffers;
+ result.frame_number = request->frame_number;
+ result.partial_result = 0;
- /* Start the camera if that's the first request we handle. */
- if (state_ == State::Stopped) {
- worker_.start();
+ std::vector<camera3_stream_buffer_t> resultBuffers(result.num_output_buffers);
+ for (auto [i, buffer] : utils::enumerate(resultBuffers)) {
+ buffer = request->output_buffers[i];
+ buffer.release_fence = request->output_buffers[i].acquire_fence;
+ buffer.acquire_fence = -1;
+ buffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+ }
+ result.output_buffers = resultBuffers.data();
- int ret = camera_->start();
- if (ret) {
- LOG(HAL, Error) << "Failed to start camera";
- return ret;
- }
+ callbacks_->process_capture_result(callbacks_, &result);
+}
- state_ = State::Running;
- }
- }
+int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Request)
+{
+ if (!isValidRequest(camera3Request))
+ return -EINVAL;
/*
* Save the request descriptors for use at completion time.
@@ -2006,6 +2027,30 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques
if (ret)
return ret;
+ /*
+ * If flush is in progress abort the request. If the camera has been
+ * stopped we have to re-start it to be able to process the request.
+ */
+ MutexLocker stateLock(stateMutex_);
+
+ if (state_ == State::Flushing) {
+ abortRequest(camera3Request);
+ return 0;
+ }
+
+ if (state_ == State::Stopped) {
+ worker_.start();
+
+ ret = camera_->start();
+ if (ret) {
+ LOG(HAL, Error) << "Failed to start camera";
+ worker_.stop();
+ return ret;
+ }
+
+ state_ = State::Running;
+ }
+
worker_.queueRequest(descriptor.request_.get());
{