QThread cannot be stop after QCamera->start()
-
hey guys.
6.9.3+vs2022.
I wanna capture a usb cam video. it works find but the thread for capturing cannot be stop.
when I exit the app, thread.wait() cannot return after runing run() function ,even i already run stop().
If I donot do anything , wait() works fine and can return.
why wait() cannot return?mainwindow.cpp, two button, one for start , another for stop:
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QCamera> #include <QDebug> #include <QCameraDevice> #include <QMediaDevices> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); connect(this,&MainWindow::sigStart,&m_cam,&CamOperator::run); connect(this,&MainWindow::sigStop,&m_cam,&CamOperator::stop); // qDebug() <<"ui:"<<QThread::currentThread(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_clicked() { emit sigStart(); } void MainWindow::on_pushButton_2_clicked() { emit sigStop(); }
wrapper for qcamera:
#include "camoperator.h" #include <QDebug> #include <QImage> #include <QDateTime> #include <QTimer> #define T_DBG qDebug() #define T_ERR qDebug() CamOperator::CamOperator(QObject *parent) : QObject{parent} { moveToThread(&m_bgThread); m_bgThread.start(); } CamOperator::~CamOperator() { stop(); if(m_bgThread.isRunning()){ T_DBG<<"stop cam..."; m_bgThread.requestInterruption(); m_bgThread.quit(); if(1){ T_DBG<<"wait thread end..."; // 3000 right here, after run(), it cannot return anymore. m_bgThread.wait(); } T_DBG<<"thred end"; } } void CamOperator::run() { auto cam = QMediaDevices::defaultVideoInput(); T_DBG <<QThread::currentThread(); if(cam.isNull()){ T_ERR <<"no usb cam"; goto fail; } m_camera = new QCamera(cam); m_captureSession.setCamera(m_camera); m_imageCapture = new QImageCapture; m_captureSession.setImageCapture(m_imageCapture); connect(m_imageCapture,&QImageCapture::imageCaptured,this,[=](int id,const QImage &i){ emit sigImageReady(i); }); connect(m_imageCapture,&QImageCapture::readyForCaptureChanged,this,[=](bool ready){ if(ready){ m_imageCapture->capture(); //qDebug()<<"ready"; } }); emit sigErrorReport("openCamOk"); T_DBG <<"start capture"; m_camera->start(); goto end; fail: emit sigErrorReport("openCamFail"); end: T_DBG <<"start cap end"; } void CamOperator::stop() { if(m_camera){ m_camera->stop(); disconnect(m_imageCapture); delete m_imageCapture; delete m_camera; m_camera = nullptr; } emit sigErrorReport("camClosed"); T_DBG <<"stop end"; }
#ifndef CAMOPERATOR_H #define CAMOPERATOR_H #include <QThread> #include <QCamera> #include <QImageCapture> #include <QCameraDevice> #include <QMediaDevices> #include <QMediaCaptureSession> class ICameraWrapper; class CamOperator : public QObject { Q_OBJECT public: explicit CamOperator(QObject *parent = nullptr); ~CamOperator(); signals: void sigErrorReport(const QString &); void sigImageReady(const QImage &); public slots: void run(); void stop(); private: QString m_camType; QCamera *m_camera{}; QImageCapture *m_imageCapture; QMediaCaptureSession m_captureSession; QThread m_bgThread; }; #endif // CAMOPERATOR_H
-
hey guys.
6.9.3+vs2022.
I wanna capture a usb cam video. it works find but the thread for capturing cannot be stop.
when I exit the app, thread.wait() cannot return after runing run() function ,even i already run stop().
If I donot do anything , wait() works fine and can return.
why wait() cannot return?mainwindow.cpp, two button, one for start , another for stop:
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QCamera> #include <QDebug> #include <QCameraDevice> #include <QMediaDevices> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); connect(this,&MainWindow::sigStart,&m_cam,&CamOperator::run); connect(this,&MainWindow::sigStop,&m_cam,&CamOperator::stop); // qDebug() <<"ui:"<<QThread::currentThread(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_clicked() { emit sigStart(); } void MainWindow::on_pushButton_2_clicked() { emit sigStop(); }
wrapper for qcamera:
#include "camoperator.h" #include <QDebug> #include <QImage> #include <QDateTime> #include <QTimer> #define T_DBG qDebug() #define T_ERR qDebug() CamOperator::CamOperator(QObject *parent) : QObject{parent} { moveToThread(&m_bgThread); m_bgThread.start(); } CamOperator::~CamOperator() { stop(); if(m_bgThread.isRunning()){ T_DBG<<"stop cam..."; m_bgThread.requestInterruption(); m_bgThread.quit(); if(1){ T_DBG<<"wait thread end..."; // 3000 right here, after run(), it cannot return anymore. m_bgThread.wait(); } T_DBG<<"thred end"; } } void CamOperator::run() { auto cam = QMediaDevices::defaultVideoInput(); T_DBG <<QThread::currentThread(); if(cam.isNull()){ T_ERR <<"no usb cam"; goto fail; } m_camera = new QCamera(cam); m_captureSession.setCamera(m_camera); m_imageCapture = new QImageCapture; m_captureSession.setImageCapture(m_imageCapture); connect(m_imageCapture,&QImageCapture::imageCaptured,this,[=](int id,const QImage &i){ emit sigImageReady(i); }); connect(m_imageCapture,&QImageCapture::readyForCaptureChanged,this,[=](bool ready){ if(ready){ m_imageCapture->capture(); //qDebug()<<"ready"; } }); emit sigErrorReport("openCamOk"); T_DBG <<"start capture"; m_camera->start(); goto end; fail: emit sigErrorReport("openCamFail"); end: T_DBG <<"start cap end"; } void CamOperator::stop() { if(m_camera){ m_camera->stop(); disconnect(m_imageCapture); delete m_imageCapture; delete m_camera; m_camera = nullptr; } emit sigErrorReport("camClosed"); T_DBG <<"stop end"; }
#ifndef CAMOPERATOR_H #define CAMOPERATOR_H #include <QThread> #include <QCamera> #include <QImageCapture> #include <QCameraDevice> #include <QMediaDevices> #include <QMediaCaptureSession> class ICameraWrapper; class CamOperator : public QObject { Q_OBJECT public: explicit CamOperator(QObject *parent = nullptr); ~CamOperator(); signals: void sigErrorReport(const QString &); void sigImageReady(const QImage &); public slots: void run(); void stop(); private: QString m_camType; QCamera *m_camera{}; QImageCapture *m_imageCapture; QMediaCaptureSession m_captureSession; QThread m_bgThread; }; #endif // CAMOPERATOR_H
@QtTester said in QThread cannot be stop after QCamera->start():
m_captureSession
This lives in the wrong thread since you don't pass a parent.
Why a thread at all? Please follow the official examples when you really want a thread here. -
@QtTester said in QThread cannot be stop after QCamera->start():
m_captureSession
This lives in the wrong thread since you don't pass a parent.
Why a thread at all? Please follow the official examples when you really want a thread here.@Christian-Ehrlicher
thanks for replying.
I have not found any thread programing for QCamera/QMediaCaptureSession,
the example in Examples\Qt-6.9.3\multimedia\camera\ use UI thread ?
can you suggest some web-link? -
@Christian-Ehrlicher
thanks for replying.
I have not found any thread programing for QCamera/QMediaCaptureSession,
the example in Examples\Qt-6.9.3\multimedia\camera\ use UI thread ?
can you suggest some web-link?@QtTester said in QThread cannot be stop after QCamera->start():
I have not found any thread programing for QCamera/QMediaCaptureSession,
It's not dedicated to
QCamera
only. I think @Christian-Ehrlicher was referring to the general Qt Multithreading examples and documentation -
@Christian-Ehrlicher
thanks for replying.
I have not found any thread programing for QCamera/QMediaCaptureSession,
the example in Examples\Qt-6.9.3\multimedia\camera\ use UI thread ?
can you suggest some web-link? -
@QtTester said in QThread cannot be stop after QCamera->start():
@jsulm for not stucking the UI? I donot know whether it is appropriate to use a thread.
Please run and study the official Camera Example: https://doc.qt.io/qt-6/qtmultimedia-camera-example.html
It shows that you don't need threads -- QCamera/QMediaCaptureSession does not block the UI.
-
@QtTester said in QThread cannot be stop after QCamera->start():
@jsulm for not stucking the UI? I donot know whether it is appropriate to use a thread.
Please run and study the official Camera Example: https://doc.qt.io/qt-6/qtmultimedia-camera-example.html
It shows that you don't need threads -- QCamera/QMediaCaptureSession does not block the UI.
-
@JKSH I read the code.
but what I am curious is : why qthread.wait() not return after qcamera.start() ?@QtTester said in QThread cannot be stop after QCamera->start():
why qthread.wait() not return after qcamera.start()
I already told you what you might did wrong
m_captureSession
This lives in the wrong thread since you don't pass a parent.
-
@QtTester said in QThread cannot be stop after QCamera->start():
why qthread.wait() not return after qcamera.start()
I already told you what you might did wrong
m_captureSession
This lives in the wrong thread since you don't pass a parent.
@Christian-Ehrlicher
if i donot new the class, wait() works fine, event i call qcamera.start():void CamOperator::run() { auto cam = QMediaDevices::defaultVideoInput(); T_DBG <<QThread::currentThread(); if(cam.isNull()){ T_ERR <<"no usb cam"; goto fail; } m_camera.setCameraDevice(cam); m_captureSession.setCamera(&m_camera); m_captureSession.setImageCapture(&m_imageCapture); m_captureSession.setVideoSink(&m_vs); connect(&m_imageCapture,&QImageCapture::imageCaptured,this,[=](int id,const QImage &i){ emit sigImageReady(i); }); connect(&m_vs, &QVideoSink::videoFrameChanged, [&]( const QVideoFrame &frame ) { m_imageCapture.capture(); }); emit sigErrorReport("openCamOk"); T_DBG <<"start capture"; m_camera.start(); goto end; fail: emit sigErrorReport("openCamFail"); end: T_DBG <<"start cap end"; }
but if i new the class and pass parent,wait() won't return anymore, why the parent will stuck it?:
void CamOperator::run() { auto cam = QMediaDevices::defaultVideoInput(); T_DBG <<QThread::currentThread(); if(cam.isNull()){ T_ERR <<"no usb cam"; goto fail; } m_camera = new QCamera(cam,this); m_camera->setCameraDevice(cam); m_captureSession = new QMediaCaptureSession(this); m_captureSession->setCamera(m_camera); m_imageCapture = new QImageCapture(this); m_captureSession->setImageCapture(m_imageCapture); m_captureSession->setVideoSink(&m_vs); connect(m_imageCapture,&QImageCapture::imageCaptured,this,[=](int id,const QImage &i){ emit sigImageReady(i); //qDebug()<<"cap:"<<QThread::currentThread(); }); connect(&m_vs, &QVideoSink::videoFrameChanged, [&]( const QVideoFrame &frame ) { m_imageCapture->capture(); }); emit sigErrorReport("openCamOk"); T_DBG <<"start capture"; m_camera->start(); goto end; fail: emit sigErrorReport("openCamFail"); end: T_DBG <<"start cap end"; }