So, Iām working on a program that processes video in real time, and I am having problems with the threads blocking each other.
My system is pretty much configured as follows:
DataSourceThread / \ / \ / \ Receiver Receiver / \ / \ / \ Processor1 Processor2
(All of these classes extend QThread.)
So, DataSourceThread extracts frames from the video stream and emits a signal containing the frame to the receivers. Connection Type: Qt :: DirectConnection
The receivers basically receive the frames sent by the DataSourceThread, and if the processor processes the previous frame, it will emit a signal containing the frame to the Processor. Connection Type: Qt :: QueuedConnection. If the processor has not finished processing the previous frame, it will simply return without radiation (frame skipping).
To check if this works, all I did was make Processor1 just print the message when it receives the frame, and Processor2 QThread :: sleep (3); and print the message.
(Receivers will also make a deep copy of the frame before transmitting it to the processors.)
Expected Result:
Processor1 must constantly print messages. Processor2 should print a message every 3 seconds.
Problem:
Both processors print their messages at the same time (every 3 seconds). Processor1 waits for Processor2 to execute before printing its message. So the result looks something like this:
"Message from processor1" "Message from processor2" "Message from processor1" "Message from processor2" "Message from processor1" "Message from processor2"
etc.
I'm running out of ideas here, so any help would be greatly appreciated!
EDIT: Here are some of the code:
main.cpp:
int main(int argc, char *argv[]) { QApplication app(argc, argv); DataSourceThread dataSourceThread; dataSourceThread.start(); GUIThread *guiProcessor = new GUIThread(); FrameReceiver *guiReceiver = new FrameReceiver(guiProcessor, 0); QObject::connect( &dataSourceThread, SIGNAL(frameReceived(Frame*)), guiReceiver, SLOT(receive(Frame*)), Qt::DirectConnection ); DetectorThread *detectorProcessor = new DetectorThread(); FrameReceiver *detectorReceiver = new FrameReceiver(detectorProcessor, 0); QObject::connect( &dataSourceThread, SIGNAL(frameReceived(Frame*)), detectorReceiver, SLOT(receive(Frame*)), Qt::DirectConnection ); return app.exec(); }
From DataSourceThread.cpp:
void DataSourceThread::run() { ... stuff ... while (true) { image = cvQueryFrame(capture); if (!image) { qDebug() << QString("Could not capture frame"); continue; } cvReleaseImage(&temp_image); temp_image = cvCreateImage(cvSize(640, 480), image->depth, 3); cvResize(image, temp_image, 1); frame->lock(); frame->setImage(temp_image); frame->unlock(); emit frameReceived(frame); msleep(1); } }
FrameReceiver.cpp:
FrameReceiver::FrameReceiver(FrameProcessor* processor, QObject *parent) : QThread(parent) { m_ready = true; m_processor = processor; m_processor->start(); QObject::connect( (QObject*)this, SIGNAL(frameReceived(Frame*)), m_processor, SLOT(receive(Frame*)), Qt::QueuedConnection ); QObject::connect( m_processor, SIGNAL(ready()), (QObject*)this, SLOT(processCompleted()), Qt::DirectConnection ); } void FrameReceiver::processCompleted() { m_ready = true; } void FrameReceiver::receive(Frame *frame) { if (m_ready == true) { m_ready = false; frame->lock(); Frame *f = new Frame(*frame); frame->unlock(); emit frameReceived(f); } else {
GUIThread.cpp: (Processor1)
GUIThread::GUIThread(QObject *parent) : FrameProcessor(parent) { m_frame = new Frame(); } void GUIThread::setFrame(Frame *frame) { qDebug() << QString("Guithread received frame"); }
Frameprocessor.cpp
DetectorThread (Processor2) does the same as guithread, but with a 3 second sleep in setFrame.