Domanda

Quindi, sto lavorando su un programma che i processi di video in tempo reale e sto avendo qualche problema con le discussioni "blocco" a vicenda.

Il mio sistema è più o meno impostato in questo modo:

         DataSourceThread
             /      \
            /        \
           /          \
     Receiver       Receiver
         /              \
        /                \ 
       /                  \
 Processor1            Processor2

(Tutte queste classi stanno estendendo QThread.)

Quindi DataSourceThread recupera fotogrammi da un videostream ed emette un segnale contenente il telaio ai ricevitori. Tipo di collegamento: Qt :: DirectConnection

I ricevitori fondamentalmente ricevere i frame inviati dal DataSourceThread e se il processore è fatto di gestire il frame precedente, emetterà un segnale contenente il telaio al processore. Tipo di collegamento:. Qt :: QueuedConnection Se il processore non viene effettuata l'elaborazione del frame precedente, sarà solo restituire senza emettere un segnale (salta immagini).

Per verificare se questo funziona, tutto è che ho fatto avere Processor1 basta stampare un messaggio quando riceve un frame e Processor2 QThread :: sonno (3); e stampare un messaggio .

(I ricevitori anche fare una copia completa del telaio prima di trasmetterla ai trasformatori.)

Risultato atteso:

Processor1 dovrebbe essere costantemente stampa dei messaggi. Processor2 dovrebbe essere stampa di un messaggio ogni 3 secondi.

Il problema:

Entrambi i processori di stampa i loro messaggi allo stesso tempo (ogni 3 secondi). Processor1 attese fino Processor2 è fatto prima di stampare il suo messaggio. Quindi l'uscita è più o meno in questo modo:

"Message from processor1"
"Message from processor2"
"Message from processor1"
"Message from processor2"
"Message from processor1"
"Message from processor2"

e così via.

Sono a corto di idee qui, modo che qualsiasi aiuto sarebbe molto apprezzato!

Modifica Ecco parte del codice:

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();
}  

Da 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 {
        // SKIPPED THIS FRAME
    }
}

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

// (The processors extend this class)
void FrameProcessor::receive(Frame *frame)
 {
     setFrame(frame);
     delete frame;
     emit ready();
 }

DetectorThread (Processor2) fa la stessa guithread, ma con un sonno 3 sec in SETFRAME.

È stato utile?

Soluzione

Credo che parte del problema è che tutti i vostri QObject sono di proprietà del thread dell'applicazione principale. Questo significa che tutti condividono un ciclo un evento per la consegna di segnali asincroni, la serializzazione in modo efficace la catena di elaborazione complesso.

Penso che il modo corretto di impostare questo sarebbe qualcosa di simile:

GUIProcessor *guiProcessor = new GUIProcessor();
QThread guiProcessorThread;
guiProcessor.moveToThread(&guiProcessorThread);

FrameReceiver *guiReceiver = new FrameReceiver(guiProcessor, 0);
QThread guiReceiverThread;
guiReceiver.moveToThread(&guiReceiverThread);

guiProcessorThread.start();
guiReceiverThread.start();

Se si fa in questo modo vorrei suggerire di non utilizzare DirectConnection tra i thread, ma piuttosto BlockingQueuedConnection se si vuole garantire che il frame corrente viene elaborato prima di acquisire la successiva.

Vedere questo: http: // laboratori. qt.nokia.com/2010/06/17/youre-doing-it-wrong/

E questo: http: // laboratori. qt.nokia.com/2006/12/04/threading-without-the-headache/

Spero che questo aiuti!

EDIT:. Per essere chiari, con il mio suggerimento vostre classi avrebbero ereditato QObject invece di QThread

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top