[libcamera-devel] [RFC PATCH] libcamera, cam, qcam: Reuse Request

Umang Jain email at uajain.com
Fri Sep 25 09:04:34 CEST 2020


Hi,

I have a question/confusion.

On 9/25/20 7:50 AM, paul.elder at ideasonboard.com wrote:
> Hello,
>
> On Thu, Sep 24, 2020 at 03:40:56PM +0300, Laurent Pinchart wrote:
>> Hello,
>>
>> 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 :/
If I copy the BufferMap as is it here, would be also copy all the memory 
allocated to BufferMap's FrameBuffer(s)?
The reason I ask, because reset() seems to bufferMap_.clear() which 
means, it will destroy all members it is holding. Then once 
FrameBuffer(s) are destroyed via reset(), I would expect some 
re-allocation of memory happening somewhere for those FrameBuffer(s). Is 
there where this copy comes into picture?
>
>>>>   
>>>>   	/*
>>>>   	 * 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.
>
>>>> +void Request::reset()
>>>> +{
>>>> +	bufferMap_.clear();
>>>> +	pending_.clear();
>> You need to clear controls_ and metadata_ too.
> Oh okay, those can't be reused?
>
>>>> +
>>>> +	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
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel



More information about the libcamera-devel mailing list