[{"id":20267,"web_url":"https://patchwork.libcamera.org/comment/20267/","msgid":"<YW15uEgaSj3TlvRp@pendragon.ideasonboard.com>","date":"2021-10-18T13:42:16","subject":"Re: [libcamera-devel] [PATCH 05/11] android: camera_device: Create\n\tstruct to track per stream buffer","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Umang,\n\nThank you for the patch.\n\nOn Mon, Oct 18, 2021 at 06:59:17PM +0530, Umang Jain wrote:\n> The Camera3RequestDescriptor structure stores, for each stream, the\n> camera3_stream_buffer_t and the libcamera FrameBuffer in two separate\n> vectors. This complicates buffer handling, as the code needs to keep\n> both vectors in sync. Create a new structure to group all data about\n> per-stream buffers to simplify this.\n> \n> As a side effect, we need to create a local vector of\n> camera3_stream_buffer_t in CameraDevice::sendCaptureResults() as the\n> camera3_stream_buffer_t instances stored in the new structure in\n> Camera3RequestDescriptor are not contiguous anymore. This is a small\n> price to pay for easier handling of buffers, and will be refactored in\n> subsequent commits anyway.\n> \n> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> ---\n>  src/android/camera_device.cpp  | 75 ++++++++++++++++++----------------\n>  src/android/camera_request.cpp |  9 +---\n>  src/android/camera_request.h   | 15 ++++++-\n>  3 files changed, 55 insertions(+), 44 deletions(-)\n> \n> diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\n> index 3bddb292..59557358 100644\n> --- a/src/android/camera_device.cpp\n> +++ b/src/android/camera_device.cpp\n> @@ -831,9 +831,9 @@ void CameraDevice::abortRequest(Camera3RequestDescriptor *descriptor) const\n>  \tnotifyError(descriptor->frameNumber_, nullptr, CAMERA3_MSG_ERROR_REQUEST);\n>  \n>  \tfor (auto &buffer : descriptor->buffers_) {\n> -\t\tbuffer.release_fence = buffer.acquire_fence;\n> -\t\tbuffer.acquire_fence = -1;\n> -\t\tbuffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> +\t\tbuffer.buffer.release_fence = buffer.buffer.acquire_fence;\n> +\t\tbuffer.buffer.acquire_fence = -1;\n> +\t\tbuffer.buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n>  \t}\n>  \n>  \tdescriptor->status_ = Camera3RequestDescriptor::Status::Error;\n> @@ -931,8 +931,8 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques\n>  \tLOG(HAL, Debug) << \"Queueing request \" << descriptor->request_->cookie()\n>  \t\t\t<< \" with \" << descriptor->buffers_.size() << \" streams\";\n>  \n> -\tfor (const auto &[i, camera3Buffer] : utils::enumerate(descriptor->buffers_)) {\n> -\t\tcamera3_stream *camera3Stream = camera3Buffer.stream;\n> +\tfor (const auto &[i, buffer] : utils::enumerate(descriptor->buffers_)) {\n> +\t\tcamera3_stream *camera3Stream = buffer.buffer.stream;\n>  \t\tCameraStream *cameraStream = static_cast<CameraStream *>(camera3Stream->priv);\n>  \n>  \t\tstd::stringstream ss;\n> @@ -949,7 +949,7 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques\n>  \t\t * while fences for streams of type Internal and Mapped are\n>  \t\t * handled at post-processing time.\n>  \t\t */\n> -\t\tFrameBuffer *buffer = nullptr;\n> +\t\tFrameBuffer *frameBuffer = nullptr;\n>  \t\tint acquireFence = -1;\n>  \t\tswitch (cameraStream->type()) {\n>  \t\tcase CameraStream::Type::Mapped:\n> @@ -967,13 +967,12 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques\n>  \t\t\t * associate it with the Camera3RequestDescriptor for\n>  \t\t\t * lifetime management only.\n>  \t\t\t */\n> -\t\t\tdescriptor->frameBuffers_.push_back(\n> -\t\t\t\tcreateFrameBuffer(*camera3Buffer.buffer,\n> +\t\t\tbuffer.frameBuffer =\n> +\t\t\t\tcreateFrameBuffer(*buffer.buffer.buffer,\n>  \t\t\t\t\t\t  cameraStream->configuration().pixelFormat,\n> -\t\t\t\t\t\t  cameraStream->configuration().size));\n> -\n> -\t\t\tbuffer = descriptor->frameBuffers_.back().get();\n> -\t\t\tacquireFence = camera3Buffer.acquire_fence;\n> +\t\t\t\t\t\t  cameraStream->configuration().size);\n> +\t\t\tframeBuffer = buffer.frameBuffer.get();\n> +\t\t\tacquireFence = buffer.buffer.acquire_fence;\n>  \t\t\tLOG(HAL, Debug) << ss.str() << \" (direct)\";\n>  \t\t\tbreak;\n>  \n> @@ -985,18 +984,18 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques\n>  \t\t\t * The buffer has to be returned to the CameraStream\n>  \t\t\t * once it has been processed.\n>  \t\t\t */\n> -\t\t\tbuffer = cameraStream->getBuffer();\n> +\t\t\tframeBuffer = cameraStream->getBuffer();\n>  \t\t\tLOG(HAL, Debug) << ss.str() << \" (internal)\";\n>  \t\t\tbreak;\n>  \t\t}\n>  \n> -\t\tif (!buffer) {\n> -\t\t\tLOG(HAL, Error) << \"Failed to create buffer\";\n> +\t\tif (!frameBuffer) {\n> +\t\t\tLOG(HAL, Error) << \"Failed to create frame buffer\";\n>  \t\t\treturn -ENOMEM;\n>  \t\t}\n>  \n> -\t\tdescriptor->request_->addBuffer(cameraStream->stream(), buffer,\n> -\t\t\t\t\t       acquireFence);\n> +\t\tdescriptor->request_->addBuffer(cameraStream->stream(),\n> +\t\t\t\t\t\tframeBuffer, acquireFence);\n>  \t}\n>  \n>  \t/*\n> @@ -1082,9 +1081,9 @@ void CameraDevice::requestComplete(Request *request)\n>  \t * The buffer status is set to OK and later changed to ERROR if\n>  \t * post-processing/compression fails.\n>  \t */\n> -\tfor (camera3_stream_buffer_t &buffer : descriptor->buffers_) {\n> +\tfor (auto &buffer : descriptor->buffers_) {\n>  \t\tCameraStream *cameraStream =\n> -\t\t\tstatic_cast<CameraStream *>(buffer.stream->priv);\n> +\t\t\tstatic_cast<CameraStream *>(buffer.buffer.stream->priv);\n>  \n>  \t\t/*\n>  \t\t * Streams of type Direct have been queued to the\n> @@ -1098,9 +1097,9 @@ void CameraDevice::requestComplete(Request *request)\n>  \t\t * fence to -1 once it has handled it and remove this check.\n>  \t\t */\n>  \t\tif (cameraStream->type() == CameraStream::Type::Direct)\n> -\t\t\tbuffer.acquire_fence = -1;\n> -\t\tbuffer.release_fence = -1;\n> -\t\tbuffer.status = CAMERA3_BUFFER_STATUS_OK;\n> +\t\t\tbuffer.buffer.acquire_fence = -1;\n> +\t\tbuffer.buffer.release_fence = -1;\n> +\t\tbuffer.buffer.status = CAMERA3_BUFFER_STATUS_OK;\n>  \t}\n>  \n>  \t/*\n> @@ -1115,15 +1114,15 @@ void CameraDevice::requestComplete(Request *request)\n>  \t\tnotifyError(descriptor->frameNumber_, nullptr,\n>  \t\t\t    CAMERA3_MSG_ERROR_REQUEST);\n>  \n> -\t\tfor (camera3_stream_buffer_t &buffer : descriptor->buffers_) {\n> +\t\tfor (auto &buffer : descriptor->buffers_) {\n>  \t\t\t/*\n>  \t\t\t * Signal to the framework it has to handle fences that\n>  \t\t\t * have not been waited on by setting the release fence\n>  \t\t\t * to the acquire fence value.\n>  \t\t\t */\n> -\t\t\tbuffer.release_fence = buffer.acquire_fence;\n> -\t\t\tbuffer.acquire_fence = -1;\n> -\t\t\tbuffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> +\t\t\tbuffer.buffer.release_fence = buffer.buffer.acquire_fence;\n> +\t\t\tbuffer.buffer.acquire_fence = -1;\n> +\t\t\tbuffer.buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n>  \t\t}\n>  \n>  \t\tdescriptor->status_ = Camera3RequestDescriptor::Status::Error;\n> @@ -1160,9 +1159,9 @@ void CameraDevice::requestComplete(Request *request)\n>  \t}\n>  \n>  \t/* Handle post-processing. */\n> -\tfor (camera3_stream_buffer_t &buffer : descriptor->buffers_) {\n> +\tfor (auto &buffer : descriptor->buffers_) {\n>  \t\tCameraStream *cameraStream =\n> -\t\t\tstatic_cast<CameraStream *>(buffer.stream->priv);\n> +\t\t\tstatic_cast<CameraStream *>(buffer.buffer.stream->priv);\n>  \n>  \t\tif (cameraStream->type() == CameraStream::Type::Direct)\n>  \t\t\tcontinue;\n> @@ -1170,13 +1169,13 @@ void CameraDevice::requestComplete(Request *request)\n>  \t\tFrameBuffer *src = request->findBuffer(cameraStream->stream());\n>  \t\tif (!src) {\n>  \t\t\tLOG(HAL, Error) << \"Failed to find a source stream buffer\";\n> -\t\t\tbuffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> -\t\t\tnotifyError(descriptor->frameNumber_, buffer.stream,\n> +\t\t\tbuffer.buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> +\t\t\tnotifyError(descriptor->frameNumber_, buffer.buffer.stream,\n>  \t\t\t\t    CAMERA3_MSG_ERROR_BUFFER);\n>  \t\t\tcontinue;\n>  \t\t}\n>  \n> -\t\tint ret = cameraStream->process(*src, buffer, descriptor);\n> +\t\tint ret = cameraStream->process(*src, buffer.buffer, descriptor);\n>  \n>  \t\t/*\n>  \t\t * Return the FrameBuffer to the CameraStream now that we're\n> @@ -1186,8 +1185,8 @@ void CameraDevice::requestComplete(Request *request)\n>  \t\t\tcameraStream->putBuffer(src);\n>  \n>  \t\tif (ret) {\n> -\t\t\tbuffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> -\t\t\tnotifyError(descriptor->frameNumber_, buffer.stream,\n> +\t\t\tbuffer.buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> +\t\t\tnotifyError(descriptor->frameNumber_, buffer.buffer.stream,\n>  \t\t\t\t    CAMERA3_MSG_ERROR_BUFFER);\n>  \t\t}\n>  \t}\n> @@ -1213,10 +1212,16 @@ void CameraDevice::sendCaptureResults()\n>  \t\tcamera3_capture_result_t captureResult = {};\n>  \n>  \t\tcaptureResult.frame_number = descriptor->frameNumber_;\n> +\n>  \t\tif (descriptor->resultMetadata_)\n>  \t\t\tcaptureResult.result = descriptor->resultMetadata_->get();\n> -\t\tcaptureResult.num_output_buffers = descriptor->buffers_.size();\n> -\t\tcaptureResult.output_buffers = descriptor->buffers_.data();\n> +\n> +\t\tstd::vector<camera3_stream_buffer_t> resultBuffers;\n> +\t\tfor (const auto &buffer : descriptor->buffers_)\n> +\t\t\tresultBuffers.emplace_back(buffer.buffer);\n> +\n> +\t\tcaptureResult.num_output_buffers = resultBuffers.size();\n> +\t\tcaptureResult.output_buffers = resultBuffers.data();\n>  \n>  \t\tif (descriptor->status_ == Camera3RequestDescriptor::Status::Success)\n>  \t\t\tcaptureResult.partial_result = 1;\n> diff --git a/src/android/camera_request.cpp b/src/android/camera_request.cpp\n> index 16a632b3..614baed4 100644\n> --- a/src/android/camera_request.cpp\n> +++ b/src/android/camera_request.cpp\n> @@ -23,15 +23,10 @@ Camera3RequestDescriptor::Camera3RequestDescriptor(\n>  \n>  \t/* Copy the camera3 request stream information for later access. */\n>  \tconst uint32_t numBuffers = camera3Request->num_output_buffers;\n> +\n>  \tbuffers_.resize(numBuffers);\n>  \tfor (uint32_t i = 0; i < numBuffers; i++)\n> -\t\tbuffers_[i] = camera3Request->output_buffers[i];\n> -\n> -\t/*\n> -\t * FrameBuffer instances created by wrapping a camera3 provided dmabuf\n> -\t * are emplaced in this vector of unique_ptr<> for lifetime management.\n> -\t */\n> -\tframeBuffers_.reserve(numBuffers);\n> +\t\tbuffers_[i].buffer = camera3Request->output_buffers[i];\n>  \n>  \t/* Clone the controls associated with the camera3 request. */\n>  \tsettings_ = CameraMetadata(camera3Request->settings);\n> diff --git a/src/android/camera_request.h b/src/android/camera_request.h\n> index db13f624..a030febf 100644\n> --- a/src/android/camera_request.h\n> +++ b/src/android/camera_request.h\n> @@ -29,6 +29,16 @@ public:\n>  \t\tError,\n>  \t};\n>  \n> +\tstruct StreamBuffer {\n> +\t\tcamera3_stream_buffer_t buffer;\n> +\t\t/*\n> +\t\t * FrameBuffer instances created by wrapping a camera3 provided\n> +\t\t * dmabuf are emplaced in this vector of unique_ptr<> for\n> +\t\t * lifetime management.\n> +\t\t */\n> +\t\tstd::unique_ptr<libcamera::FrameBuffer> frameBuffer;\n> +\t};\n> +\n>  \tCamera3RequestDescriptor(libcamera::Camera *camera,\n>  \t\t\t\t const camera3_capture_request_t *camera3Request);\n>  \t~Camera3RequestDescriptor();\n> @@ -36,8 +46,9 @@ public:\n>  \tbool isPending() const { return status_ == Status::Pending; }\n>  \n>  \tuint32_t frameNumber_ = 0;\n> -\tstd::vector<camera3_stream_buffer_t> buffers_;\n> -\tstd::vector<std::unique_ptr<libcamera::FrameBuffer>> frameBuffers_;\n> +\n> +\tstd::vector<StreamBuffer> buffers_;\n> +\n>  \tCameraMetadata settings_;\n>  \tstd::unique_ptr<CaptureRequest> request_;\n>  \tstd::unique_ptr<CameraMetadata> resultMetadata_;","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 4C166C323E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 18 Oct 2021 13:42:35 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 0B76968F59;\n\tMon, 18 Oct 2021 15:42:35 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id B2F6768F56\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 18 Oct 2021 15:42:33 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 476648C6;\n\tMon, 18 Oct 2021 15:42:33 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"INPA3rBq\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1634564553;\n\tbh=vZkGxzWBigw2/u9N/QdFtFN5MqzYDetKBL8+L/fJB7Y=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=INPA3rBq9Z2hIf+V6KurWQ70g8dEIThLjiyljUCOiT3j7wviGgewH11wmo7EWPBqY\n\tDokVbs6cVzknB5FP+PHSU6jUrPGdWIOH5b/LWpoIGUNSS7+ho5BunwZOwKeS+GOtDZ\n\tF4W+wtAyBN9fHZ4RrnlstZGKRpaaZS3N5CMTjapI=","Date":"Mon, 18 Oct 2021 16:42:16 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Umang Jain <umang.jain@ideasonboard.com>","Message-ID":"<YW15uEgaSj3TlvRp@pendragon.ideasonboard.com>","References":"<20211018132923.476242-1-umang.jain@ideasonboard.com>\n\t<20211018132923.476242-6-umang.jain@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20211018132923.476242-6-umang.jain@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH 05/11] android: camera_device: Create\n\tstruct to track per stream buffer","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":20273,"web_url":"https://patchwork.libcamera.org/comment/20273/","msgid":"<20211018162228.2fdkhlorn25ramn2@uno.localdomain>","date":"2021-10-18T16:22:28","subject":"Re: [libcamera-devel] [PATCH 05/11] android: camera_device: Create\n\tstruct to track per stream buffer","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Umang,\n\nOn Mon, Oct 18, 2021 at 06:59:17PM +0530, Umang Jain wrote:\n> The Camera3RequestDescriptor structure stores, for each stream, the\n> camera3_stream_buffer_t and the libcamera FrameBuffer in two separate\n> vectors. This complicates buffer handling, as the code needs to keep\n> both vectors in sync. Create a new structure to group all data about\n> per-stream buffers to simplify this.\n>\n> As a side effect, we need to create a local vector of\n> camera3_stream_buffer_t in CameraDevice::sendCaptureResults() as the\n> camera3_stream_buffer_t instances stored in the new structure in\n> Camera3RequestDescriptor are not contiguous anymore. This is a small\n> price to pay for easier handling of buffers, and will be refactored in\n> subsequent commits anyway.\n>\n> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>  src/android/camera_device.cpp  | 75 ++++++++++++++++++----------------\n>  src/android/camera_request.cpp |  9 +---\n>  src/android/camera_request.h   | 15 ++++++-\n>  3 files changed, 55 insertions(+), 44 deletions(-)\n>\n> diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\n> index 3bddb292..59557358 100644\n> --- a/src/android/camera_device.cpp\n> +++ b/src/android/camera_device.cpp\n> @@ -831,9 +831,9 @@ void CameraDevice::abortRequest(Camera3RequestDescriptor *descriptor) const\n>  \tnotifyError(descriptor->frameNumber_, nullptr, CAMERA3_MSG_ERROR_REQUEST);\n>\n>  \tfor (auto &buffer : descriptor->buffers_) {\n> -\t\tbuffer.release_fence = buffer.acquire_fence;\n> -\t\tbuffer.acquire_fence = -1;\n> -\t\tbuffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> +\t\tbuffer.buffer.release_fence = buffer.buffer.acquire_fence;\n> +\t\tbuffer.buffer.acquire_fence = -1;\n> +\t\tbuffer.buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n>  \t}\n>\n>  \tdescriptor->status_ = Camera3RequestDescriptor::Status::Error;\n> @@ -931,8 +931,8 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques\n>  \tLOG(HAL, Debug) << \"Queueing request \" << descriptor->request_->cookie()\n>  \t\t\t<< \" with \" << descriptor->buffers_.size() << \" streams\";\n>\n> -\tfor (const auto &[i, camera3Buffer] : utils::enumerate(descriptor->buffers_)) {\n> -\t\tcamera3_stream *camera3Stream = camera3Buffer.stream;\n> +\tfor (const auto &[i, buffer] : utils::enumerate(descriptor->buffers_)) {\n> +\t\tcamera3_stream *camera3Stream = buffer.buffer.stream;\n>  \t\tCameraStream *cameraStream = static_cast<CameraStream *>(camera3Stream->priv);\n>\n>  \t\tstd::stringstream ss;\n> @@ -949,7 +949,7 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques\n>  \t\t * while fences for streams of type Internal and Mapped are\n>  \t\t * handled at post-processing time.\n>  \t\t */\n> -\t\tFrameBuffer *buffer = nullptr;\n> +\t\tFrameBuffer *frameBuffer = nullptr;\n>  \t\tint acquireFence = -1;\n>  \t\tswitch (cameraStream->type()) {\n>  \t\tcase CameraStream::Type::Mapped:\n> @@ -967,13 +967,12 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques\n>  \t\t\t * associate it with the Camera3RequestDescriptor for\n>  \t\t\t * lifetime management only.\n>  \t\t\t */\n> -\t\t\tdescriptor->frameBuffers_.push_back(\n> -\t\t\t\tcreateFrameBuffer(*camera3Buffer.buffer,\n> +\t\t\tbuffer.frameBuffer =\n> +\t\t\t\tcreateFrameBuffer(*buffer.buffer.buffer,\n>  \t\t\t\t\t\t  cameraStream->configuration().pixelFormat,\n> -\t\t\t\t\t\t  cameraStream->configuration().size));\n> -\n> -\t\t\tbuffer = descriptor->frameBuffers_.back().get();\n> -\t\t\tacquireFence = camera3Buffer.acquire_fence;\n> +\t\t\t\t\t\t  cameraStream->configuration().size);\n> +\t\t\tframeBuffer = buffer.frameBuffer.get();\n> +\t\t\tacquireFence = buffer.buffer.acquire_fence;\n>  \t\t\tLOG(HAL, Debug) << ss.str() << \" (direct)\";\n>  \t\t\tbreak;\n>\n> @@ -985,18 +984,18 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques\n>  \t\t\t * The buffer has to be returned to the CameraStream\n>  \t\t\t * once it has been processed.\n>  \t\t\t */\n> -\t\t\tbuffer = cameraStream->getBuffer();\n> +\t\t\tframeBuffer = cameraStream->getBuffer();\n>  \t\t\tLOG(HAL, Debug) << ss.str() << \" (internal)\";\n>  \t\t\tbreak;\n>  \t\t}\n>\n> -\t\tif (!buffer) {\n> -\t\t\tLOG(HAL, Error) << \"Failed to create buffer\";\n> +\t\tif (!frameBuffer) {\n> +\t\t\tLOG(HAL, Error) << \"Failed to create frame buffer\";\n>  \t\t\treturn -ENOMEM;\n>  \t\t}\n>\n> -\t\tdescriptor->request_->addBuffer(cameraStream->stream(), buffer,\n> -\t\t\t\t\t       acquireFence);\n> +\t\tdescriptor->request_->addBuffer(cameraStream->stream(),\n> +\t\t\t\t\t\tframeBuffer, acquireFence);\n>  \t}\n>\n>  \t/*\n> @@ -1082,9 +1081,9 @@ void CameraDevice::requestComplete(Request *request)\n>  \t * The buffer status is set to OK and later changed to ERROR if\n>  \t * post-processing/compression fails.\n>  \t */\n> -\tfor (camera3_stream_buffer_t &buffer : descriptor->buffers_) {\n> +\tfor (auto &buffer : descriptor->buffers_) {\n>  \t\tCameraStream *cameraStream =\n> -\t\t\tstatic_cast<CameraStream *>(buffer.stream->priv);\n> +\t\t\tstatic_cast<CameraStream *>(buffer.buffer.stream->priv);\n>\n>  \t\t/*\n>  \t\t * Streams of type Direct have been queued to the\n> @@ -1098,9 +1097,9 @@ void CameraDevice::requestComplete(Request *request)\n>  \t\t * fence to -1 once it has handled it and remove this check.\n>  \t\t */\n>  \t\tif (cameraStream->type() == CameraStream::Type::Direct)\n> -\t\t\tbuffer.acquire_fence = -1;\n> -\t\tbuffer.release_fence = -1;\n> -\t\tbuffer.status = CAMERA3_BUFFER_STATUS_OK;\n> +\t\t\tbuffer.buffer.acquire_fence = -1;\n> +\t\tbuffer.buffer.release_fence = -1;\n> +\t\tbuffer.buffer.status = CAMERA3_BUFFER_STATUS_OK;\n>  \t}\n>\n>  \t/*\n> @@ -1115,15 +1114,15 @@ void CameraDevice::requestComplete(Request *request)\n>  \t\tnotifyError(descriptor->frameNumber_, nullptr,\n>  \t\t\t    CAMERA3_MSG_ERROR_REQUEST);\n>\n> -\t\tfor (camera3_stream_buffer_t &buffer : descriptor->buffers_) {\n> +\t\tfor (auto &buffer : descriptor->buffers_) {\n>  \t\t\t/*\n>  \t\t\t * Signal to the framework it has to handle fences that\n>  \t\t\t * have not been waited on by setting the release fence\n>  \t\t\t * to the acquire fence value.\n>  \t\t\t */\n> -\t\t\tbuffer.release_fence = buffer.acquire_fence;\n> -\t\t\tbuffer.acquire_fence = -1;\n> -\t\t\tbuffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> +\t\t\tbuffer.buffer.release_fence = buffer.buffer.acquire_fence;\n> +\t\t\tbuffer.buffer.acquire_fence = -1;\n> +\t\t\tbuffer.buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n>  \t\t}\n>\n>  \t\tdescriptor->status_ = Camera3RequestDescriptor::Status::Error;\n> @@ -1160,9 +1159,9 @@ void CameraDevice::requestComplete(Request *request)\n>  \t}\n>\n>  \t/* Handle post-processing. */\n> -\tfor (camera3_stream_buffer_t &buffer : descriptor->buffers_) {\n> +\tfor (auto &buffer : descriptor->buffers_) {\n>  \t\tCameraStream *cameraStream =\n> -\t\t\tstatic_cast<CameraStream *>(buffer.stream->priv);\n> +\t\t\tstatic_cast<CameraStream *>(buffer.buffer.stream->priv);\n>\n>  \t\tif (cameraStream->type() == CameraStream::Type::Direct)\n>  \t\t\tcontinue;\n> @@ -1170,13 +1169,13 @@ void CameraDevice::requestComplete(Request *request)\n>  \t\tFrameBuffer *src = request->findBuffer(cameraStream->stream());\n>  \t\tif (!src) {\n>  \t\t\tLOG(HAL, Error) << \"Failed to find a source stream buffer\";\n> -\t\t\tbuffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> -\t\t\tnotifyError(descriptor->frameNumber_, buffer.stream,\n> +\t\t\tbuffer.buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> +\t\t\tnotifyError(descriptor->frameNumber_, buffer.buffer.stream,\n>  \t\t\t\t    CAMERA3_MSG_ERROR_BUFFER);\n>  \t\t\tcontinue;\n>  \t\t}\n>\n> -\t\tint ret = cameraStream->process(*src, buffer, descriptor);\n> +\t\tint ret = cameraStream->process(*src, buffer.buffer, descriptor);\n>\n>  \t\t/*\n>  \t\t * Return the FrameBuffer to the CameraStream now that we're\n> @@ -1186,8 +1185,8 @@ void CameraDevice::requestComplete(Request *request)\n>  \t\t\tcameraStream->putBuffer(src);\n>\n>  \t\tif (ret) {\n> -\t\t\tbuffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> -\t\t\tnotifyError(descriptor->frameNumber_, buffer.stream,\n> +\t\t\tbuffer.buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> +\t\t\tnotifyError(descriptor->frameNumber_, buffer.buffer.stream,\n>  \t\t\t\t    CAMERA3_MSG_ERROR_BUFFER);\n>  \t\t}\n>  \t}\n> @@ -1213,10 +1212,16 @@ void CameraDevice::sendCaptureResults()\n>  \t\tcamera3_capture_result_t captureResult = {};\n>\n>  \t\tcaptureResult.frame_number = descriptor->frameNumber_;\n> +\n>  \t\tif (descriptor->resultMetadata_)\n>  \t\t\tcaptureResult.result = descriptor->resultMetadata_->get();\n> -\t\tcaptureResult.num_output_buffers = descriptor->buffers_.size();\n> -\t\tcaptureResult.output_buffers = descriptor->buffers_.data();\n> +\n> +\t\tstd::vector<camera3_stream_buffer_t> resultBuffers;\n\nCan't you std::vector::reserve(descriptor->streams.size()) to avoid\nrelocations ?\n\nI guess I'll find out more in next patches how this change will be\nused.\n\nReviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n\nThanks\n   j\n\n> +\t\tfor (const auto &buffer : descriptor->buffers_)\n> +\t\t\tresultBuffers.emplace_back(buffer.buffer);\n> +\n> +\t\tcaptureResult.num_output_buffers = resultBuffers.size();\n> +\t\tcaptureResult.output_buffers = resultBuffers.data();\n>\n>  \t\tif (descriptor->status_ == Camera3RequestDescriptor::Status::Success)\n>  \t\t\tcaptureResult.partial_result = 1;\n> diff --git a/src/android/camera_request.cpp b/src/android/camera_request.cpp\n> index 16a632b3..614baed4 100644\n> --- a/src/android/camera_request.cpp\n> +++ b/src/android/camera_request.cpp\n> @@ -23,15 +23,10 @@ Camera3RequestDescriptor::Camera3RequestDescriptor(\n>\n>  \t/* Copy the camera3 request stream information for later access. */\n>  \tconst uint32_t numBuffers = camera3Request->num_output_buffers;\n> +\n>  \tbuffers_.resize(numBuffers);\n>  \tfor (uint32_t i = 0; i < numBuffers; i++)\n> -\t\tbuffers_[i] = camera3Request->output_buffers[i];\n> -\n> -\t/*\n> -\t * FrameBuffer instances created by wrapping a camera3 provided dmabuf\n> -\t * are emplaced in this vector of unique_ptr<> for lifetime management.\n> -\t */\n> -\tframeBuffers_.reserve(numBuffers);\n> +\t\tbuffers_[i].buffer = camera3Request->output_buffers[i];\n>\n>  \t/* Clone the controls associated with the camera3 request. */\n>  \tsettings_ = CameraMetadata(camera3Request->settings);\n> diff --git a/src/android/camera_request.h b/src/android/camera_request.h\n> index db13f624..a030febf 100644\n> --- a/src/android/camera_request.h\n> +++ b/src/android/camera_request.h\n> @@ -29,6 +29,16 @@ public:\n>  \t\tError,\n>  \t};\n>\n> +\tstruct StreamBuffer {\n> +\t\tcamera3_stream_buffer_t buffer;\n> +\t\t/*\n> +\t\t * FrameBuffer instances created by wrapping a camera3 provided\n> +\t\t * dmabuf are emplaced in this vector of unique_ptr<> for\n> +\t\t * lifetime management.\n> +\t\t */\n> +\t\tstd::unique_ptr<libcamera::FrameBuffer> frameBuffer;\n> +\t};\n> +\n>  \tCamera3RequestDescriptor(libcamera::Camera *camera,\n>  \t\t\t\t const camera3_capture_request_t *camera3Request);\n>  \t~Camera3RequestDescriptor();\n> @@ -36,8 +46,9 @@ public:\n>  \tbool isPending() const { return status_ == Status::Pending; }\n>\n>  \tuint32_t frameNumber_ = 0;\n> -\tstd::vector<camera3_stream_buffer_t> buffers_;\n> -\tstd::vector<std::unique_ptr<libcamera::FrameBuffer>> frameBuffers_;\n> +\n> +\tstd::vector<StreamBuffer> buffers_;\n> +\n>  \tCameraMetadata settings_;\n>  \tstd::unique_ptr<CaptureRequest> request_;\n>  \tstd::unique_ptr<CameraMetadata> resultMetadata_;\n> --\n> 2.31.0\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id CF0C0C323E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 18 Oct 2021 16:21:41 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 2118968F59;\n\tMon, 18 Oct 2021 18:21:41 +0200 (CEST)","from relay10.mail.gandi.net (relay10.mail.gandi.net\n\t[217.70.178.230])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 88CDC68F56\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 18 Oct 2021 18:21:40 +0200 (CEST)","(Authenticated sender: jacopo@jmondi.org)\n\tby relay10.mail.gandi.net (Postfix) with ESMTPSA id 1243A240002;\n\tMon, 18 Oct 2021 16:21:39 +0000 (UTC)"],"Date":"Mon, 18 Oct 2021 18:22:28 +0200","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Umang Jain <umang.jain@ideasonboard.com>","Message-ID":"<20211018162228.2fdkhlorn25ramn2@uno.localdomain>","References":"<20211018132923.476242-1-umang.jain@ideasonboard.com>\n\t<20211018132923.476242-6-umang.jain@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20211018132923.476242-6-umang.jain@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH 05/11] android: camera_device: Create\n\tstruct to track per stream buffer","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":20291,"web_url":"https://patchwork.libcamera.org/comment/20291/","msgid":"<CAO5uPHPuZMLUZnSBM83adM3Hz+mRLJ9Yz5xsxrcpRByL+MXQGQ@mail.gmail.com>","date":"2021-10-19T04:48:51","subject":"Re: [libcamera-devel] [PATCH 05/11] android: camera_device: Create\n\tstruct to track per stream buffer","submitter":{"id":63,"url":"https://patchwork.libcamera.org/api/people/63/","name":"Hirokazu Honda","email":"hiroh@chromium.org"},"content":"Hi Umang, thank you for the patch.\n\nOn Tue, Oct 19, 2021 at 1:21 AM Jacopo Mondi <jacopo@jmondi.org> wrote:\n>\n> Hi Umang,\n>\n> On Mon, Oct 18, 2021 at 06:59:17PM +0530, Umang Jain wrote:\n> > The Camera3RequestDescriptor structure stores, for each stream, the\n> > camera3_stream_buffer_t and the libcamera FrameBuffer in two separate\n> > vectors. This complicates buffer handling, as the code needs to keep\n> > both vectors in sync. Create a new structure to group all data about\n> > per-stream buffers to simplify this.\n> >\n> > As a side effect, we need to create a local vector of\n> > camera3_stream_buffer_t in CameraDevice::sendCaptureResults() as the\n> > camera3_stream_buffer_t instances stored in the new structure in\n> > Camera3RequestDescriptor are not contiguous anymore. This is a small\n> > price to pay for easier handling of buffers, and will be refactored in\n> > subsequent commits anyway.\n> >\n> > Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>\n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nReviewed-by: Hirokazu Honda <hiroh@chromium.org>\n\n\n> > ---\n> >  src/android/camera_device.cpp  | 75 ++++++++++++++++++----------------\n> >  src/android/camera_request.cpp |  9 +---\n> >  src/android/camera_request.h   | 15 ++++++-\n> >  3 files changed, 55 insertions(+), 44 deletions(-)\n> >\n> > diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\n> > index 3bddb292..59557358 100644\n> > --- a/src/android/camera_device.cpp\n> > +++ b/src/android/camera_device.cpp\n> > @@ -831,9 +831,9 @@ void CameraDevice::abortRequest(Camera3RequestDescriptor *descriptor) const\n> >       notifyError(descriptor->frameNumber_, nullptr, CAMERA3_MSG_ERROR_REQUEST);\n> >\n> >       for (auto &buffer : descriptor->buffers_) {\n> > -             buffer.release_fence = buffer.acquire_fence;\n> > -             buffer.acquire_fence = -1;\n> > -             buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> > +             buffer.buffer.release_fence = buffer.buffer.acquire_fence;\n> > +             buffer.buffer.acquire_fence = -1;\n> > +             buffer.buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> >       }\n> >\n> >       descriptor->status_ = Camera3RequestDescriptor::Status::Error;\n> > @@ -931,8 +931,8 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques\n> >       LOG(HAL, Debug) << \"Queueing request \" << descriptor->request_->cookie()\n> >                       << \" with \" << descriptor->buffers_.size() << \" streams\";\n> >\n> > -     for (const auto &[i, camera3Buffer] : utils::enumerate(descriptor->buffers_)) {\n> > -             camera3_stream *camera3Stream = camera3Buffer.stream;\n> > +     for (const auto &[i, buffer] : utils::enumerate(descriptor->buffers_)) {\n> > +             camera3_stream *camera3Stream = buffer.buffer.stream;\n> >               CameraStream *cameraStream = static_cast<CameraStream *>(camera3Stream->priv);\n> >\n> >               std::stringstream ss;\n> > @@ -949,7 +949,7 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques\n> >                * while fences for streams of type Internal and Mapped are\n> >                * handled at post-processing time.\n> >                */\n> > -             FrameBuffer *buffer = nullptr;\n> > +             FrameBuffer *frameBuffer = nullptr;\n> >               int acquireFence = -1;\n> >               switch (cameraStream->type()) {\n> >               case CameraStream::Type::Mapped:\n> > @@ -967,13 +967,12 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques\n> >                        * associate it with the Camera3RequestDescriptor for\n> >                        * lifetime management only.\n> >                        */\n> > -                     descriptor->frameBuffers_.push_back(\n> > -                             createFrameBuffer(*camera3Buffer.buffer,\n> > +                     buffer.frameBuffer =\n> > +                             createFrameBuffer(*buffer.buffer.buffer,\n> >                                                 cameraStream->configuration().pixelFormat,\n> > -                                               cameraStream->configuration().size));\n> > -\n> > -                     buffer = descriptor->frameBuffers_.back().get();\n> > -                     acquireFence = camera3Buffer.acquire_fence;\n> > +                                               cameraStream->configuration().size);\n> > +                     frameBuffer = buffer.frameBuffer.get();\n> > +                     acquireFence = buffer.buffer.acquire_fence;\n> >                       LOG(HAL, Debug) << ss.str() << \" (direct)\";\n> >                       break;\n> >\n> > @@ -985,18 +984,18 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques\n> >                        * The buffer has to be returned to the CameraStream\n> >                        * once it has been processed.\n> >                        */\n> > -                     buffer = cameraStream->getBuffer();\n> > +                     frameBuffer = cameraStream->getBuffer();\n> >                       LOG(HAL, Debug) << ss.str() << \" (internal)\";\n> >                       break;\n> >               }\n> >\n> > -             if (!buffer) {\n> > -                     LOG(HAL, Error) << \"Failed to create buffer\";\n> > +             if (!frameBuffer) {\n> > +                     LOG(HAL, Error) << \"Failed to create frame buffer\";\n> >                       return -ENOMEM;\n> >               }\n> >\n> > -             descriptor->request_->addBuffer(cameraStream->stream(), buffer,\n> > -                                            acquireFence);\n> > +             descriptor->request_->addBuffer(cameraStream->stream(),\n> > +                                             frameBuffer, acquireFence);\n> >       }\n> >\n> >       /*\n> > @@ -1082,9 +1081,9 @@ void CameraDevice::requestComplete(Request *request)\n> >        * The buffer status is set to OK and later changed to ERROR if\n> >        * post-processing/compression fails.\n> >        */\n> > -     for (camera3_stream_buffer_t &buffer : descriptor->buffers_) {\n> > +     for (auto &buffer : descriptor->buffers_) {\n> >               CameraStream *cameraStream =\n> > -                     static_cast<CameraStream *>(buffer.stream->priv);\n> > +                     static_cast<CameraStream *>(buffer.buffer.stream->priv);\n> >\n> >               /*\n> >                * Streams of type Direct have been queued to the\n> > @@ -1098,9 +1097,9 @@ void CameraDevice::requestComplete(Request *request)\n> >                * fence to -1 once it has handled it and remove this check.\n> >                */\n> >               if (cameraStream->type() == CameraStream::Type::Direct)\n> > -                     buffer.acquire_fence = -1;\n> > -             buffer.release_fence = -1;\n> > -             buffer.status = CAMERA3_BUFFER_STATUS_OK;\n> > +                     buffer.buffer.acquire_fence = -1;\n> > +             buffer.buffer.release_fence = -1;\n> > +             buffer.buffer.status = CAMERA3_BUFFER_STATUS_OK;\n> >       }\n> >\n> >       /*\n> > @@ -1115,15 +1114,15 @@ void CameraDevice::requestComplete(Request *request)\n> >               notifyError(descriptor->frameNumber_, nullptr,\n> >                           CAMERA3_MSG_ERROR_REQUEST);\n> >\n> > -             for (camera3_stream_buffer_t &buffer : descriptor->buffers_) {\n> > +             for (auto &buffer : descriptor->buffers_) {\n> >                       /*\n> >                        * Signal to the framework it has to handle fences that\n> >                        * have not been waited on by setting the release fence\n> >                        * to the acquire fence value.\n> >                        */\n> > -                     buffer.release_fence = buffer.acquire_fence;\n> > -                     buffer.acquire_fence = -1;\n> > -                     buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> > +                     buffer.buffer.release_fence = buffer.buffer.acquire_fence;\n> > +                     buffer.buffer.acquire_fence = -1;\n> > +                     buffer.buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> >               }\n> >\n> >               descriptor->status_ = Camera3RequestDescriptor::Status::Error;\n> > @@ -1160,9 +1159,9 @@ void CameraDevice::requestComplete(Request *request)\n> >       }\n> >\n> >       /* Handle post-processing. */\n> > -     for (camera3_stream_buffer_t &buffer : descriptor->buffers_) {\n> > +     for (auto &buffer : descriptor->buffers_) {\n> >               CameraStream *cameraStream =\n> > -                     static_cast<CameraStream *>(buffer.stream->priv);\n> > +                     static_cast<CameraStream *>(buffer.buffer.stream->priv);\n> >\n> >               if (cameraStream->type() == CameraStream::Type::Direct)\n> >                       continue;\n> > @@ -1170,13 +1169,13 @@ void CameraDevice::requestComplete(Request *request)\n> >               FrameBuffer *src = request->findBuffer(cameraStream->stream());\n> >               if (!src) {\n> >                       LOG(HAL, Error) << \"Failed to find a source stream buffer\";\n> > -                     buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> > -                     notifyError(descriptor->frameNumber_, buffer.stream,\n> > +                     buffer.buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> > +                     notifyError(descriptor->frameNumber_, buffer.buffer.stream,\n> >                                   CAMERA3_MSG_ERROR_BUFFER);\n> >                       continue;\n> >               }\n> >\n> > -             int ret = cameraStream->process(*src, buffer, descriptor);\n> > +             int ret = cameraStream->process(*src, buffer.buffer, descriptor);\n> >\n> >               /*\n> >                * Return the FrameBuffer to the CameraStream now that we're\n> > @@ -1186,8 +1185,8 @@ void CameraDevice::requestComplete(Request *request)\n> >                       cameraStream->putBuffer(src);\n> >\n> >               if (ret) {\n> > -                     buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> > -                     notifyError(descriptor->frameNumber_, buffer.stream,\n> > +                     buffer.buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n> > +                     notifyError(descriptor->frameNumber_, buffer.buffer.stream,\n> >                                   CAMERA3_MSG_ERROR_BUFFER);\n> >               }\n> >       }\n> > @@ -1213,10 +1212,16 @@ void CameraDevice::sendCaptureResults()\n> >               camera3_capture_result_t captureResult = {};\n> >\n> >               captureResult.frame_number = descriptor->frameNumber_;\n> > +\n> >               if (descriptor->resultMetadata_)\n> >                       captureResult.result = descriptor->resultMetadata_->get();\n> > -             captureResult.num_output_buffers = descriptor->buffers_.size();\n> > -             captureResult.output_buffers = descriptor->buffers_.data();\n> > +\n> > +             std::vector<camera3_stream_buffer_t> resultBuffers;\n>\n> Can't you std::vector::reserve(descriptor->streams.size()) to avoid\n> relocations ?\n>\n> I guess I'll find out more in next patches how this change will be\n> used.\n>\n> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n>\n> Thanks\n>    j\n>\n> > +             for (const auto &buffer : descriptor->buffers_)\n> > +                     resultBuffers.emplace_back(buffer.buffer);\n> > +\n> > +             captureResult.num_output_buffers = resultBuffers.size();\n> > +             captureResult.output_buffers = resultBuffers.data();\n> >\n> >               if (descriptor->status_ == Camera3RequestDescriptor::Status::Success)\n> >                       captureResult.partial_result = 1;\n> > diff --git a/src/android/camera_request.cpp b/src/android/camera_request.cpp\n> > index 16a632b3..614baed4 100644\n> > --- a/src/android/camera_request.cpp\n> > +++ b/src/android/camera_request.cpp\n> > @@ -23,15 +23,10 @@ Camera3RequestDescriptor::Camera3RequestDescriptor(\n> >\n> >       /* Copy the camera3 request stream information for later access. */\n> >       const uint32_t numBuffers = camera3Request->num_output_buffers;\n> > +\n> >       buffers_.resize(numBuffers);\n> >       for (uint32_t i = 0; i < numBuffers; i++)\n> > -             buffers_[i] = camera3Request->output_buffers[i];\n> > -\n> > -     /*\n> > -      * FrameBuffer instances created by wrapping a camera3 provided dmabuf\n> > -      * are emplaced in this vector of unique_ptr<> for lifetime management.\n> > -      */\n> > -     frameBuffers_.reserve(numBuffers);\n> > +             buffers_[i].buffer = camera3Request->output_buffers[i];\n> >\n> >       /* Clone the controls associated with the camera3 request. */\n> >       settings_ = CameraMetadata(camera3Request->settings);\n> > diff --git a/src/android/camera_request.h b/src/android/camera_request.h\n> > index db13f624..a030febf 100644\n> > --- a/src/android/camera_request.h\n> > +++ b/src/android/camera_request.h\n> > @@ -29,6 +29,16 @@ public:\n> >               Error,\n> >       };\n> >\n> > +     struct StreamBuffer {\n> > +             camera3_stream_buffer_t buffer;\n> > +             /*\n> > +              * FrameBuffer instances created by wrapping a camera3 provided\n> > +              * dmabuf are emplaced in this vector of unique_ptr<> for\n> > +              * lifetime management.\n> > +              */\n> > +             std::unique_ptr<libcamera::FrameBuffer> frameBuffer;\n> > +     };\n> > +\n> >       Camera3RequestDescriptor(libcamera::Camera *camera,\n> >                                const camera3_capture_request_t *camera3Request);\n> >       ~Camera3RequestDescriptor();\n> > @@ -36,8 +46,9 @@ public:\n> >       bool isPending() const { return status_ == Status::Pending; }\n> >\n> >       uint32_t frameNumber_ = 0;\n> > -     std::vector<camera3_stream_buffer_t> buffers_;\n> > -     std::vector<std::unique_ptr<libcamera::FrameBuffer>> frameBuffers_;\n> > +\n> > +     std::vector<StreamBuffer> buffers_;\n> > +\n> >       CameraMetadata settings_;\n> >       std::unique_ptr<CaptureRequest> request_;\n> >       std::unique_ptr<CameraMetadata> resultMetadata_;\n> > --\n> > 2.31.0\n> >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id CD63AC324C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 19 Oct 2021 04:49:04 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1B5B168F5A;\n\tTue, 19 Oct 2021 06:49:04 +0200 (CEST)","from mail-ed1-x52f.google.com (mail-ed1-x52f.google.com\n\t[IPv6:2a00:1450:4864:20::52f])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 13DDE60126\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 19 Oct 2021 06:49:03 +0200 (CEST)","by mail-ed1-x52f.google.com with SMTP id a25so7777087edx.8\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 18 Oct 2021 21:49:03 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=chromium.org header.i=@chromium.org\n\theader.b=\"Cg+kdOfw\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org;\n\ts=google; \n\th=mime-version:references:in-reply-to:from:date:message-id:subject:to\n\t:cc; bh=qo+yF0XxMA/1Wls57Cab74zPbzhVGjCKzhqhyVz7TKY=;\n\tb=Cg+kdOfwsg0lZ5Q8Irp9XaGD+iFNCS/47N/4+I8YYMA/rfMRIBDZ+NP8E8t8YbgVul\n\tlYlc2CzFIaYoeVjjVBsklIAa6Gy6r6u6J6AzdVm7Bztb6ZuRNhKdtHO1mxcjQnPnxJND\n\tdkW21ukUwmBnxXgYTLVbBxGwQQgToNgXY75eQ=","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=x-gm-message-state:mime-version:references:in-reply-to:from:date\n\t:message-id:subject:to:cc;\n\tbh=qo+yF0XxMA/1Wls57Cab74zPbzhVGjCKzhqhyVz7TKY=;\n\tb=c08v7pf5s1GXFf8cOZ/yQ2IVnt97EnNHQt6yod42HImYfz0pYMRxf6uDODoBOVtaOe\n\t/wHzQrMeDWIAzIPN8TAIFbsUfYMRvJj3eXjMnhek+0xIRhB20E1D5PyGJbn2bcvaK8Dh\n\tPSfS9/ykAF1sh43WHAKgUgHlLzzqpmI9lRHhXh+17yGNqxmTmh+/gHFyMxrFObKApVc4\n\t6ZQQfbEgGbObiYDlnST3b+ypE26iB9Z3jQpQtps5dO8t4hEkCLsJHsstW+6goCDCjy5/\n\ts0hPL7HumICeYA/eJaaCImvhgpCwr9L49M+B01eOXV4g1biCdOMP7nyvwzESz2kP1CMC\n\treBQ==","X-Gm-Message-State":"AOAM530XCvulW9x/X+tQ0AVoCM9JZPsCQWvK5yCCigFwTy6GFBUwUkwR\n\t/i0rHKRY23YDV2Tm0/jeowtUurdeSOj0gqdaqz6cpg==","X-Google-Smtp-Source":"ABdhPJx6UJvqz0sWZyu1lcVf3Od66+T5zLEWFui3bkNu9KiqUSgNnip6eHJYrF3f5zXo5l1F6wZWmdtlpz/rPV1D8NA=","X-Received":"by 2002:a05:6402:26d3:: with SMTP id\n\tx19mr52068647edd.291.1634618942537; \n\tMon, 18 Oct 2021 21:49:02 -0700 (PDT)","MIME-Version":"1.0","References":"<20211018132923.476242-1-umang.jain@ideasonboard.com>\n\t<20211018132923.476242-6-umang.jain@ideasonboard.com>\n\t<20211018162228.2fdkhlorn25ramn2@uno.localdomain>","In-Reply-To":"<20211018162228.2fdkhlorn25ramn2@uno.localdomain>","From":"Hirokazu Honda <hiroh@chromium.org>","Date":"Tue, 19 Oct 2021 13:48:51 +0900","Message-ID":"<CAO5uPHPuZMLUZnSBM83adM3Hz+mRLJ9Yz5xsxrcpRByL+MXQGQ@mail.gmail.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Content-Type":"text/plain; charset=\"UTF-8\"","Subject":"Re: [libcamera-devel] [PATCH 05/11] android: camera_device: Create\n\tstruct to track per stream buffer","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":20301,"web_url":"https://patchwork.libcamera.org/comment/20301/","msgid":"<b6fb5660-136d-1195-b3bd-8be7fde86e0a@ideasonboard.com>","date":"2021-10-19T11:20:42","subject":"Re: [libcamera-devel] [PATCH 05/11] android: camera_device: Create\n\tstruct to track per stream buffer","submitter":{"id":86,"url":"https://patchwork.libcamera.org/api/people/86/","name":"Umang Jain","email":"umang.jain@ideasonboard.com"},"content":"Hi Jacopo,\n\nOn 10/18/21 9:52 PM, Jacopo Mondi wrote:\n> Hi Umang,\n>\n> On Mon, Oct 18, 2021 at 06:59:17PM +0530, Umang Jain wrote:\n>> The Camera3RequestDescriptor structure stores, for each stream, the\n>> camera3_stream_buffer_t and the libcamera FrameBuffer in two separate\n>> vectors. This complicates buffer handling, as the code needs to keep\n>> both vectors in sync. Create a new structure to group all data about\n>> per-stream buffers to simplify this.\n>>\n>> As a side effect, we need to create a local vector of\n>> camera3_stream_buffer_t in CameraDevice::sendCaptureResults() as the\n>> camera3_stream_buffer_t instances stored in the new structure in\n>> Camera3RequestDescriptor are not contiguous anymore. This is a small\n>> price to pay for easier handling of buffers, and will be refactored in\n>> subsequent commits anyway.\n>>\n>> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>\n>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n>> ---\n>>   src/android/camera_device.cpp  | 75 ++++++++++++++++++----------------\n>>   src/android/camera_request.cpp |  9 +---\n>>   src/android/camera_request.h   | 15 ++++++-\n>>   3 files changed, 55 insertions(+), 44 deletions(-)\n>>\n>> diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\n>> index 3bddb292..59557358 100644\n>> --- a/src/android/camera_device.cpp\n>> +++ b/src/android/camera_device.cpp\n>> @@ -831,9 +831,9 @@ void CameraDevice::abortRequest(Camera3RequestDescriptor *descriptor) const\n>>   \tnotifyError(descriptor->frameNumber_, nullptr, CAMERA3_MSG_ERROR_REQUEST);\n>>\n>>   \tfor (auto &buffer : descriptor->buffers_) {\n>> -\t\tbuffer.release_fence = buffer.acquire_fence;\n>> -\t\tbuffer.acquire_fence = -1;\n>> -\t\tbuffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n>> +\t\tbuffer.buffer.release_fence = buffer.buffer.acquire_fence;\n>> +\t\tbuffer.buffer.acquire_fence = -1;\n>> +\t\tbuffer.buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n>>   \t}\n>>\n>>   \tdescriptor->status_ = Camera3RequestDescriptor::Status::Error;\n>> @@ -931,8 +931,8 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques\n>>   \tLOG(HAL, Debug) << \"Queueing request \" << descriptor->request_->cookie()\n>>   \t\t\t<< \" with \" << descriptor->buffers_.size() << \" streams\";\n>>\n>> -\tfor (const auto &[i, camera3Buffer] : utils::enumerate(descriptor->buffers_)) {\n>> -\t\tcamera3_stream *camera3Stream = camera3Buffer.stream;\n>> +\tfor (const auto &[i, buffer] : utils::enumerate(descriptor->buffers_)) {\n>> +\t\tcamera3_stream *camera3Stream = buffer.buffer.stream;\n>>   \t\tCameraStream *cameraStream = static_cast<CameraStream *>(camera3Stream->priv);\n>>\n>>   \t\tstd::stringstream ss;\n>> @@ -949,7 +949,7 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques\n>>   \t\t * while fences for streams of type Internal and Mapped are\n>>   \t\t * handled at post-processing time.\n>>   \t\t */\n>> -\t\tFrameBuffer *buffer = nullptr;\n>> +\t\tFrameBuffer *frameBuffer = nullptr;\n>>   \t\tint acquireFence = -1;\n>>   \t\tswitch (cameraStream->type()) {\n>>   \t\tcase CameraStream::Type::Mapped:\n>> @@ -967,13 +967,12 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques\n>>   \t\t\t * associate it with the Camera3RequestDescriptor for\n>>   \t\t\t * lifetime management only.\n>>   \t\t\t */\n>> -\t\t\tdescriptor->frameBuffers_.push_back(\n>> -\t\t\t\tcreateFrameBuffer(*camera3Buffer.buffer,\n>> +\t\t\tbuffer.frameBuffer =\n>> +\t\t\t\tcreateFrameBuffer(*buffer.buffer.buffer,\n>>   \t\t\t\t\t\t  cameraStream->configuration().pixelFormat,\n>> -\t\t\t\t\t\t  cameraStream->configuration().size));\n>> -\n>> -\t\t\tbuffer = descriptor->frameBuffers_.back().get();\n>> -\t\t\tacquireFence = camera3Buffer.acquire_fence;\n>> +\t\t\t\t\t\t  cameraStream->configuration().size);\n>> +\t\t\tframeBuffer = buffer.frameBuffer.get();\n>> +\t\t\tacquireFence = buffer.buffer.acquire_fence;\n>>   \t\t\tLOG(HAL, Debug) << ss.str() << \" (direct)\";\n>>   \t\t\tbreak;\n>>\n>> @@ -985,18 +984,18 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques\n>>   \t\t\t * The buffer has to be returned to the CameraStream\n>>   \t\t\t * once it has been processed.\n>>   \t\t\t */\n>> -\t\t\tbuffer = cameraStream->getBuffer();\n>> +\t\t\tframeBuffer = cameraStream->getBuffer();\n>>   \t\t\tLOG(HAL, Debug) << ss.str() << \" (internal)\";\n>>   \t\t\tbreak;\n>>   \t\t}\n>>\n>> -\t\tif (!buffer) {\n>> -\t\t\tLOG(HAL, Error) << \"Failed to create buffer\";\n>> +\t\tif (!frameBuffer) {\n>> +\t\t\tLOG(HAL, Error) << \"Failed to create frame buffer\";\n>>   \t\t\treturn -ENOMEM;\n>>   \t\t}\n>>\n>> -\t\tdescriptor->request_->addBuffer(cameraStream->stream(), buffer,\n>> -\t\t\t\t\t       acquireFence);\n>> +\t\tdescriptor->request_->addBuffer(cameraStream->stream(),\n>> +\t\t\t\t\t\tframeBuffer, acquireFence);\n>>   \t}\n>>\n>>   \t/*\n>> @@ -1082,9 +1081,9 @@ void CameraDevice::requestComplete(Request *request)\n>>   \t * The buffer status is set to OK and later changed to ERROR if\n>>   \t * post-processing/compression fails.\n>>   \t */\n>> -\tfor (camera3_stream_buffer_t &buffer : descriptor->buffers_) {\n>> +\tfor (auto &buffer : descriptor->buffers_) {\n>>   \t\tCameraStream *cameraStream =\n>> -\t\t\tstatic_cast<CameraStream *>(buffer.stream->priv);\n>> +\t\t\tstatic_cast<CameraStream *>(buffer.buffer.stream->priv);\n>>\n>>   \t\t/*\n>>   \t\t * Streams of type Direct have been queued to the\n>> @@ -1098,9 +1097,9 @@ void CameraDevice::requestComplete(Request *request)\n>>   \t\t * fence to -1 once it has handled it and remove this check.\n>>   \t\t */\n>>   \t\tif (cameraStream->type() == CameraStream::Type::Direct)\n>> -\t\t\tbuffer.acquire_fence = -1;\n>> -\t\tbuffer.release_fence = -1;\n>> -\t\tbuffer.status = CAMERA3_BUFFER_STATUS_OK;\n>> +\t\t\tbuffer.buffer.acquire_fence = -1;\n>> +\t\tbuffer.buffer.release_fence = -1;\n>> +\t\tbuffer.buffer.status = CAMERA3_BUFFER_STATUS_OK;\n>>   \t}\n>>\n>>   \t/*\n>> @@ -1115,15 +1114,15 @@ void CameraDevice::requestComplete(Request *request)\n>>   \t\tnotifyError(descriptor->frameNumber_, nullptr,\n>>   \t\t\t    CAMERA3_MSG_ERROR_REQUEST);\n>>\n>> -\t\tfor (camera3_stream_buffer_t &buffer : descriptor->buffers_) {\n>> +\t\tfor (auto &buffer : descriptor->buffers_) {\n>>   \t\t\t/*\n>>   \t\t\t * Signal to the framework it has to handle fences that\n>>   \t\t\t * have not been waited on by setting the release fence\n>>   \t\t\t * to the acquire fence value.\n>>   \t\t\t */\n>> -\t\t\tbuffer.release_fence = buffer.acquire_fence;\n>> -\t\t\tbuffer.acquire_fence = -1;\n>> -\t\t\tbuffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n>> +\t\t\tbuffer.buffer.release_fence = buffer.buffer.acquire_fence;\n>> +\t\t\tbuffer.buffer.acquire_fence = -1;\n>> +\t\t\tbuffer.buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n>>   \t\t}\n>>\n>>   \t\tdescriptor->status_ = Camera3RequestDescriptor::Status::Error;\n>> @@ -1160,9 +1159,9 @@ void CameraDevice::requestComplete(Request *request)\n>>   \t}\n>>\n>>   \t/* Handle post-processing. */\n>> -\tfor (camera3_stream_buffer_t &buffer : descriptor->buffers_) {\n>> +\tfor (auto &buffer : descriptor->buffers_) {\n>>   \t\tCameraStream *cameraStream =\n>> -\t\t\tstatic_cast<CameraStream *>(buffer.stream->priv);\n>> +\t\t\tstatic_cast<CameraStream *>(buffer.buffer.stream->priv);\n>>\n>>   \t\tif (cameraStream->type() == CameraStream::Type::Direct)\n>>   \t\t\tcontinue;\n>> @@ -1170,13 +1169,13 @@ void CameraDevice::requestComplete(Request *request)\n>>   \t\tFrameBuffer *src = request->findBuffer(cameraStream->stream());\n>>   \t\tif (!src) {\n>>   \t\t\tLOG(HAL, Error) << \"Failed to find a source stream buffer\";\n>> -\t\t\tbuffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n>> -\t\t\tnotifyError(descriptor->frameNumber_, buffer.stream,\n>> +\t\t\tbuffer.buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n>> +\t\t\tnotifyError(descriptor->frameNumber_, buffer.buffer.stream,\n>>   \t\t\t\t    CAMERA3_MSG_ERROR_BUFFER);\n>>   \t\t\tcontinue;\n>>   \t\t}\n>>\n>> -\t\tint ret = cameraStream->process(*src, buffer, descriptor);\n>> +\t\tint ret = cameraStream->process(*src, buffer.buffer, descriptor);\n>>\n>>   \t\t/*\n>>   \t\t * Return the FrameBuffer to the CameraStream now that we're\n>> @@ -1186,8 +1185,8 @@ void CameraDevice::requestComplete(Request *request)\n>>   \t\t\tcameraStream->putBuffer(src);\n>>\n>>   \t\tif (ret) {\n>> -\t\t\tbuffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n>> -\t\t\tnotifyError(descriptor->frameNumber_, buffer.stream,\n>> +\t\t\tbuffer.buffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n>> +\t\t\tnotifyError(descriptor->frameNumber_, buffer.buffer.stream,\n>>   \t\t\t\t    CAMERA3_MSG_ERROR_BUFFER);\n>>   \t\t}\n>>   \t}\n>> @@ -1213,10 +1212,16 @@ void CameraDevice::sendCaptureResults()\n>>   \t\tcamera3_capture_result_t captureResult = {};\n>>\n>>   \t\tcaptureResult.frame_number = descriptor->frameNumber_;\n>> +\n>>   \t\tif (descriptor->resultMetadata_)\n>>   \t\t\tcaptureResult.result = descriptor->resultMetadata_->get();\n>> -\t\tcaptureResult.num_output_buffers = descriptor->buffers_.size();\n>> -\t\tcaptureResult.output_buffers = descriptor->buffers_.data();\n>> +\n>> +\t\tstd::vector<camera3_stream_buffer_t> resultBuffers;\n> Can't you std::vector::reserve(descriptor->streams.size()) to avoid\n> relocations ?\n>\n> I guess I'll find out more in next patches how this change will be\n> used.\n\n\nIf you haven't found already, .reserve() is used in 9/11 to avoid \nrelocations. :-)\n\n>\n> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n>\n> Thanks\n>     j\n>\n>> +\t\tfor (const auto &buffer : descriptor->buffers_)\n>> +\t\t\tresultBuffers.emplace_back(buffer.buffer);\n>> +\n>> +\t\tcaptureResult.num_output_buffers = resultBuffers.size();\n>> +\t\tcaptureResult.output_buffers = resultBuffers.data();\n>>\n>>   \t\tif (descriptor->status_ == Camera3RequestDescriptor::Status::Success)\n>>   \t\t\tcaptureResult.partial_result = 1;\n>> diff --git a/src/android/camera_request.cpp b/src/android/camera_request.cpp\n>> index 16a632b3..614baed4 100644\n>> --- a/src/android/camera_request.cpp\n>> +++ b/src/android/camera_request.cpp\n>> @@ -23,15 +23,10 @@ Camera3RequestDescriptor::Camera3RequestDescriptor(\n>>\n>>   \t/* Copy the camera3 request stream information for later access. */\n>>   \tconst uint32_t numBuffers = camera3Request->num_output_buffers;\n>> +\n>>   \tbuffers_.resize(numBuffers);\n>>   \tfor (uint32_t i = 0; i < numBuffers; i++)\n>> -\t\tbuffers_[i] = camera3Request->output_buffers[i];\n>> -\n>> -\t/*\n>> -\t * FrameBuffer instances created by wrapping a camera3 provided dmabuf\n>> -\t * are emplaced in this vector of unique_ptr<> for lifetime management.\n>> -\t */\n>> -\tframeBuffers_.reserve(numBuffers);\n>> +\t\tbuffers_[i].buffer = camera3Request->output_buffers[i];\n>>\n>>   \t/* Clone the controls associated with the camera3 request. */\n>>   \tsettings_ = CameraMetadata(camera3Request->settings);\n>> diff --git a/src/android/camera_request.h b/src/android/camera_request.h\n>> index db13f624..a030febf 100644\n>> --- a/src/android/camera_request.h\n>> +++ b/src/android/camera_request.h\n>> @@ -29,6 +29,16 @@ public:\n>>   \t\tError,\n>>   \t};\n>>\n>> +\tstruct StreamBuffer {\n>> +\t\tcamera3_stream_buffer_t buffer;\n>> +\t\t/*\n>> +\t\t * FrameBuffer instances created by wrapping a camera3 provided\n>> +\t\t * dmabuf are emplaced in this vector of unique_ptr<> for\n>> +\t\t * lifetime management.\n>> +\t\t */\n>> +\t\tstd::unique_ptr<libcamera::FrameBuffer> frameBuffer;\n>> +\t};\n>> +\n>>   \tCamera3RequestDescriptor(libcamera::Camera *camera,\n>>   \t\t\t\t const camera3_capture_request_t *camera3Request);\n>>   \t~Camera3RequestDescriptor();\n>> @@ -36,8 +46,9 @@ public:\n>>   \tbool isPending() const { return status_ == Status::Pending; }\n>>\n>>   \tuint32_t frameNumber_ = 0;\n>> -\tstd::vector<camera3_stream_buffer_t> buffers_;\n>> -\tstd::vector<std::unique_ptr<libcamera::FrameBuffer>> frameBuffers_;\n>> +\n>> +\tstd::vector<StreamBuffer> buffers_;\n>> +\n>>   \tCameraMetadata settings_;\n>>   \tstd::unique_ptr<CaptureRequest> request_;\n>>   \tstd::unique_ptr<CameraMetadata> resultMetadata_;\n>> --\n>> 2.31.0\n>>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 3A720C324C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 19 Oct 2021 11:20:50 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id AC93F604FF;\n\tTue, 19 Oct 2021 13:20:49 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C949F604FE\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 19 Oct 2021 13:20:47 +0200 (CEST)","from [192.168.1.106] (unknown [103.251.226.98])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id D23BF12A;\n\tTue, 19 Oct 2021 13:20:46 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"YYIFKINS\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1634642447;\n\tbh=jpmc5sEDiptu+eSkPAF0S5zbZ3mZFLTF/X152Zt+nFk=;\n\th=Subject:To:Cc:References:From:Date:In-Reply-To:From;\n\tb=YYIFKINS5NAKvvZgqVEOXJlM0YUm6ub5OGC/zCIl1+UsSn/lKvSyX8n5TQfG1hCAM\n\tGdXZRU3sv6G41kxmZMUh2DfVA8y2slaEVJKnjEsOP6lsCZa5oXq7AO8WuWP9OUjNU7\n\tgVe2qTIK5Wv1wGKKX4Ie3XZXTzvNTthc3+OGKPoU=","To":"Jacopo Mondi <jacopo@jmondi.org>","References":"<20211018132923.476242-1-umang.jain@ideasonboard.com>\n\t<20211018132923.476242-6-umang.jain@ideasonboard.com>\n\t<20211018162228.2fdkhlorn25ramn2@uno.localdomain>","From":"Umang Jain <umang.jain@ideasonboard.com>","Message-ID":"<b6fb5660-136d-1195-b3bd-8be7fde86e0a@ideasonboard.com>","Date":"Tue, 19 Oct 2021 16:50:42 +0530","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101\n\tThunderbird/78.10.2","MIME-Version":"1.0","In-Reply-To":"<20211018162228.2fdkhlorn25ramn2@uno.localdomain>","Content-Type":"text/plain; charset=utf-8; format=flowed","Content-Transfer-Encoding":"7bit","Content-Language":"en-US","Subject":"Re: [libcamera-devel] [PATCH 05/11] android: camera_device: Create\n\tstruct to track per stream buffer","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]