[libcamera-devel] [RFC PATCH] libcamera, cam, qcam: Reuse Request
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Fri Sep 25 04:39:52 CEST 2020
Hi Paul,
On Fri, Sep 25, 2020 at 11:20:38AM +0900, paul.elder at ideasonboard.com wrote:
> On Thu, Sep 24, 2020 at 03:40:56PM +0300, Laurent Pinchart wrote:
> > On Thu, Sep 24, 2020 at 02:09:51PM +0200, Niklas Söderlund wrote:
> > > On 2020-09-23 21:14:48 +0900, Paul Elder wrote:
> > > > Allow reuse of the Request object by implementing a reset() function.
> > > > This means that the applications now have the responsibility of freeing
> > > > the the Request objects, so make cam and qcam do so.
> > > >
> > > > Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
> > > >
> > > > ---
> > > > In this RFC, I've only made qcam and cam reuse the Request object. Just
> > > > gauging the direction, and then I'll put it in for andoird and gstreamer
> > > > and v4l2-compat as well.
> > > > ---
> > > > include/libcamera/request.h | 2 ++
> > > > src/cam/capture.cpp | 20 ++++++++++----------
> > > > src/cam/capture.h | 3 +++
> > > > src/libcamera/camera.cpp | 4 +---
> > > > src/libcamera/request.cpp | 9 +++++++++
> > > > src/qcam/main_window.cpp | 26 ++++++++++++--------------
> > > > src/qcam/main_window.h | 14 ++++++++++----
> > > > src/qcam/viewfinder.h | 4 +++-
> > > > src/qcam/viewfinder_gl.cpp | 9 +++++----
> > > > src/qcam/viewfinder_gl.h | 5 +++--
> > > > src/qcam/viewfinder_qt.cpp | 10 ++++++----
> > > > src/qcam/viewfinder_qt.h | 8 ++++++--
> > > > 12 files changed, 70 insertions(+), 44 deletions(-)
> > > >
> > > > diff --git a/include/libcamera/request.h b/include/libcamera/request.h
> > > > index 5976ac50..9f615a24 100644
> > > > --- a/include/libcamera/request.h
> > > > +++ b/include/libcamera/request.h
> > > > @@ -38,6 +38,8 @@ public:
> > > > Request &operator=(const Request &) = delete;
> > > > ~Request();
> > > >
> > > > + void reset();
> > > > +
> > > > ControlList &controls() { return *controls_; }
> > > > ControlList &metadata() { return *metadata_; }
> > > > const BufferMap &buffers() const { return bufferMap_; }
> > > > diff --git a/src/cam/capture.cpp b/src/cam/capture.cpp
> > > > index 5510c009..fe9d591a 100644
> > > > --- a/src/cam/capture.cpp
> > > > +++ b/src/cam/capture.cpp
> > > > @@ -65,6 +65,9 @@ int Capture::run(const OptionsParser::Options &options)
> > > > writer_ = nullptr;
> > > > }
> > > >
> > > > + for (Request *req : requests_)
> > > > + delete req;
> > > > +
> > > > delete allocator;
> > > >
> > > > return ret;
> > > > @@ -92,7 +95,6 @@ int Capture::capture(FrameBufferAllocator *allocator)
> > > > * example pushing a button. For now run all streams all the time.
> > > > */
> > > >
> > > > - std::vector<Request *> requests;
> > > > for (unsigned int i = 0; i < nbuffers; i++) {
> > > > Request *request = camera_->createRequest();
> > > > if (!request) {
> > > > @@ -117,7 +119,7 @@ int Capture::capture(FrameBufferAllocator *allocator)
> > > > writer_->mapBuffer(buffer.get());
> > > > }
> > > >
> > > > - requests.push_back(request);
> > > > + requests_.push_back(request);
> > > > }
> > > >
> > > > ret = camera_->start();
> > > > @@ -126,7 +128,7 @@ int Capture::capture(FrameBufferAllocator *allocator)
> > > > return ret;
> > > > }
> > > >
> > > > - for (Request *request : requests) {
> > > > + for (Request *request : requests_) {
> > > > ret = camera_->queueRequest(request);
> > > > if (ret < 0) {
> > > > std::cerr << "Can't queue request" << std::endl;
> > > > @@ -153,10 +155,12 @@ int Capture::capture(FrameBufferAllocator *allocator)
> > > >
> > > > void Capture::requestComplete(Request *request)
> > > > {
> > > > - if (request->status() == Request::RequestCancelled)
> > > > + if (request->status() == Request::RequestCancelled) {
> > > > + request->reset();
> > > > return;
> > > > + }
> > > >
> > > > - const Request::BufferMap &buffers = request->buffers();
> > > > + const Request::BufferMap buffers = request->buffers();
> >
> > A copy isn't very nice, but we can live with it for now.
>
> Without the copy, all the buffers become invalid upon reset :/
I know, that's why I said we can live with it for now :-)
> > > >
> > > > /*
> > > > * Compute the frame rate. The timestamp is arbitrarily retrieved from
> > > > @@ -206,11 +210,7 @@ void Capture::requestComplete(Request *request)
> > > > * 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;
> > > > - }
> > > > + request->reset();
> > >
> > > Hum, is this really "reusing" the request object? I imagined a reused
> > > request would retain its buffers while gaining the ability to be be
> > > requeued to the Camera after it have completed. With this patch we still
> > > need to keep the logic to fill the request with buffers each iteration,
> > > is there some advantage to this I'm missing?
> >
> > Two advantages, we don't free and reallocate the request needlessly, and
> > it can be stored in the application and used after the request handler
> > completes.
> >
> > I don't think retaining buffers by default is a good idea, in many cases
> > we'll have a different number of buffers that can be cycled through than
> > the number of allocated requests.
> >
> > > >
> > > > for (auto it = buffers.begin(); it != buffers.end(); ++it) {
> > > > const Stream *stream = it->first;
> > > > diff --git a/src/cam/capture.h b/src/cam/capture.h
> > > > index 0aebdac9..62cf9bf1 100644
> > > > --- a/src/cam/capture.h
> > > > +++ b/src/cam/capture.h
> > > > @@ -9,6 +9,7 @@
> > > >
> > > > #include <memory>
> > > > #include <stdint.h>
> > > > +#include <vector>
> > > >
> > > > #include <libcamera/buffer.h>
> > > > #include <libcamera/camera.h>
> > > > @@ -43,6 +44,8 @@ private:
> > > > EventLoop *loop_;
> > > > unsigned int captureCount_;
> > > > unsigned int captureLimit_;
> > > > +
> > > > + std::vector<libcamera::Request *> requests_;
> > > > };
> > > >
> > > > #endif /* __CAM_CAPTURE_H__ */
> > > > diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp
> > > > index ae16a64a..4cc68bce 100644
> > > > --- a/src/libcamera/camera.cpp
> > > > +++ b/src/libcamera/camera.cpp
> > > > @@ -974,13 +974,11 @@ int Camera::stop()
> > > > * \param[in] request The request that has completed
> > > > *
> > > > * 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.
> > > > + * the request has completed. It emits the requestCompleted signal.
> > > > */
> > > > void Camera::requestComplete(Request *request)
> > > > {
> > > > requestCompleted.emit(request);
> > > > - delete request;
> > > > }
> > > >
> > > > } /* namespace libcamera */
> > > > diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp
> > > > index 60b30692..606866a6 100644
> > > > --- a/src/libcamera/request.cpp
> > > > +++ b/src/libcamera/request.cpp
> > > > @@ -85,6 +85,15 @@ Request::~Request()
> > > > delete validator_;
> > > > }
> > > >
> >
> > No documentation ? :-) You should also update the documentation of
>
> Not yet :p
>
> > Camera::queueRequest(). Thinking about it, I think we should enforce
> > ownership of requests by the application by returning a
> > std::unique_ptr<Request> from Camera::createRequest(). We may even want
> > to drop Camera::createRequest() completely, but that can be done in a
> > separate patch.
>
> Yeah... but I thought there was a problem when the Request completes,
> since there could be multiple slots, and they all can't receive unique
> pointers.
>
> On the other hand... it's only one application... could we require that
> the application only connect one slot to the Request completion handler,
> and then the application can split it among multiple sub-handlers if it
> wants to? Then we can keep unique_ptr for the Request, and the ownership
> can be clear.
I don't think there's a way to implement this, the number of connected
slots isn't known at compile time, the compiler won't like a
std::unique_ptr<> in a signal in any case.
But that's not what I was proposing. With request reuse, ownership of
the request stays in the application. Passing the request pointer to
Camera::queueRequest() borrows a reference, the function shouldn't take
a unique pointer. The completion handler will thus keep using a normal
pointer too. It's only Camera::createRequest() that would return a
unique pointer, to enforce ownership of the request by the application.
> > > > +void Request::reset()
> > > > +{
> > > > + bufferMap_.clear();
> > > > + pending_.clear();
> >
> > You need to clear controls_ and metadata_ too.
>
> Oh okay, those can't be reused?
Why should they ?
> > > > +
> > > > + status_ = RequestPending;
> > > > + cancelled_ = false;
> > > > +}
> > > > +
> > > > /**
> > > > * \fn Request::controls()
> > > > * \brief Retrieve the request's ControlList
> > > > diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp
> > > > index 985743f3..1531b44f 100644
> > > > --- a/src/qcam/main_window.cpp
> > > > +++ b/src/qcam/main_window.cpp
> > > > @@ -367,7 +367,6 @@ void MainWindow::toggleCapture(bool start)
> > > > int MainWindow::startCapture()
> > > > {
> > > > StreamRoles roles = StreamKeyValueParser::roles(options_[OptStream]);
> > > > - std::vector<Request *> requests;
> > > > int ret;
> > > >
> > > > /* Verify roles are supported. */
> > > > @@ -499,7 +498,7 @@ int MainWindow::startCapture()
> > > > goto error;
> > > > }
> > > >
> > > > - requests.push_back(request);
> > > > + requests_.push_back(request);
> > > > }
> > > >
> > > > /* Start the title timer and the camera. */
> > > > @@ -518,7 +517,7 @@ int MainWindow::startCapture()
> > > > camera_->requestCompleted.connect(this, &MainWindow::requestComplete);
> > > >
> > > > /* Queue all requests. */
> > > > - for (Request *request : requests) {
> > > > + for (Request *request : requests_) {
> > > > ret = camera_->queueRequest(request);
> > > > if (ret < 0) {
> > > > qWarning() << "Can't queue request";
> > > > @@ -535,7 +534,7 @@ error_disconnect:
> > > > camera_->stop();
> > > >
> > > > error:
> > > > - for (Request *request : requests)
> > > > + for (Request *request : requests_)
> > > > delete request;
> > > >
> > > > for (auto &iter : mappedBuffers_) {
> > > > @@ -580,6 +579,9 @@ void MainWindow::stopCapture()
> > > > }
> > > > mappedBuffers_.clear();
> > > >
> > > > + for (Request *req : requests_)
> > > > + delete req;
> >
> > Have you tried stopping and restarting capture ? You delete all the
> > requests here, but the vector still contains the pointers. When capture
> > is restarted I expect issue. A
> >
> > requests_.clear();
>
> Ah, right.
>
> > is needed, and I would also turn it into a
> > std::vector<std::unique_ptr<Request>> to avoid the manual delete loops.
> > Same thing for the cam application (even if in that case capture can't
> > be stopped and restarted at the moment, but let's still do it right).
> >
> > > > +
> > > > delete allocator_;
> > > >
> > > > isCapturing_ = false;
> > > > @@ -701,7 +703,7 @@ void MainWindow::requestComplete(Request *request)
> > > > */
> > > > {
> > > > QMutexLocker locker(&mutex_);
> > > > - doneQueue_.enqueue({ request->buffers(), request->metadata() });
> > > > + doneQueue_.enqueue({ request->buffers(), request->metadata(), request });
> >
> > You aobut enqueuing the request only ? The reason to enqueue a copy of
> > buffers() and metadata() was because the request was deleted right after
> > this function returns, now that it's not the case anymore, we can just
> > pass the request around. The MainWindow::CaptureRequest class can be
> > removed.
>
> ack
>
> > > > }
> > > >
> > > > QCoreApplication::postEvent(this, new CaptureEvent);
> > > > @@ -726,13 +728,13 @@ void MainWindow::processCapture()
> > > >
> > > > /* Process buffers. */
> > > > if (request.buffers_.count(vfStream_))
> > > > - processViewfinder(request.buffers_[vfStream_]);
> > > > + processViewfinder(request.request_, request.buffers_[vfStream_]);
> > > >
> > > > if (request.buffers_.count(rawStream_))
> > > > processRaw(request.buffers_[rawStream_], request.metadata_);
> >
> > Instead of passing the request to processViewfinder(), how about adding
> > it to a free list here, and taking a request from the free list in
> > MainWindow::queueRequest() ? That would avoid the changes to the
> > viewfinder.
>
> ack
>
> > > > }
> > > >
> > > > -void MainWindow::processViewfinder(FrameBuffer *buffer)
> > > > +void MainWindow::processViewfinder(Request *request, FrameBuffer *buffer)
> > > > {
> > > > framesCaptured_++;
> > > >
> > > > @@ -749,16 +751,12 @@ void MainWindow::processViewfinder(FrameBuffer *buffer)
> > > > << "fps:" << Qt::fixed << qSetRealNumberPrecision(2) << fps;
> > > >
> > > > /* Render the frame on the viewfinder. */
> > > > - viewfinder_->render(buffer, &mappedBuffers_[buffer]);
> > > > + viewfinder_->render(request, buffer, &mappedBuffers_[buffer]);
> > > > }
> > > >
> > > > -void MainWindow::queueRequest(FrameBuffer *buffer)
> > > > +void MainWindow::queueRequest(Request *request, FrameBuffer *buffer)
> > > > {
> > > > - Request *request = camera_->createRequest();
> > > > - if (!request) {
> > > > - qWarning() << "Can't create request";
> > > > - return;
> > > > - }
> > > > + request->reset();
> > > >
> > > > request->addBuffer(vfStream_, buffer);
> > > >
> > > > diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h
> > > > index 5c61a4df..83535373 100644
> > > > --- a/src/qcam/main_window.h
> > > > +++ b/src/qcam/main_window.h
> > > > @@ -8,6 +8,7 @@
> > > > #define __QCAM_MAIN_WINDOW_H__
> > > >
> > > > #include <memory>
> > > > +#include <vector>
> > > >
> > > > #include <QElapsedTimer>
> > > > #include <QIcon>
> > > > @@ -22,6 +23,7 @@
> > > > #include <libcamera/camera_manager.h>
> > > > #include <libcamera/controls.h>
> > > > #include <libcamera/framebuffer_allocator.h>
> > > > +#include <libcamera/request.h>
> > > > #include <libcamera/stream.h>
> > > >
> > > > #include "../cam/stream_options.h"
> > > > @@ -49,13 +51,15 @@ public:
> > > > }
> > > >
> > > > CaptureRequest(const Request::BufferMap &buffers,
> > > > - const ControlList &metadata)
> > > > - : buffers_(buffers), metadata_(metadata)
> > > > + const ControlList &metadata,
> > > > + Request * const request)
> > > > + : buffers_(buffers), metadata_(metadata), request_(request)
> > > > {
> > > > }
> > > >
> > > > Request::BufferMap buffers_;
> > > > ControlList metadata_;
> > > > + Request *request_;
> > > > };
> > > >
> > > > class MainWindow : public QMainWindow
> > > > @@ -79,7 +83,7 @@ private Q_SLOTS:
> > > > void captureRaw();
> > > > void processRaw(FrameBuffer *buffer, const ControlList &metadata);
> > > >
> > > > - void queueRequest(FrameBuffer *buffer);
> > > > + void queueRequest(Request *request, FrameBuffer *buffer);
> > > >
> > > > private:
> > > > int createToolbars();
> > > > @@ -96,7 +100,7 @@ private:
> > > > void requestComplete(Request *request);
> > > > void processCapture();
> > > > void processHotplug(HotplugEvent *e);
> > > > - void processViewfinder(FrameBuffer *buffer);
> > > > + void processViewfinder(Request *request, FrameBuffer *buffer);
> > > >
> > > > /* UI elements */
> > > > QToolBar *toolbar_;
> > > > @@ -135,6 +139,8 @@ private:
> > > > QElapsedTimer frameRateInterval_;
> > > > uint32_t previousFrames_;
> > > > uint32_t framesCaptured_;
> > > > +
> > > > + std::vector<Request *> requests_;
> > > > };
> > > >
> > > > #endif /* __QCAM_MAIN_WINDOW__ */
> > > > diff --git a/src/qcam/viewfinder.h b/src/qcam/viewfinder.h
> > > > index 67da1df2..26c20f1b 100644
> > > > --- a/src/qcam/viewfinder.h
> > > > +++ b/src/qcam/viewfinder.h
> > > > @@ -27,7 +27,9 @@ public:
> > > > virtual const QList<libcamera::PixelFormat> &nativeFormats() const = 0;
> > > >
> > > > virtual int setFormat(const libcamera::PixelFormat &format, const QSize &size) = 0;
> > > > - virtual void render(libcamera::FrameBuffer *buffer, MappedBuffer *map) = 0;
> > > > + virtual void render(libcamera::Request *request,
> > > > + libcamera::FrameBuffer *buffer,
> > > > + MappedBuffer *map) = 0;
> > > > virtual void stop() = 0;
> > > >
> > > > virtual QImage getCurrentImage() = 0;
> > > > diff --git a/src/qcam/viewfinder_gl.cpp b/src/qcam/viewfinder_gl.cpp
> > > > index fbe21dcf..c65b41f6 100644
> > > > --- a/src/qcam/viewfinder_gl.cpp
> > > > +++ b/src/qcam/viewfinder_gl.cpp
> > > > @@ -23,7 +23,7 @@ static const QList<libcamera::PixelFormat> supportedFormats{
> > > > };
> > > >
> > > > ViewFinderGL::ViewFinderGL(QWidget *parent)
> > > > - : QOpenGLWidget(parent), buffer_(nullptr), yuvData_(nullptr),
> > > > + : QOpenGLWidget(parent), request_(nullptr), buffer_(nullptr), yuvData_(nullptr),
> > > > fragmentShader_(nullptr), vertexShader_(nullptr),
> > > > vertexBuffer_(QOpenGLBuffer::VertexBuffer),
> > > > textureU_(QOpenGLTexture::Target2D),
> > > > @@ -67,7 +67,7 @@ int ViewFinderGL::setFormat(const libcamera::PixelFormat &format,
> > > > void ViewFinderGL::stop()
> > > > {
> > > > if (buffer_) {
> > > > - renderComplete(buffer_);
> > > > + renderComplete(request_, buffer_);
> > > > buffer_ = nullptr;
> > > > }
> > > > }
> > > > @@ -79,7 +79,7 @@ QImage ViewFinderGL::getCurrentImage()
> > > > return grabFramebuffer();
> > > > }
> > > >
> > > > -void ViewFinderGL::render(libcamera::FrameBuffer *buffer, MappedBuffer *map)
> > > > +void ViewFinderGL::render(libcamera::Request *request, libcamera::FrameBuffer *buffer, MappedBuffer *map)
> > > > {
> > > > if (buffer->planes().size() != 1) {
> > > > qWarning() << "Multi-planar buffers are not supported";
> > > > @@ -87,11 +87,12 @@ void ViewFinderGL::render(libcamera::FrameBuffer *buffer, MappedBuffer *map)
> > > > }
> > > >
> > > > if (buffer_)
> > > > - renderComplete(buffer_);
> > > > + renderComplete(request_, buffer_);
> > > >
> > > > yuvData_ = static_cast<unsigned char *>(map->memory);
> > > > update();
> > > > buffer_ = buffer;
> > > > + request_ = request;
> > > > }
> > > >
> > > > bool ViewFinderGL::selectFormat(const libcamera::PixelFormat &format)
> > > > diff --git a/src/qcam/viewfinder_gl.h b/src/qcam/viewfinder_gl.h
> > > > index 69502b7a..7db41841 100644
> > > > --- a/src/qcam/viewfinder_gl.h
> > > > +++ b/src/qcam/viewfinder_gl.h
> > > > @@ -36,13 +36,13 @@ public:
> > > > const QList<libcamera::PixelFormat> &nativeFormats() const override;
> > > >
> > > > int setFormat(const libcamera::PixelFormat &format, const QSize &size) override;
> > > > - void render(libcamera::FrameBuffer *buffer, MappedBuffer *map) override;
> > > > + void render(libcamera::Request *request, libcamera::FrameBuffer *buffer, MappedBuffer *map) override;
> > > > void stop() override;
> > > >
> > > > QImage getCurrentImage() override;
> > > >
> > > > Q_SIGNALS:
> > > > - void renderComplete(libcamera::FrameBuffer *buffer);
> > > > + void renderComplete(libcamera::Request *request, libcamera::FrameBuffer *buffer);
> > > >
> > > > protected:
> > > > void initializeGL() override;
> > > > @@ -60,6 +60,7 @@ private:
> > > > void doRender();
> > > >
> > > > /* Captured image size, format and buffer */
> > > > + libcamera::Request *request_;
> > > > libcamera::FrameBuffer *buffer_;
> > > > libcamera::PixelFormat format_;
> > > > QSize size_;
> > > > diff --git a/src/qcam/viewfinder_qt.cpp b/src/qcam/viewfinder_qt.cpp
> > > > index e436714c..7f9f913b 100644
> > > > --- a/src/qcam/viewfinder_qt.cpp
> > > > +++ b/src/qcam/viewfinder_qt.cpp
> > > > @@ -34,7 +34,7 @@ static const QMap<libcamera::PixelFormat, QImage::Format> nativeFormats
> > > > };
> > > >
> > > > ViewFinderQt::ViewFinderQt(QWidget *parent)
> > > > - : QWidget(parent), buffer_(nullptr)
> > > > + : QWidget(parent), request_(nullptr), buffer_(nullptr)
> > > > {
> > > > icon_ = QIcon(":camera-off.svg");
> > > > }
> > > > @@ -78,7 +78,8 @@ int ViewFinderQt::setFormat(const libcamera::PixelFormat &format,
> > > > return 0;
> > > > }
> > > >
> > > > -void ViewFinderQt::render(libcamera::FrameBuffer *buffer, MappedBuffer *map)
> > > > +void ViewFinderQt::render(libcamera::Request *request,
> > > > + libcamera::FrameBuffer *buffer, MappedBuffer *map)
> > > > {
> > > > if (buffer->planes().size() != 1) {
> > > > qWarning() << "Multi-planar buffers are not supported";
> > > > @@ -106,6 +107,7 @@ void ViewFinderQt::render(libcamera::FrameBuffer *buffer, MappedBuffer *map)
> > > > size / size_.height(),
> > > > ::nativeFormats[format_]);
> > > > std::swap(buffer, buffer_);
> > > > + std::swap(request, request_);
> > > > } else {
> > > > /*
> > > > * Otherwise, convert the format and release the frame
> > > > @@ -118,7 +120,7 @@ void ViewFinderQt::render(libcamera::FrameBuffer *buffer, MappedBuffer *map)
> > > > update();
> > > >
> > > > if (buffer)
> > > > - renderComplete(buffer);
> > > > + renderComplete(request, buffer);
> > > > }
> > > >
> > > > void ViewFinderQt::stop()
> > > > @@ -126,7 +128,7 @@ void ViewFinderQt::stop()
> > > > image_ = QImage();
> > > >
> > > > if (buffer_) {
> > > > - renderComplete(buffer_);
> > > > + renderComplete(request_, buffer_);
> > > > buffer_ = nullptr;
> > > > }
> > > >
> > > > diff --git a/src/qcam/viewfinder_qt.h b/src/qcam/viewfinder_qt.h
> > > > index d7554288..5f62d7f6 100644
> > > > --- a/src/qcam/viewfinder_qt.h
> > > > +++ b/src/qcam/viewfinder_qt.h
> > > > @@ -17,6 +17,7 @@
> > > > #include <libcamera/buffer.h>
> > > > #include <libcamera/formats.h>
> > > > #include <libcamera/pixel_format.h>
> > > > +#include <libcamera/request.h>
> > > >
> > > > #include "format_converter.h"
> > > > #include "viewfinder.h"
> > > > @@ -32,13 +33,15 @@ public:
> > > > const QList<libcamera::PixelFormat> &nativeFormats() const override;
> > > >
> > > > int setFormat(const libcamera::PixelFormat &format, const QSize &size) override;
> > > > - void render(libcamera::FrameBuffer *buffer, MappedBuffer *map) override;
> > > > + void render(libcamera::Request *request,
> > > > + libcamera::FrameBuffer *buffer,
> > > > + MappedBuffer *map) override;
> > > > void stop() override;
> > > >
> > > > QImage getCurrentImage() override;
> > > >
> > > > Q_SIGNALS:
> > > > - void renderComplete(libcamera::FrameBuffer *buffer);
> > > > + void renderComplete(libcamera::Request *request, libcamera::FrameBuffer *buffer);
> > > >
> > > > protected:
> > > > void paintEvent(QPaintEvent *) override;
> > > > @@ -56,6 +59,7 @@ private:
> > > > QPixmap pixmap_;
> > > >
> > > > /* Buffer and render image */
> > > > + libcamera::Request *request_;
> > > > libcamera::FrameBuffer *buffer_;
> > > > QImage image_;
> > > > QMutex mutex_; /* Prevent concurrent access to image_ */
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list