Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Camera class in QThread



  • Hi,

    I woluld like to implement the Camera class in a separate thread to be able to independently retrieve data from a device and process it in the run() method. Unfortunately, when calling the run() method, the code gets stuck in a loop and won't come out. As a result, I cannot stop the camera with the stop() method. How could I fix that?

    camera.h:

    class Camera : public QThread
    {
        Q_OBJECT
    public:
        Camera();
        ~Camera() {}
    
        void run();
        void stop() { camera_running = false; }
    
    private:
        rs2::config cfg;
        rs2::pipeline pipe;
        rs2::frameset frames;
        bool camera_running;
    
    signals:
        void FrameReady(rs2::depth_frame frame);
    };
    

    camera.cpp:

    Camera::Camera()
    {
        camera_running = true;
      
        cfg.enable_stream(RS2_STREAM_DEPTH,
                          CAMERA::RESOLUTION::DEPTH_WIDTH,
                          CAMERA::RESOLUTION::DEPTH_HIGHT,
                          RS2_FORMAT_Z16,
                          CAMERA::FPS);
    
        pipe.start(cfg);
    }
    void Camera::run()
    {
        while(!this->isInterruptionRequested())
        {
            try{
                frames = pipe.wait_for_frames();
                rs2::depth_frame depth = frames.get_depth_frame();
               emit FrameReady(depth);
            }
            catch(const rs2::error& e)
            {
                std::cout << "ERROR: " << e.get_failed_function() << "(" <<e.get_failed_args() <<")    "<<e.what()<<std::endl;
            }
        }
    }
    

    main.cpp:

    QThread cameraThread;
        Camera *camera = new Camera();
        QObject::connect(camera, &Camera::FrameReady, mqttClient, &MqttClient::sendFrame);
        camera->moveToThread(&cameraThread);
        camera->run();
        qDebug()<<"Started";  //Will not be done
        camera->stop(); //Will not be done
        qDebug()<<"Stopped"; //Will not be done
    


  • I think the problem is that you call run directly from your GUI thread - this is a simple (blocking) call, not the start of a new thread. You should call start() on your camera object, I guess.
    Edit: Your have two QThread objects - cameraThread and camera (which is derived from QThread) why? You mix the two options to use QThread (moving a worker object to QThread or reimplementing QThread::run(). )



  • @stryga42 If I change the inheritance from QThread to QObject, nothing will change


  • Lifetime Qt Champion

    @Creatorczyk Since you don't start the thread anywhere nothing happens.



  • @Christian-Ehrlicher I change code in main.cpp to:

    QThread cameraThread;
        Camera *camera = new Camera();
        QObject::connect(camera, &Camera::FrameReady, mqttClient, &MqttClient::sendFrame);
        camera->moveToThread(&cameraThread);
        cameraThread.start();
        camera->run();
        qDebug()<<"Started";   //Will not be done
        camera->stop();   //Will not be done
        qDebug()<<"Stopped";   //Will not be done
    

    Unfortunately nothing happened. Futher code does not execute


  • Lifetime Qt Champion

    @Creatorczyk Again: you don't start your thread anywhere, you just call a function named run() in your Camera object - nothing more.



  • @Christian-Ehrlicher calling "cameraThread.start();" will not start thread?


  • Lifetime Qt Champion

    @Creatorczyk It will, but then you call a blocking function in your main thread.



  • @Creatorczyk

    cameraThread.start();
    

    is the right thing to do. Yes, this starts a new thread "within" the object cameraThread. This call to start() does not block. Check it it out by inserting a qDebug() output right after the call.
    But then you call (unnecessarily) Camera::run(), which will block. Use signals to "trigger" your camera object. Again, I think you mix up the two ways to use QThread: Usually you EITHER use the "moveToTrhread-style" OR the "reimplement QThread::run-style", but not both at the same time. If you want your code in Camera::run() to be executed without signaling, you have to call start() on your (then QThread derived) Camera object. Som thing like

    camera->start();
    

    should do the job. cameraThread is then not required at all.


  • Lifetime Qt Champion

    @Creatorczyk said in Camera class in QThread:

    calling "cameraThread.start();" will not start thread?

    Did you read https://doc.qt.io/qt-5/qthread.html#start ?
    start() calls run() - you do not have to call run() by yourself and you should NOT!



  • @stryga42 @Christian-Ehrlicher @jsulm Thanks, I fixed it!


Log in to reply