Pregunta

Así que estoy trabajando en un programa que los procesos de vídeo en tiempo real y estoy teniendo algunos problemas con hilos de "bloqueo" entre sí.

Mi sistema es más o menos configurado de esta manera:

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

(Todas estas clases están extendiendo QThread.)

Así DataSourceThread obtiene fotogramas de un videostream y emite una señal que contiene el marco de los receptores. Tipo de conexión: Qt :: DirectConnection

Los receptores básicamente recibir los marcos de los enviados por DataSourceThread y si el procesador se realiza el procesamiento de la imagen anterior, emitirá una señal que contiene el marco para el procesador. Tipo de conexión:. Qt :: QueuedConnection Si el procesador no se lleva a cabo el procesamiento de la imagen anterior, se acaba de regresar sin emitir una señal (saltos de imagen).

Para probar si esto funciona, es decir todos los que he hecho tienen processor1 acaba de imprimir un mensaje cuando se recibe una trama y Processor2 hace QThread :: sueño (3); e imprimir un mensaje .

(Los receptores también hacer una copia profunda de la trama antes de pasarlo a los procesadores.)

Resultado esperado:

processor1 debe estar constantemente imprimir mensajes. Processor2 debe imprimiendo un mensaje cada 3 segundos.

El problema:

Ambos procesadores imprimir sus mensajes al mismo tiempo (cada 3 segundos). processor1 espera hasta Processor2 se realiza antes de imprimir su mensaje. Por lo que la salida es más o menos así:

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

y así sucesivamente.

Me estoy quedando sin ideas aquí, por lo que cualquier ayuda sería muy apreciada!

EDIT: He aquí una parte del código:

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

Desde 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) hace lo mismo que guithread, pero con un sueño 3 seg en setFrame.

¿Fue útil?

Solución

Creo que parte del problema es que todas sus QObjects son propiedad de la rosca principal de la aplicación. Este todos comparten un bucle de un evento para la entrega de señales asíncronas, serializar eficazmente su cadena de procesamiento de todo medio.

Creo que la forma correcta de instalar esto sería algo como:

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

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

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

Si lo haces de esta manera que sugeriría no usar DirectConnection entre hilos, sino más bien BlockingQueuedConnection si usted quiere asegurarse de que el cuadro actual se procesa antes de capturar el siguiente.

Vea esto: http: // laboratorios. qt.nokia.com/2010/06/17/youre-doing-it-wrong/

Y esto: http: // laboratorios. qt.nokia.com/2006/12/04/threading-without-the-headache/

Espero que esto ayude!

EDIT:. Para que quede claro, con mi sugerencia de sus clases heredarían QObject en lugar de QThread

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top