diff options
-rw-r--r-- | src/android/camera_device.cpp | 77 | ||||
-rw-r--r-- | src/android/camera_device.h | 3 | ||||
-rw-r--r-- | src/android/camera_ops.cpp | 8 |
3 files changed, 71 insertions, 17 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()); { diff --git a/src/android/camera_device.h b/src/android/camera_device.h index c949fa50..4aadb27c 100644 --- a/src/android/camera_device.h +++ b/src/android/camera_device.h @@ -43,6 +43,7 @@ public: int open(const hw_module_t *hardwareModule); void close(); + void flush(); unsigned int id() const { return id_; } camera3_device_t *camera3Device() { return &camera3Device_; } @@ -92,6 +93,7 @@ private: enum class State { Stopped, + Flushing, Running, }; @@ -106,6 +108,7 @@ private: getRawResolutions(const libcamera::PixelFormat &pixelFormat); libcamera::FrameBuffer *createFrameBuffer(const buffer_handle_t camera3buffer); + void abortRequest(camera3_capture_request_t *request); void notifyShutter(uint32_t frameNumber, uint64_t timestamp); void notifyError(uint32_t frameNumber, camera3_stream_t *stream, camera3_error_msg_code code); diff --git a/src/android/camera_ops.cpp b/src/android/camera_ops.cpp index 696e8043..8a3cfa17 100644 --- a/src/android/camera_ops.cpp +++ b/src/android/camera_ops.cpp @@ -66,8 +66,14 @@ static void hal_dev_dump([[maybe_unused]] const struct camera3_device *dev, { } -static int hal_dev_flush([[maybe_unused]] const struct camera3_device *dev) +static int hal_dev_flush(const struct camera3_device *dev) { + if (!dev) + return -EINVAL; + + CameraDevice *camera = reinterpret_cast<CameraDevice *>(dev->priv); + camera->flush(); + return 0; } |