libcamera, android, cam, gstreamer, qcam, v4l2: Reuse Request

Allow reuse of the Request object by implementing reuse(). This means
the applications now have the responsibility of freeing the Request
objects, so make all libcamera users (cam, qcam, v4l2-compat, gstreamer,
android) do so.

Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
This commit is contained in:
Paul Elder 2020-09-23 19:05:41 +09:00
parent 05cdef27ab
commit c753223ad6
15 changed files with 163 additions and 109 deletions

View file

@ -96,7 +96,7 @@ public:
std::unique_ptr<CameraConfiguration> generateConfiguration(const StreamRoles &roles = {}); std::unique_ptr<CameraConfiguration> generateConfiguration(const StreamRoles &roles = {});
int configure(CameraConfiguration *config); int configure(CameraConfiguration *config);
Request *createRequest(uint64_t cookie = 0); std::unique_ptr<Request> createRequest(uint64_t cookie = 0);
int queueRequest(Request *request); int queueRequest(Request *request);
int start(); int start();

View file

@ -31,6 +31,11 @@ public:
RequestCancelled, RequestCancelled,
}; };
enum ReuseFlag {
Default = 0,
ReuseBuffers = (1 << 0),
};
using BufferMap = std::map<const Stream *, FrameBuffer *>; using BufferMap = std::map<const Stream *, FrameBuffer *>;
Request(Camera *camera, uint64_t cookie = 0); Request(Camera *camera, uint64_t cookie = 0);
@ -38,6 +43,8 @@ public:
Request &operator=(const Request &) = delete; Request &operator=(const Request &) = delete;
~Request(); ~Request();
void reuse(ReuseFlag flags = Default);
ControlList &controls() { return *controls_; } ControlList &controls() { return *controls_; }
ControlList &metadata() { return *metadata_; } ControlList &metadata() { return *metadata_; }
const BufferMap &buffers() const { return bufferMap_; } const BufferMap &buffers() const { return bufferMap_; }

View file

@ -1375,8 +1375,12 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques
new Camera3RequestDescriptor(camera3Request->frame_number, new Camera3RequestDescriptor(camera3Request->frame_number,
camera3Request->num_output_buffers); camera3Request->num_output_buffers);
Request *request = std::unique_ptr<Request> request =
camera_->createRequest(reinterpret_cast<uint64_t>(descriptor)); camera_->createRequest(reinterpret_cast<uint64_t>(descriptor));
if (!request) {
LOG(HAL, Error) << "Failed to create request";
return -ENOMEM;
}
LOG(HAL, Debug) << "Queueing Request to libcamera with " LOG(HAL, Debug) << "Queueing Request to libcamera with "
<< descriptor->numBuffers << " HAL streams"; << descriptor->numBuffers << " HAL streams";
@ -1440,7 +1444,6 @@ 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 request;
delete descriptor; delete descriptor;
return -ENOMEM; return -ENOMEM;
} }
@ -1448,14 +1451,16 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques
request->addBuffer(cameraStream->stream(), buffer); request->addBuffer(cameraStream->stream(), buffer);
} }
int ret = camera_->queueRequest(request); int ret = camera_->queueRequest(request.get());
if (ret) { if (ret) {
LOG(HAL, Error) << "Failed to queue request"; LOG(HAL, Error) << "Failed to queue request";
delete request;
delete descriptor; delete descriptor;
return ret; return ret;
} }
/* The request will be deleted in the completion handler. */
request.release();
return 0; return 0;
} }
@ -1559,6 +1564,7 @@ void CameraDevice::requestComplete(Request *request)
callbacks_->process_capture_result(callbacks_, &captureResult); callbacks_->process_capture_result(callbacks_, &captureResult);
delete descriptor; delete descriptor;
delete request;
} }
std::string CameraDevice::logPrefix() const std::string CameraDevice::logPrefix() const

View file

@ -65,6 +65,8 @@ int Capture::run(const OptionsParser::Options &options)
writer_ = nullptr; writer_ = nullptr;
} }
requests_.clear();
delete allocator; delete allocator;
return ret; return ret;
@ -92,9 +94,8 @@ int Capture::capture(FrameBufferAllocator *allocator)
* example pushing a button. For now run all streams all the time. * example pushing a button. For now run all streams all the time.
*/ */
std::vector<Request *> requests;
for (unsigned int i = 0; i < nbuffers; i++) { for (unsigned int i = 0; i < nbuffers; i++) {
Request *request = camera_->createRequest(); std::unique_ptr<Request> request = camera_->createRequest();
if (!request) { if (!request) {
std::cerr << "Can't create request" << std::endl; std::cerr << "Can't create request" << std::endl;
return -ENOMEM; return -ENOMEM;
@ -117,7 +118,7 @@ int Capture::capture(FrameBufferAllocator *allocator)
writer_->mapBuffer(buffer.get()); writer_->mapBuffer(buffer.get());
} }
requests.push_back(request); requests_.push_back(std::move(request));
} }
ret = camera_->start(); ret = camera_->start();
@ -126,8 +127,8 @@ int Capture::capture(FrameBufferAllocator *allocator)
return ret; return ret;
} }
for (Request *request : requests) { for (std::unique_ptr<Request> &request : requests_) {
ret = camera_->queueRequest(request); ret = camera_->queueRequest(request.get());
if (ret < 0) { if (ret < 0) {
std::cerr << "Can't queue request" << std::endl; std::cerr << "Can't queue request" << std::endl;
camera_->stop(); camera_->stop();
@ -202,22 +203,6 @@ void Capture::requestComplete(Request *request)
return; return;
} }
/* request->reuse(Request::ReuseBuffers);
* Create a new request and populate it with one buffer for each
* stream.
*/
request = camera_->createRequest();
if (!request) {
std::cerr << "Can't create request" << std::endl;
return;
}
for (auto it = buffers.begin(); it != buffers.end(); ++it) {
const Stream *stream = it->first;
FrameBuffer *buffer = it->second;
request->addBuffer(stream, buffer);
}
camera_->queueRequest(request); camera_->queueRequest(request);
} }

View file

@ -9,6 +9,7 @@
#include <memory> #include <memory>
#include <stdint.h> #include <stdint.h>
#include <vector>
#include <libcamera/buffer.h> #include <libcamera/buffer.h>
#include <libcamera/camera.h> #include <libcamera/camera.h>
@ -43,6 +44,8 @@ private:
EventLoop *loop_; EventLoop *loop_;
unsigned int captureCount_; unsigned int captureCount_;
unsigned int captureLimit_; unsigned int captureLimit_;
std::vector<std::unique_ptr<libcamera::Request>> requests_;
}; };
#endif /* __CAM_CAPTURE_H__ */ #endif /* __CAM_CAPTURE_H__ */

View file

@ -74,6 +74,8 @@ RequestWrap::~RequestWrap()
if (item.second) if (item.second)
gst_buffer_unref(item.second); gst_buffer_unref(item.second);
} }
delete request_;
} }
void RequestWrap::attachBuffer(GstBuffer *buffer) void RequestWrap::attachBuffer(GstBuffer *buffer)
@ -266,8 +268,8 @@ gst_libcamera_src_task_run(gpointer user_data)
GstLibcameraSrc *self = GST_LIBCAMERA_SRC(user_data); GstLibcameraSrc *self = GST_LIBCAMERA_SRC(user_data);
GstLibcameraSrcState *state = self->state; GstLibcameraSrcState *state = self->state;
Request *request = state->cam_->createRequest(); std::unique_ptr<Request> request = state->cam_->createRequest();
auto wrap = std::make_unique<RequestWrap>(request); auto wrap = std::make_unique<RequestWrap>(request.get());
for (GstPad *srcpad : state->srcpads_) { for (GstPad *srcpad : state->srcpads_) {
GstLibcameraPool *pool = gst_libcamera_pad_get_pool(srcpad); GstLibcameraPool *pool = gst_libcamera_pad_get_pool(srcpad);
GstBuffer *buffer; GstBuffer *buffer;
@ -280,8 +282,7 @@ gst_libcamera_src_task_run(gpointer user_data)
* RequestWrap does not take ownership, and we won't be * RequestWrap does not take ownership, and we won't be
* queueing this one due to lack of buffers. * queueing this one due to lack of buffers.
*/ */
delete request; request.reset();
request = nullptr;
break; break;
} }
@ -291,8 +292,11 @@ gst_libcamera_src_task_run(gpointer user_data)
if (request) { if (request) {
GLibLocker lock(GST_OBJECT(self)); GLibLocker lock(GST_OBJECT(self));
GST_TRACE_OBJECT(self, "Requesting buffers"); GST_TRACE_OBJECT(self, "Requesting buffers");
state->cam_->queueRequest(request); state->cam_->queueRequest(request.get());
state->requests_.push(std::move(wrap)); state->requests_.push(std::move(wrap));
/* The request will be deleted in the completion handler. */
request.release();
} }
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;

View file

@ -847,21 +847,22 @@ int Camera::configure(CameraConfiguration *config)
* handler, and is completely opaque to libcamera. * handler, and is completely opaque to libcamera.
* *
* The ownership of the returned request is passed to the caller, which is * The ownership of the returned request is passed to the caller, which is
* responsible for either queueing the request or deleting it. * responsible for deleting it. The request may be deleted in the completion
* handler, or reused after resetting its state with Request::reuse().
* *
* \context This function is \threadsafe. It may only be called when the camera * \context This function is \threadsafe. It may only be called when the camera
* is in the Configured or Running state as defined in \ref camera_operation. * is in the Configured or Running state as defined in \ref camera_operation.
* *
* \return A pointer to the newly created request, or nullptr on error * \return A pointer to the newly created request, or nullptr on error
*/ */
Request *Camera::createRequest(uint64_t cookie) std::unique_ptr<Request> Camera::createRequest(uint64_t cookie)
{ {
int ret = p_->isAccessAllowed(Private::CameraConfigured, int ret = p_->isAccessAllowed(Private::CameraConfigured,
Private::CameraRunning); Private::CameraRunning);
if (ret < 0) if (ret < 0)
return nullptr; return nullptr;
return new Request(this, cookie); return std::make_unique<Request>(this, cookie);
} }
/** /**
@ -877,9 +878,6 @@ Request *Camera::createRequest(uint64_t cookie)
* Once the request has been queued, the camera will notify its completion * Once the request has been queued, the camera will notify its completion
* through the \ref requestCompleted signal. * through the \ref requestCompleted signal.
* *
* Ownership of the request is transferred to the camera. It will be deleted
* automatically after it completes.
*
* \context This function is \threadsafe. It may only be called when the camera * \context This function is \threadsafe. It may only be called when the camera
* is in the Running state as defined in \ref camera_operation. * is in the Running state as defined in \ref camera_operation.
* *
@ -988,13 +986,11 @@ int Camera::stop()
* \param[in] request The request that has completed * \param[in] request The request that has completed
* *
* This function is called by the pipeline handler to notify the camera that * This function is called by the pipeline handler to notify the camera that
* the request has completed. It emits the requestCompleted signal and deletes * the request has completed. It emits the requestCompleted signal.
* the request.
*/ */
void Camera::requestComplete(Request *request) void Camera::requestComplete(Request *request)
{ {
requestCompleted.emit(request); requestCompleted.emit(request);
delete request;
} }
} /* namespace libcamera */ } /* namespace libcamera */

View file

@ -37,6 +37,15 @@ LOG_DEFINE_CATEGORY(Request)
* The request has been cancelled due to capture stop * The request has been cancelled due to capture stop
*/ */
/**
* \enum Request::ReuseFlag
* Flags to control the behavior of Request::reuse()
* \var Request::Default
* Don't reuse buffers
* \var Request::ReuseBuffers
* Reuse the buffers that were previously added by addBuffer()
*/
/** /**
* \typedef Request::BufferMap * \typedef Request::BufferMap
* \brief A map of Stream to FrameBuffer pointers * \brief A map of Stream to FrameBuffer pointers
@ -85,6 +94,35 @@ Request::~Request()
delete validator_; delete validator_;
} }
/**
* \brief Reset the request for reuse
* \param[in] flags Indicate whether or not to reuse the buffers
*
* Reset the status and controls associated with the request, to allow it to
* be reused and requeued without destruction. This function shall be called
* prior to queueing the request to the camera, in lieu of constructing a new
* request. The application can reuse the buffers that were previously added
* to the request via addBuffer() by setting \a flags to ReuseBuffers.
*/
void Request::reuse(ReuseFlag flags)
{
pending_.clear();
if (flags & ReuseBuffers) {
for (auto pair : bufferMap_) {
pair.second->request_ = this;
pending_.insert(pair.second);
}
} else {
bufferMap_.clear();
}
status_ = RequestPending;
cancelled_ = false;
controls_->clear();
metadata_->clear();
}
/** /**
* \fn Request::controls() * \fn Request::controls()
* \brief Retrieve the request's ControlList * \brief Retrieve the request's ControlList

View file

@ -367,7 +367,6 @@ void MainWindow::toggleCapture(bool start)
int MainWindow::startCapture() int MainWindow::startCapture()
{ {
StreamRoles roles = StreamKeyValueParser::roles(options_[OptStream]); StreamRoles roles = StreamKeyValueParser::roles(options_[OptStream]);
std::vector<Request *> requests;
int ret; int ret;
/* Verify roles are supported. */ /* Verify roles are supported. */
@ -486,7 +485,7 @@ int MainWindow::startCapture()
while (!freeBuffers_[vfStream_].isEmpty()) { while (!freeBuffers_[vfStream_].isEmpty()) {
FrameBuffer *buffer = freeBuffers_[vfStream_].dequeue(); FrameBuffer *buffer = freeBuffers_[vfStream_].dequeue();
Request *request = camera_->createRequest(); std::unique_ptr<Request> request = camera_->createRequest();
if (!request) { if (!request) {
qWarning() << "Can't create request"; qWarning() << "Can't create request";
ret = -ENOMEM; ret = -ENOMEM;
@ -499,7 +498,7 @@ int MainWindow::startCapture()
goto error; goto error;
} }
requests.push_back(request); requests_.push_back(std::move(request));
} }
/* Start the title timer and the camera. */ /* Start the title timer and the camera. */
@ -518,8 +517,8 @@ int MainWindow::startCapture()
camera_->requestCompleted.connect(this, &MainWindow::requestComplete); camera_->requestCompleted.connect(this, &MainWindow::requestComplete);
/* Queue all requests. */ /* Queue all requests. */
for (Request *request : requests) { for (std::unique_ptr<Request> &request : requests_) {
ret = camera_->queueRequest(request); ret = camera_->queueRequest(request.get());
if (ret < 0) { if (ret < 0) {
qWarning() << "Can't queue request"; qWarning() << "Can't queue request";
goto error_disconnect; goto error_disconnect;
@ -535,8 +534,7 @@ error_disconnect:
camera_->stop(); camera_->stop();
error: error:
for (Request *request : requests) requests_.clear();
delete request;
for (auto &iter : mappedBuffers_) { for (auto &iter : mappedBuffers_) {
const MappedBuffer &buffer = iter.second; const MappedBuffer &buffer = iter.second;
@ -580,6 +578,8 @@ void MainWindow::stopCapture()
} }
mappedBuffers_.clear(); mappedBuffers_.clear();
requests_.clear();
delete allocator_; delete allocator_;
isCapturing_ = false; isCapturing_ = false;
@ -701,7 +701,7 @@ void MainWindow::requestComplete(Request *request)
*/ */
{ {
QMutexLocker locker(&mutex_); QMutexLocker locker(&mutex_);
doneQueue_.enqueue({ request->buffers(), request->metadata() }); doneQueue_.enqueue(request);
} }
QCoreApplication::postEvent(this, new CaptureEvent); QCoreApplication::postEvent(this, new CaptureEvent);
@ -714,8 +714,7 @@ void MainWindow::processCapture()
* if stopCapture() has been called while a CaptureEvent was posted but * if stopCapture() has been called while a CaptureEvent was posted but
* not processed yet. Return immediately in that case. * not processed yet. Return immediately in that case.
*/ */
CaptureRequest request; Request *request;
{ {
QMutexLocker locker(&mutex_); QMutexLocker locker(&mutex_);
if (doneQueue_.isEmpty()) if (doneQueue_.isEmpty())
@ -725,11 +724,15 @@ void MainWindow::processCapture()
} }
/* Process buffers. */ /* Process buffers. */
if (request.buffers_.count(vfStream_)) if (request->buffers().count(vfStream_))
processViewfinder(request.buffers_[vfStream_]); processViewfinder(request->buffers().at(vfStream_));
if (request.buffers_.count(rawStream_)) if (request->buffers().count(rawStream_))
processRaw(request.buffers_[rawStream_], request.metadata_); processRaw(request->buffers().at(rawStream_), request->metadata());
request->reuse();
QMutexLocker locker(&mutex_);
freeQueue_.enqueue(request);
} }
void MainWindow::processViewfinder(FrameBuffer *buffer) void MainWindow::processViewfinder(FrameBuffer *buffer)
@ -754,10 +757,13 @@ void MainWindow::processViewfinder(FrameBuffer *buffer)
void MainWindow::queueRequest(FrameBuffer *buffer) void MainWindow::queueRequest(FrameBuffer *buffer)
{ {
Request *request = camera_->createRequest(); Request *request;
if (!request) { {
qWarning() << "Can't create request"; QMutexLocker locker(&mutex_);
return; if (freeQueue_.isEmpty())
return;
request = freeQueue_.dequeue();
} }
request->addBuffer(vfStream_, buffer); request->addBuffer(vfStream_, buffer);

View file

@ -8,6 +8,7 @@
#define __QCAM_MAIN_WINDOW_H__ #define __QCAM_MAIN_WINDOW_H__
#include <memory> #include <memory>
#include <vector>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QIcon> #include <QIcon>
@ -22,6 +23,7 @@
#include <libcamera/camera_manager.h> #include <libcamera/camera_manager.h>
#include <libcamera/controls.h> #include <libcamera/controls.h>
#include <libcamera/framebuffer_allocator.h> #include <libcamera/framebuffer_allocator.h>
#include <libcamera/request.h>
#include <libcamera/stream.h> #include <libcamera/stream.h>
#include "../cam/stream_options.h" #include "../cam/stream_options.h"
@ -41,23 +43,6 @@ enum {
OptStream = 's', OptStream = 's',
}; };
class CaptureRequest
{
public:
CaptureRequest()
{
}
CaptureRequest(const Request::BufferMap &buffers,
const ControlList &metadata)
: buffers_(buffers), metadata_(metadata)
{
}
Request::BufferMap buffers_;
ControlList metadata_;
};
class MainWindow : public QMainWindow class MainWindow : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
@ -128,13 +113,16 @@ private:
Stream *vfStream_; Stream *vfStream_;
Stream *rawStream_; Stream *rawStream_;
std::map<const Stream *, QQueue<FrameBuffer *>> freeBuffers_; std::map<const Stream *, QQueue<FrameBuffer *>> freeBuffers_;
QQueue<CaptureRequest> doneQueue_; QQueue<Request *> doneQueue_;
QMutex mutex_; /* Protects freeBuffers_ and doneQueue_ */ QQueue<Request *> freeQueue_;
QMutex mutex_; /* Protects freeBuffers_, doneQueue_, and freeQueue_ */
uint64_t lastBufferTime_; uint64_t lastBufferTime_;
QElapsedTimer frameRateInterval_; QElapsedTimer frameRateInterval_;
uint32_t previousFrames_; uint32_t previousFrames_;
uint32_t framesCaptured_; uint32_t framesCaptured_;
std::vector<std::unique_ptr<Request>> requests_;
}; };
#endif /* __QCAM_MAIN_WINDOW__ */ #endif /* __QCAM_MAIN_WINDOW__ */

View file

@ -49,6 +49,8 @@ int V4L2Camera::open(StreamConfiguration *streamConfig)
void V4L2Camera::close() void V4L2Camera::close()
{ {
requestPool_.clear();
delete bufferAllocator_; delete bufferAllocator_;
bufferAllocator_ = nullptr; bufferAllocator_ = nullptr;
@ -96,6 +98,7 @@ void V4L2Camera::requestComplete(Request *request)
if (ret != sizeof(data)) if (ret != sizeof(data))
LOG(V4L2Compat, Error) << "Failed to signal eventfd POLLIN"; LOG(V4L2Compat, Error) << "Failed to signal eventfd POLLIN";
request->reuse();
{ {
MutexLocker locker(bufferMutex_); MutexLocker locker(bufferMutex_);
bufferAvailableCount_++; bufferAvailableCount_++;
@ -154,16 +157,30 @@ int V4L2Camera::validateConfiguration(const PixelFormat &pixelFormat,
return 0; return 0;
} }
int V4L2Camera::allocBuffers([[maybe_unused]] unsigned int count) int V4L2Camera::allocBuffers(unsigned int count)
{ {
Stream *stream = config_->at(0).stream(); Stream *stream = config_->at(0).stream();
return bufferAllocator_->allocate(stream); int ret = bufferAllocator_->allocate(stream);
if (ret < 0)
return ret;
for (unsigned int i = 0; i < count; i++) {
std::unique_ptr<Request> request = camera_->createRequest(i);
if (!request) {
requestPool_.clear();
return -ENOMEM;
}
requestPool_.push_back(std::move(request));
}
return ret;
} }
void V4L2Camera::freeBuffers() void V4L2Camera::freeBuffers()
{ {
pendingRequests_.clear(); pendingRequests_.clear();
requestPool_.clear();
Stream *stream = config_->at(0).stream(); Stream *stream = config_->at(0).stream();
bufferAllocator_->free(stream); bufferAllocator_->free(stream);
@ -192,9 +209,9 @@ int V4L2Camera::streamOn()
isRunning_ = true; isRunning_ = true;
for (std::unique_ptr<Request> &req : pendingRequests_) { for (Request *req : pendingRequests_) {
/* \todo What should we do if this returns -EINVAL? */ /* \todo What should we do if this returns -EINVAL? */
ret = camera_->queueRequest(req.release()); ret = camera_->queueRequest(req);
if (ret < 0) if (ret < 0)
return ret == -EACCES ? -EBUSY : ret; return ret == -EACCES ? -EBUSY : ret;
} }
@ -206,8 +223,12 @@ int V4L2Camera::streamOn()
int V4L2Camera::streamOff() int V4L2Camera::streamOff()
{ {
if (!isRunning_) if (!isRunning_) {
for (std::unique_ptr<Request> &req : requestPool_)
req->reuse();
return 0; return 0;
}
pendingRequests_.clear(); pendingRequests_.clear();
@ -226,12 +247,11 @@ int V4L2Camera::streamOff()
int V4L2Camera::qbuf(unsigned int index) int V4L2Camera::qbuf(unsigned int index)
{ {
std::unique_ptr<Request> request = if (index >= requestPool_.size()) {
std::unique_ptr<Request>(camera_->createRequest(index)); LOG(V4L2Compat, Error) << "Invalid index";
if (!request) { return -EINVAL;
LOG(V4L2Compat, Error) << "Can't create request";
return -ENOMEM;
} }
Request *request = requestPool_[index].get();
Stream *stream = config_->at(0).stream(); Stream *stream = config_->at(0).stream();
FrameBuffer *buffer = bufferAllocator_->buffers(stream)[index].get(); FrameBuffer *buffer = bufferAllocator_->buffers(stream)[index].get();
@ -242,11 +262,11 @@ int V4L2Camera::qbuf(unsigned int index)
} }
if (!isRunning_) { if (!isRunning_) {
pendingRequests_.push_back(std::move(request)); pendingRequests_.push_back(request);
return 0; return 0;
} }
ret = camera_->queueRequest(request.release()); ret = camera_->queueRequest(request);
if (ret < 0) { if (ret < 0) {
LOG(V4L2Compat, Error) << "Can't queue request"; LOG(V4L2Compat, Error) << "Can't queue request";
return ret == -EACCES ? -EBUSY : ret; return ret == -EACCES ? -EBUSY : ret;

View file

@ -76,7 +76,9 @@ private:
std::mutex bufferLock_; std::mutex bufferLock_;
FrameBufferAllocator *bufferAllocator_; FrameBufferAllocator *bufferAllocator_;
std::deque<std::unique_ptr<Request>> pendingRequests_; std::vector<std::unique_ptr<Request>> requestPool_;
std::deque<Request *> pendingRequests_;
std::deque<std::unique_ptr<Buffer>> completedBuffers_; std::deque<std::unique_ptr<Buffer>> completedBuffers_;
int efd_; int efd_;

View file

@ -58,7 +58,7 @@ protected:
const Stream *stream = buffers.begin()->first; const Stream *stream = buffers.begin()->first;
FrameBuffer *buffer = buffers.begin()->second; FrameBuffer *buffer = buffers.begin()->second;
request = camera_->createRequest(); request->reuse();
request->addBuffer(stream, buffer); request->addBuffer(stream, buffer);
camera_->queueRequest(request); camera_->queueRequest(request);
} }
@ -98,9 +98,8 @@ protected:
if (ret != TestPass) if (ret != TestPass)
return ret; return ret;
std::vector<Request *> requests;
for (const std::unique_ptr<FrameBuffer> &buffer : source.buffers()) { for (const std::unique_ptr<FrameBuffer> &buffer : source.buffers()) {
Request *request = camera_->createRequest(); std::unique_ptr<Request> request = camera_->createRequest();
if (!request) { if (!request) {
std::cout << "Failed to create request" << std::endl; std::cout << "Failed to create request" << std::endl;
return TestFail; return TestFail;
@ -111,7 +110,7 @@ protected:
return TestFail; return TestFail;
} }
requests.push_back(request); requests_.push_back(std::move(request));
} }
completeRequestsCount_ = 0; completeRequestsCount_ = 0;
@ -125,8 +124,8 @@ protected:
return TestFail; return TestFail;
} }
for (Request *request : requests) { for (std::unique_ptr<Request> &request : requests_) {
if (camera_->queueRequest(request)) { if (camera_->queueRequest(request.get())) {
std::cout << "Failed to queue request" << std::endl; std::cout << "Failed to queue request" << std::endl;
return TestFail; return TestFail;
} }
@ -160,6 +159,8 @@ protected:
} }
private: private:
std::vector<std::unique_ptr<Request>> requests_;
unsigned int completeBuffersCount_; unsigned int completeBuffersCount_;
unsigned int completeRequestsCount_; unsigned int completeRequestsCount_;
std::unique_ptr<CameraConfiguration> config_; std::unique_ptr<CameraConfiguration> config_;

View file

@ -52,7 +52,7 @@ protected:
const Stream *stream = buffers.begin()->first; const Stream *stream = buffers.begin()->first;
FrameBuffer *buffer = buffers.begin()->second; FrameBuffer *buffer = buffers.begin()->second;
request = camera_->createRequest(); request->reuse();
request->addBuffer(stream, buffer); request->addBuffer(stream, buffer);
camera_->queueRequest(request); camera_->queueRequest(request);
} }
@ -98,9 +98,8 @@ protected:
if (ret < 0) if (ret < 0)
return TestFail; return TestFail;
std::vector<Request *> requests;
for (const std::unique_ptr<FrameBuffer> &buffer : allocator_->buffers(stream)) { for (const std::unique_ptr<FrameBuffer> &buffer : allocator_->buffers(stream)) {
Request *request = camera_->createRequest(); std::unique_ptr<Request> request = camera_->createRequest();
if (!request) { if (!request) {
cout << "Failed to create request" << endl; cout << "Failed to create request" << endl;
return TestFail; return TestFail;
@ -111,7 +110,7 @@ protected:
return TestFail; return TestFail;
} }
requests.push_back(request); requests_.push_back(std::move(request));
} }
completeRequestsCount_ = 0; completeRequestsCount_ = 0;
@ -125,8 +124,8 @@ protected:
return TestFail; return TestFail;
} }
for (Request *request : requests) { for (std::unique_ptr<Request> &request : requests_) {
if (camera_->queueRequest(request)) { if (camera_->queueRequest(request.get())) {
cout << "Failed to queue request" << endl; cout << "Failed to queue request" << endl;
return TestFail; return TestFail;
} }
@ -161,6 +160,8 @@ protected:
return TestPass; return TestPass;
} }
std::vector<std::unique_ptr<Request>> requests_;
std::unique_ptr<CameraConfiguration> config_; std::unique_ptr<CameraConfiguration> config_;
FrameBufferAllocator *allocator_; FrameBufferAllocator *allocator_;
}; };

View file

@ -101,13 +101,10 @@ protected:
return TestFail; return TestFail;
/* Test operations which should pass. */ /* Test operations which should pass. */
Request *request2 = camera_->createRequest(); std::unique_ptr<Request> request2 = camera_->createRequest();
if (!request2) if (!request2)
return TestFail; return TestFail;
/* Never handed to hardware so need to manually delete it. */
delete request2;
/* Test valid state transitions, end in Running state. */ /* Test valid state transitions, end in Running state. */
if (camera_->release()) if (camera_->release())
return TestFail; return TestFail;
@ -146,7 +143,7 @@ protected:
return TestFail; return TestFail;
/* Test operations which should pass. */ /* Test operations which should pass. */
Request *request = camera_->createRequest(); std::unique_ptr<Request> request = camera_->createRequest();
if (!request) if (!request)
return TestFail; return TestFail;
@ -154,7 +151,7 @@ protected:
if (request->addBuffer(stream, allocator_->buffers(stream)[0].get())) if (request->addBuffer(stream, allocator_->buffers(stream)[0].get()))
return TestFail; return TestFail;
if (camera_->queueRequest(request)) if (camera_->queueRequest(request.get()))
return TestFail; return TestFail;
/* Test valid state transitions, end in Available state. */ /* Test valid state transitions, end in Available state. */