android: CameraDevice: Fix Camera3RequestDescriptor leakage
CameraDevice creates Camera3RequestDescriptor in processCaptureRequest() and disallocates in requestComplete(). Camera3RequestDescriptor can never be destroyed if requestComplete() is never called. This avoid the memory leakage by storing them in map CameraRequestDescriptor. Signed-off-by: Hirokazu Honda <hiroh@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
0b661d70ec
commit
d40430116b
4 changed files with 57 additions and 39 deletions
|
@ -381,16 +381,12 @@ CameraDevice::Camera3RequestDescriptor::Camera3RequestDescriptor(
|
||||||
settings_ = CameraMetadata(camera3Request->settings);
|
settings_ = CameraMetadata(camera3Request->settings);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create the libcamera::Request unique_ptr<> to tie its lifetime
|
* Create the CaptureRequest, stored as a unique_ptr<> to tie its
|
||||||
* to the descriptor's one. Set the descriptor's address as the
|
* lifetime to the descriptor.
|
||||||
* request's cookie to retrieve it at completion time.
|
|
||||||
*/
|
*/
|
||||||
request_ = std::make_unique<CaptureRequest>(camera,
|
request_ = std::make_unique<CaptureRequest>(camera);
|
||||||
reinterpret_cast<uint64_t>(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CameraDevice::Camera3RequestDescriptor::~Camera3RequestDescriptor() = default;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* \class CameraDevice
|
* \class CameraDevice
|
||||||
*
|
*
|
||||||
|
@ -767,6 +763,7 @@ void CameraDevice::stop()
|
||||||
worker_.stop();
|
worker_.stop();
|
||||||
camera_->stop();
|
camera_->stop();
|
||||||
|
|
||||||
|
descriptors_.clear();
|
||||||
running_ = false;
|
running_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1933,8 +1930,8 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques
|
||||||
* The descriptor and the associated memory reserved here are freed
|
* The descriptor and the associated memory reserved here are freed
|
||||||
* at request complete time.
|
* at request complete time.
|
||||||
*/
|
*/
|
||||||
Camera3RequestDescriptor *descriptor =
|
Camera3RequestDescriptor descriptor(camera_.get(), camera3Request);
|
||||||
new Camera3RequestDescriptor(camera_.get(), camera3Request);
|
|
||||||
/*
|
/*
|
||||||
* \todo The Android request model is incremental, settings passed in
|
* \todo The Android request model is incremental, settings passed in
|
||||||
* previous requests are to be effective until overridden explicitly in
|
* previous requests are to be effective until overridden explicitly in
|
||||||
|
@ -1944,12 +1941,12 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques
|
||||||
if (camera3Request->settings)
|
if (camera3Request->settings)
|
||||||
lastSettings_ = camera3Request->settings;
|
lastSettings_ = camera3Request->settings;
|
||||||
else
|
else
|
||||||
descriptor->settings_ = lastSettings_;
|
descriptor.settings_ = lastSettings_;
|
||||||
|
|
||||||
LOG(HAL, Debug) << "Queueing request " << descriptor->request_->cookie()
|
LOG(HAL, Debug) << "Queueing request " << descriptor.request_->cookie()
|
||||||
<< " with " << descriptor->buffers_.size() << " streams";
|
<< " with " << descriptor.buffers_.size() << " streams";
|
||||||
for (unsigned int i = 0; i < descriptor->buffers_.size(); ++i) {
|
for (unsigned int i = 0; i < descriptor.buffers_.size(); ++i) {
|
||||||
const camera3_stream_buffer_t &camera3Buffer = descriptor->buffers_[i];
|
const camera3_stream_buffer_t &camera3Buffer = descriptor.buffers_[i];
|
||||||
camera3_stream *camera3Stream = camera3Buffer.stream;
|
camera3_stream *camera3Stream = camera3Buffer.stream;
|
||||||
CameraStream *cameraStream = static_cast<CameraStream *>(camera3Stream->priv);
|
CameraStream *cameraStream = static_cast<CameraStream *>(camera3Stream->priv);
|
||||||
|
|
||||||
|
@ -1982,7 +1979,7 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques
|
||||||
* lifetime management only.
|
* lifetime management only.
|
||||||
*/
|
*/
|
||||||
buffer = createFrameBuffer(*camera3Buffer.buffer);
|
buffer = createFrameBuffer(*camera3Buffer.buffer);
|
||||||
descriptor->frameBuffers_.emplace_back(buffer);
|
descriptor.frameBuffers_.emplace_back(buffer);
|
||||||
LOG(HAL, Debug) << ss.str() << " (direct)";
|
LOG(HAL, Debug) << ss.str() << " (direct)";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2001,11 +1998,10 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques
|
||||||
|
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
LOG(HAL, Error) << "Failed to create buffer";
|
LOG(HAL, Error) << "Failed to create buffer";
|
||||||
delete descriptor;
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptor->request_->addBuffer(cameraStream->stream(), buffer,
|
descriptor.request_->addBuffer(cameraStream->stream(), buffer,
|
||||||
camera3Buffer.acquire_fence);
|
camera3Buffer.acquire_fence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2013,11 +2009,16 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques
|
||||||
* Translate controls from Android to libcamera and queue the request
|
* Translate controls from Android to libcamera and queue the request
|
||||||
* to the CameraWorker thread.
|
* to the CameraWorker thread.
|
||||||
*/
|
*/
|
||||||
int ret = processControls(descriptor);
|
int ret = processControls(&descriptor);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
worker_.queueRequest(descriptor->request_.get());
|
worker_.queueRequest(descriptor.request_.get());
|
||||||
|
|
||||||
|
{
|
||||||
|
std::scoped_lock<std::mutex> lock(mutex_);
|
||||||
|
descriptors_[descriptor.request_->cookie()] = std::move(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2027,8 +2028,21 @@ void CameraDevice::requestComplete(Request *request)
|
||||||
const Request::BufferMap &buffers = request->buffers();
|
const Request::BufferMap &buffers = request->buffers();
|
||||||
camera3_buffer_status status = CAMERA3_BUFFER_STATUS_OK;
|
camera3_buffer_status status = CAMERA3_BUFFER_STATUS_OK;
|
||||||
std::unique_ptr<CameraMetadata> resultMetadata;
|
std::unique_ptr<CameraMetadata> resultMetadata;
|
||||||
Camera3RequestDescriptor *descriptor =
|
|
||||||
reinterpret_cast<Camera3RequestDescriptor *>(request->cookie());
|
decltype(descriptors_)::node_type node;
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
Camera3RequestDescriptor &descriptor = node.mapped();
|
||||||
|
|
||||||
if (request->status() != Request::RequestComplete) {
|
if (request->status() != Request::RequestComplete) {
|
||||||
LOG(HAL, Error) << "Request not successfully completed: "
|
LOG(HAL, Error) << "Request not successfully completed: "
|
||||||
|
@ -2037,7 +2051,7 @@ void CameraDevice::requestComplete(Request *request)
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(HAL, Debug) << "Request " << request->cookie() << " completed with "
|
LOG(HAL, Debug) << "Request " << request->cookie() << " completed with "
|
||||||
<< descriptor->buffers_.size() << " streams";
|
<< descriptor.buffers_.size() << " streams";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* \todo The timestamp used for the metadata is currently always taken
|
* \todo The timestamp used for the metadata is currently always taken
|
||||||
|
@ -2046,10 +2060,10 @@ void CameraDevice::requestComplete(Request *request)
|
||||||
* pipeline handlers) timestamp in the Request itself.
|
* pipeline handlers) timestamp in the Request itself.
|
||||||
*/
|
*/
|
||||||
uint64_t timestamp = buffers.begin()->second->metadata().timestamp;
|
uint64_t timestamp = buffers.begin()->second->metadata().timestamp;
|
||||||
resultMetadata = getResultMetadata(*descriptor, timestamp);
|
resultMetadata = getResultMetadata(descriptor, timestamp);
|
||||||
|
|
||||||
/* Handle any JPEG compression. */
|
/* Handle any JPEG compression. */
|
||||||
for (camera3_stream_buffer_t &buffer : descriptor->buffers_) {
|
for (camera3_stream_buffer_t &buffer : descriptor.buffers_) {
|
||||||
CameraStream *cameraStream =
|
CameraStream *cameraStream =
|
||||||
static_cast<CameraStream *>(buffer.stream->priv);
|
static_cast<CameraStream *>(buffer.stream->priv);
|
||||||
|
|
||||||
|
@ -2064,7 +2078,7 @@ void CameraDevice::requestComplete(Request *request)
|
||||||
|
|
||||||
int ret = cameraStream->process(*src,
|
int ret = cameraStream->process(*src,
|
||||||
*buffer.buffer,
|
*buffer.buffer,
|
||||||
descriptor->settings_,
|
descriptor.settings_,
|
||||||
resultMetadata.get());
|
resultMetadata.get());
|
||||||
if (ret) {
|
if (ret) {
|
||||||
status = CAMERA3_BUFFER_STATUS_ERROR;
|
status = CAMERA3_BUFFER_STATUS_ERROR;
|
||||||
|
@ -2081,17 +2095,17 @@ void CameraDevice::requestComplete(Request *request)
|
||||||
|
|
||||||
/* Prepare to call back the Android camera stack. */
|
/* Prepare to call back the Android camera stack. */
|
||||||
camera3_capture_result_t captureResult = {};
|
camera3_capture_result_t captureResult = {};
|
||||||
captureResult.frame_number = descriptor->frameNumber_;
|
captureResult.frame_number = descriptor.frameNumber_;
|
||||||
captureResult.num_output_buffers = descriptor->buffers_.size();
|
captureResult.num_output_buffers = descriptor.buffers_.size();
|
||||||
for (camera3_stream_buffer_t &buffer : descriptor->buffers_) {
|
for (camera3_stream_buffer_t &buffer : descriptor.buffers_) {
|
||||||
buffer.acquire_fence = -1;
|
buffer.acquire_fence = -1;
|
||||||
buffer.release_fence = -1;
|
buffer.release_fence = -1;
|
||||||
buffer.status = status;
|
buffer.status = status;
|
||||||
}
|
}
|
||||||
captureResult.output_buffers = descriptor->buffers_.data();
|
captureResult.output_buffers = descriptor.buffers_.data();
|
||||||
|
|
||||||
if (status == CAMERA3_BUFFER_STATUS_OK) {
|
if (status == CAMERA3_BUFFER_STATUS_OK) {
|
||||||
notifyShutter(descriptor->frameNumber_, timestamp);
|
notifyShutter(descriptor.frameNumber_, timestamp);
|
||||||
|
|
||||||
captureResult.partial_result = 1;
|
captureResult.partial_result = 1;
|
||||||
captureResult.result = resultMetadata->get();
|
captureResult.result = resultMetadata->get();
|
||||||
|
@ -2104,13 +2118,11 @@ void CameraDevice::requestComplete(Request *request)
|
||||||
* is here signalled. Make sure the error path plays well with
|
* is here signalled. Make sure the error path plays well with
|
||||||
* the camera stack state machine.
|
* the camera stack state machine.
|
||||||
*/
|
*/
|
||||||
notifyError(descriptor->frameNumber_,
|
notifyError(descriptor.frameNumber_,
|
||||||
descriptor->buffers_[0].stream);
|
descriptor.buffers_[0].stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks_->process_capture_result(callbacks_, &captureResult);
|
callbacks_->process_capture_result(callbacks_, &captureResult);
|
||||||
|
|
||||||
delete descriptor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CameraDevice::logPrefix() const
|
std::string CameraDevice::logPrefix() const
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -69,11 +70,13 @@ private:
|
||||||
CameraDevice(unsigned int id, std::shared_ptr<libcamera::Camera> camera);
|
CameraDevice(unsigned int id, std::shared_ptr<libcamera::Camera> camera);
|
||||||
|
|
||||||
struct Camera3RequestDescriptor {
|
struct Camera3RequestDescriptor {
|
||||||
|
Camera3RequestDescriptor() = default;
|
||||||
|
~Camera3RequestDescriptor() = default;
|
||||||
Camera3RequestDescriptor(libcamera::Camera *camera,
|
Camera3RequestDescriptor(libcamera::Camera *camera,
|
||||||
const camera3_capture_request_t *camera3Request);
|
const camera3_capture_request_t *camera3Request);
|
||||||
~Camera3RequestDescriptor();
|
Camera3RequestDescriptor &operator=(Camera3RequestDescriptor &&) = default;
|
||||||
|
|
||||||
uint32_t frameNumber_;
|
uint32_t frameNumber_ = 0;
|
||||||
std::vector<camera3_stream_buffer_t> buffers_;
|
std::vector<camera3_stream_buffer_t> buffers_;
|
||||||
std::vector<std::unique_ptr<libcamera::FrameBuffer>> frameBuffers_;
|
std::vector<std::unique_ptr<libcamera::FrameBuffer>> frameBuffers_;
|
||||||
CameraMetadata settings_;
|
CameraMetadata settings_;
|
||||||
|
@ -124,6 +127,9 @@ private:
|
||||||
std::map<int, libcamera::PixelFormat> formatsMap_;
|
std::map<int, libcamera::PixelFormat> formatsMap_;
|
||||||
std::vector<CameraStream> streams_;
|
std::vector<CameraStream> streams_;
|
||||||
|
|
||||||
|
std::mutex mutex_; /* Protect descriptors_ */
|
||||||
|
std::map<uint64_t, Camera3RequestDescriptor> descriptors_;
|
||||||
|
|
||||||
std::string maker_;
|
std::string maker_;
|
||||||
std::string model_;
|
std::string model_;
|
||||||
|
|
||||||
|
|
|
@ -26,10 +26,10 @@ LOG_DECLARE_CATEGORY(HAL)
|
||||||
* by the CameraWorker which queues it to the libcamera::Camera after handling
|
* by the CameraWorker which queues it to the libcamera::Camera after handling
|
||||||
* fences.
|
* fences.
|
||||||
*/
|
*/
|
||||||
CaptureRequest::CaptureRequest(libcamera::Camera *camera, uint64_t cookie)
|
CaptureRequest::CaptureRequest(libcamera::Camera *camera)
|
||||||
: camera_(camera)
|
: camera_(camera)
|
||||||
{
|
{
|
||||||
request_ = camera_->createRequest(cookie);
|
request_ = camera_->createRequest(reinterpret_cast<uint64_t>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CaptureRequest::addBuffer(Stream *stream, FrameBuffer *buffer, int fence)
|
void CaptureRequest::addBuffer(Stream *stream, FrameBuffer *buffer, int fence)
|
||||||
|
|
|
@ -22,7 +22,7 @@ class CameraDevice;
|
||||||
class CaptureRequest
|
class CaptureRequest
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CaptureRequest(libcamera::Camera *camera, uint64_t cookie);
|
CaptureRequest(libcamera::Camera *camera);
|
||||||
|
|
||||||
const std::vector<int> &fences() const { return acquireFences_; }
|
const std::vector<int> &fences() const { return acquireFences_; }
|
||||||
libcamera::ControlList &controls() { return request_->controls(); }
|
libcamera::ControlList &controls() { return request_->controls(); }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue