mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-20 02:45:08 +03:00
qcam: main_window: Move capture event processing to main thread
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@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
parent
8e7d1bbe9b
commit
77ea51820a
2 changed files with 62 additions and 1 deletions
|
@ -19,6 +19,7 @@
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QImageWriter>
|
#include <QImageWriter>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
|
#include <QMutexLocker>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QToolBar>
|
#include <QToolBar>
|
||||||
|
@ -31,6 +32,21 @@
|
||||||
|
|
||||||
using namespace libcamera;
|
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)
|
MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options)
|
||||||
: options_(options), cm_(cm), allocator_(nullptr), isCapturing_(false)
|
: 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()
|
int MainWindow::createToolbars()
|
||||||
{
|
{
|
||||||
QAction *action;
|
QAction *action;
|
||||||
|
@ -343,6 +369,13 @@ void MainWindow::stopCapture()
|
||||||
|
|
||||||
config_.reset();
|
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();
|
titleTimer_.stop();
|
||||||
setWindowTitle(title_);
|
setWindowTitle(title_);
|
||||||
}
|
}
|
||||||
|
@ -371,10 +404,30 @@ void MainWindow::requestComplete(Request *request)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const std::map<Stream *, FrameBuffer *> &buffers = request->buffers();
|
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_++;
|
framesCaptured_++;
|
||||||
|
|
||||||
FrameBuffer *buffer = buffers.begin()->second;
|
|
||||||
const FrameMetadata &metadata = buffer->metadata();
|
const FrameMetadata &metadata = buffer->metadata();
|
||||||
|
|
||||||
double fps = metadata.timestamp - lastBufferTime_;
|
double fps = metadata.timestamp - lastBufferTime_;
|
||||||
|
|
|
@ -11,7 +11,9 @@
|
||||||
|
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
#include <QMutex>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QQueue>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include <libcamera/buffer.h>
|
#include <libcamera/buffer.h>
|
||||||
|
@ -40,6 +42,8 @@ public:
|
||||||
MainWindow(CameraManager *cm, const OptionsParser::Options &options);
|
MainWindow(CameraManager *cm, const OptionsParser::Options &options);
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
|
|
||||||
|
bool event(QEvent *e) override;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void quit();
|
void quit();
|
||||||
void updateTitle();
|
void updateTitle();
|
||||||
|
@ -57,6 +61,7 @@ private:
|
||||||
int openCamera();
|
int openCamera();
|
||||||
|
|
||||||
void requestComplete(Request *request);
|
void requestComplete(Request *request);
|
||||||
|
void processCapture();
|
||||||
int display(FrameBuffer *buffer);
|
int display(FrameBuffer *buffer);
|
||||||
void queueRequest(FrameBuffer *buffer);
|
void queueRequest(FrameBuffer *buffer);
|
||||||
|
|
||||||
|
@ -78,6 +83,9 @@ private:
|
||||||
uint32_t previousFrames_;
|
uint32_t previousFrames_;
|
||||||
uint32_t framesCaptured_;
|
uint32_t framesCaptured_;
|
||||||
|
|
||||||
|
QMutex mutex_;
|
||||||
|
QQueue<FrameBuffer *> doneQueue_;
|
||||||
|
|
||||||
QToolBar *toolbar_;
|
QToolBar *toolbar_;
|
||||||
ViewFinder *viewfinder_;
|
ViewFinder *viewfinder_;
|
||||||
std::map<int, std::pair<void *, unsigned int>> mappedBuffers_;
|
std::map<int, std::pair<void *, unsigned int>> mappedBuffers_;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue