[libcamera-devel] [PATCH v2 05/21] qcam: main_window: Move capture event processing to main thread

Kieran Bingham kieran.bingham at ideasonboard.com
Mon Mar 23 18:46:01 CET 2020


On 23/03/2020 17:35, Laurent Pinchart wrote:
> To avoid blocking the camera manager for a long amount of time, move
> capture event processing to the main thread. Captured buffers are added
> to a queue and an event is posted to the main window to signal
> availability of a buffer.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>

I believe I added this to v1:

Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>

> ---
> Changes since v1:
> 
> - Add blank line
> ---
>  src/qcam/main_window.cpp | 55 +++++++++++++++++++++++++++++++++++++++-
>  src/qcam/main_window.h   |  8 ++++++
>  2 files changed, 62 insertions(+), 1 deletion(-)
> 
> diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp
> index 354a53367d0f..805690d5006a 100644
> --- a/src/qcam/main_window.cpp
> +++ b/src/qcam/main_window.cpp
> @@ -19,6 +19,7 @@
>  #include <QImage>
>  #include <QImageWriter>
>  #include <QInputDialog>
> +#include <QMutexLocker>
>  #include <QStandardPaths>
>  #include <QTimer>
>  #include <QToolBar>
> @@ -31,6 +32,21 @@
>  
>  using namespace libcamera;
>  
> +class CaptureEvent : public QEvent
> +{
> +public:
> +	CaptureEvent()
> +		: QEvent(type())
> +	{
> +	}
> +
> +	static Type type()
> +	{
> +		static int type = QEvent::registerEventType();
> +		return static_cast<Type>(type);
> +	}
> +};
> +
>  MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options)
>  	: options_(options), cm_(cm), allocator_(nullptr), isCapturing_(false)
>  {
> @@ -63,6 +79,16 @@ MainWindow::~MainWindow()
>  	}
>  }
>  
> +bool MainWindow::event(QEvent *e)
> +{
> +	if (e->type() == CaptureEvent::type()) {
> +		processCapture();
> +		return true;
> +	}
> +
> +	return QMainWindow::event(e);
> +}
> +
>  int MainWindow::createToolbars()
>  {
>  	QAction *action;
> @@ -343,6 +369,13 @@ void MainWindow::stopCapture()
>  
>  	config_.reset();
>  
> +	/*
> +	 * A CaptureEvent may have been posted before we stopped the camera,
> +	 * but not processed yet. Clear the queue of done buffers to avoid
> +	 * racing with the event handler.
> +	 */
> +	doneQueue_.clear();
> +
>  	titleTimer_.stop();
>  	setWindowTitle(title_);
>  }
> @@ -371,10 +404,30 @@ void MainWindow::requestComplete(Request *request)
>  		return;
>  
>  	const std::map<Stream *, FrameBuffer *> &buffers = request->buffers();
> +	FrameBuffer *buffer = buffers.begin()->second;
> +
> +	{
> +		QMutexLocker locker(&mutex_);
> +		doneQueue_.enqueue(buffer);
> +	}
> +
> +	QCoreApplication::postEvent(this, new CaptureEvent);
> +}
> +
> +void MainWindow::processCapture()
> +{
> +	FrameBuffer *buffer;
> +
> +	{
> +		QMutexLocker locker(&mutex_);
> +		if (doneQueue_.isEmpty())
> +			return;
> +
> +		buffer = doneQueue_.dequeue();
> +	}
>  
>  	framesCaptured_++;
>  
> -	FrameBuffer *buffer = buffers.begin()->second;
>  	const FrameMetadata &metadata = buffer->metadata();
>  
>  	double fps = metadata.timestamp - lastBufferTime_;
> diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h
> index 720a3393e3dc..c623120d5894 100644
> --- a/src/qcam/main_window.h
> +++ b/src/qcam/main_window.h
> @@ -11,7 +11,9 @@
>  
>  #include <QElapsedTimer>
>  #include <QMainWindow>
> +#include <QMutex>
>  #include <QObject>
> +#include <QQueue>
>  #include <QTimer>
>  
>  #include <libcamera/buffer.h>
> @@ -40,6 +42,8 @@ public:
>  	MainWindow(CameraManager *cm, const OptionsParser::Options &options);
>  	~MainWindow();
>  
> +	bool event(QEvent *e) override;
> +
>  private Q_SLOTS:
>  	void quit();
>  	void updateTitle();
> @@ -57,6 +61,7 @@ private:
>  	int openCamera();
>  
>  	void requestComplete(Request *request);
> +	void processCapture();
>  	int display(FrameBuffer *buffer);
>  	void queueRequest(FrameBuffer *buffer);
>  
> @@ -78,6 +83,9 @@ private:
>  	uint32_t previousFrames_;
>  	uint32_t framesCaptured_;
>  
> +	QMutex mutex_;
> +	QQueue<FrameBuffer *> doneQueue_;
> +
>  	QToolBar *toolbar_;
>  	ViewFinder *viewfinder_;
>  	std::map<int, std::pair<void *, unsigned int>> mappedBuffers_;
> 

-- 
Regards
--
Kieran


More information about the libcamera-devel mailing list