[libcamera-devel] [PATCH 03/11] android: camera_device: Build capture_result dynamically
Umang Jain
umang.jain at ideasonboard.com
Mon Oct 18 18:12:24 CEST 2021
Hi Jacopo
On 10/18/21 9:18 PM, Jacopo Mondi wrote:
> Hi Umang,
>
> On Mon, Oct 18, 2021 at 06:59:15PM +0530, Umang Jain wrote:
>> From: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
>>
>> The camera3_capture_result_t is only needed to convey capture results to
>> the camera service through the process_capture_result() callback.
>> There's no need to store it in the Camera3RequestDescriptor. Build it
>> dynamically in CameraDevice::sendCaptureResults() instead.
>>
>> This requires storing the result metadata created in
>> CameraDevice::requestComplete() in the Camera3RequestDescriptor. A side
>> effect of this change is that the request metadata lifetime will match
>> the Camera3RequestDescriptor instead of being destroyed at the end of
>> requestComplete(). This will be needed to support asynchronous
>> post-processing, where the request completion will be signaled to the
>> camera service asynchronously from requestComplete().
>>
>> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
>> Signed-off-by: Umang Jain <umang.jain at ideasonboard.com>
>> ---
>> src/android/camera_device.cpp | 43 ++++++++++++++++-------------------
>> src/android/camera_request.h | 2 +-
>> 2 files changed, 21 insertions(+), 24 deletions(-)
>>
>> diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
>> index b4ab5da1..c6ae8930 100644
>> --- a/src/android/camera_device.cpp
>> +++ b/src/android/camera_device.cpp
>> @@ -830,19 +830,11 @@ void CameraDevice::abortRequest(Camera3RequestDescriptor *descriptor) const
>> {
>> notifyError(descriptor->frameNumber_, nullptr, CAMERA3_MSG_ERROR_REQUEST);
>>
>> - camera3_capture_result_t &result = descriptor->captureResult_;
>> - result.num_output_buffers = descriptor->buffers_.size();
>> - result.frame_number = descriptor->frameNumber_;
>> - result.partial_result = 0;
>> -
>> - std::vector<camera3_stream_buffer_t> resultBuffers(result.num_output_buffers);
>> - for (auto [i, buffer] : utils::enumerate(resultBuffers)) {
>> - buffer = descriptor->buffers_[i];
>> - buffer.release_fence = descriptor->buffers_[i].acquire_fence;
>> + for (auto &buffer : descriptor->buffers_) {
>> + buffer.release_fence = buffer.acquire_fence;
>> buffer.acquire_fence = -1;
>> buffer.status = CAMERA3_BUFFER_STATUS_ERROR;
>> }
>> - result.output_buffers = resultBuffers.data();
>>
>> descriptor->status_ = Camera3RequestDescriptor::Status::Error;
>> }
>> @@ -1090,9 +1082,6 @@ void CameraDevice::requestComplete(Request *request)
>> * The buffer status is set to OK and later changed to ERROR if
>> * post-processing/compression fails.
>> */
>> - camera3_capture_result_t &captureResult = descriptor->captureResult_;
>> - captureResult.frame_number = descriptor->frameNumber_;
>> - captureResult.num_output_buffers = descriptor->buffers_.size();
>> for (camera3_stream_buffer_t &buffer : descriptor->buffers_) {
>> CameraStream *cameraStream =
>> static_cast<CameraStream *>(buffer.stream->priv);
>> @@ -1113,8 +1102,6 @@ void CameraDevice::requestComplete(Request *request)
>> buffer.release_fence = -1;
>> buffer.status = CAMERA3_BUFFER_STATUS_OK;
>> }
>> - captureResult.output_buffers = descriptor->buffers_.data();
>> - captureResult.partial_result = 1;
>>
>> /*
>> * If the Request has failed, abort the request by notifying the error
>> @@ -1128,7 +1115,6 @@ void CameraDevice::requestComplete(Request *request)
>> notifyError(descriptor->frameNumber_, nullptr,
>> CAMERA3_MSG_ERROR_REQUEST);
>>
>> - captureResult.partial_result = 0;
>> for (camera3_stream_buffer_t &buffer : descriptor->buffers_) {
>> /*
>> * Signal to the framework it has to handle fences that
>> @@ -1165,12 +1151,12 @@ void CameraDevice::requestComplete(Request *request)
>> * Notify if the metadata generation has failed, but continue processing
>> * buffers and return an empty metadata pack.
>> */
>> - std::unique_ptr<CameraMetadata> resultMetadata = getResultMetadata(*descriptor);
>> - if (!resultMetadata) {
>> + descriptor->resultMetadata_ = getResultMetadata(*descriptor);
>> + if (!descriptor->resultMetadata_) {
>> notifyError(descriptor->frameNumber_, nullptr, CAMERA3_MSG_ERROR_RESULT);
>>
>> /* The camera framework expects an empty metadata pack on error. */
>> - resultMetadata = std::make_unique<CameraMetadata>(0, 0);
>> + descriptor->resultMetadata_ = std::make_unique<CameraMetadata>(0, 0);
> Since we don't sendCaptureResult() and return here we get to
> post-processing with a (0, 0) metadata pack. I wonder if the
> post-processing code is robust enough to cope with that situation
> (even if I suspect I already know the answer :)
>
> It is my understanding the situation is like this already, so it's
> fine, but maybe we should add a todo.
\todo stating what? The situation or the solution. I am not sure of a
potential solution of this yet
>
>> }
>>
>> /* Handle post-processing. */
>> @@ -1192,7 +1178,7 @@ void CameraDevice::requestComplete(Request *request)
>>
>> int ret = cameraStream->process(*src, buffer,
>> descriptor->settings_,
>> - resultMetadata.get());
>> + descriptor->resultMetadata_.get());
>> /*
>> * Return the FrameBuffer to the CameraStream now that we're
>> * done processing it.
>> @@ -1207,7 +1193,6 @@ void CameraDevice::requestComplete(Request *request)
>> }
>> }
>>
>> - captureResult.result = resultMetadata->get();
>> descriptor->status_ = Camera3RequestDescriptor::Status::Success;
>> sendCaptureResults();
>> }
>> @@ -1225,8 +1210,20 @@ void CameraDevice::sendCaptureResults()
>> * impact on performance which should be measured.
>> */
>> lock.unlock();
>> - callbacks_->process_capture_result(callbacks_,
>> - &descriptor->captureResult_);
>> +
>> + camera3_capture_result_t captureResult = {};
>> +
>> + captureResult.frame_number = descriptor->frameNumber_;
>> + if (descriptor->resultMetadata_)
> Do we need this ? As resultMetadata_ is a unique_ptr<> it is
> constructed owning nothing, and calling get() on it simnply return
> nullptr, which I think it's what we want.
Yes we need this. There are two get() here
a) one of the unique_ptr one, .get()
b) another is the descriptor->resultMetadata_->get()) one
If descriptor->resultMetadata_ is nullptr (initialized), ->get() on it,
will segfault
So I found best to guard it with an if () block for now. Does it make sense?
>
> Thanks
> j
>> + captureResult.result = descriptor->resultMetadata_->get();
>> + captureResult.num_output_buffers = descriptor->buffers_.size();
>> + captureResult.output_buffers = descriptor->buffers_.data();
>> +
>> + if (descriptor->status_ == Camera3RequestDescriptor::Status::Success)
>> + captureResult.partial_result = 1;
>> +
>> + callbacks_->process_capture_result(callbacks_, &captureResult);
>> +
>> lock.lock();
>> }
>> }
>> diff --git a/src/android/camera_request.h b/src/android/camera_request.h
>> index 79dfdb58..db13f624 100644
>> --- a/src/android/camera_request.h
>> +++ b/src/android/camera_request.h
>> @@ -40,8 +40,8 @@ public:
>> std::vector<std::unique_ptr<libcamera::FrameBuffer>> frameBuffers_;
>> CameraMetadata settings_;
>> std::unique_ptr<CaptureRequest> request_;
>> + std::unique_ptr<CameraMetadata> resultMetadata_;
>>
>> - camera3_capture_result_t captureResult_ = {};
>> Status status_ = Status::Pending;
>>
>> private:
>> --
>> 2.31.0
>>
More information about the libcamera-devel
mailing list