PDA

View Full Version : this pointer



freekill
27th January 2010, 02:59
I'm running in an application crash. gdb's complaining about segmentation fault in QObject::thread (this=(incomplete type)). Here's the code where I suspect the problem is coming from:



#include <QtDebug>
#include <QtGUI>
#include <QPainter>
#include <QThread>
#include "webcam.h"
#include "capturingthread.h"
#include "imagebuffer.h"
#include "renderingthread.h"

WebcamWidget::WebcamWidget(QWidget *parent) : QWidget(parent)
{
setupUi(this);

pWaitCondition = &waitCondition;
imageBuffer = new ImageBuffer(pWaitCondition);
capturingThread = new CapturingThread(imageBuffer);
renderingThread = new RenderingThread(imageBuffer,pWaitCondition);

qRegisterMetaType<QImage>("QImage&");
connect(renderingThread, SIGNAL(renderingDone(QImage& )), this, SLOT(updatePixmap(QImage& )));
connect(startButton, SIGNAL(clicked()), this, SLOT(startThreads()));
}

WebcamWidget::~WebcamWidget()
{
delete imageBuffer;
delete capturingThread;
delete renderingThread;
}

void WebcamWidget::startThreads()
{
if (capturingThread->isRunning())//&&renderingThread->isRunning())
{
capturingThread->haltCapture();
renderingThread->haltRendering();
startButton->setText("Start");
}
else
{
capturingThread->start();
renderingThread->start();
startButton->setText("Stop");
}
}

void WebcamWidget::haltThreads()
{
capturingThread->haltCapture();
renderingThread->haltRendering();
}

void WebcamWidget::paintEvent(QPaintEvent*)
{
QPainter painter(this);
painter.fillRect(rect(), Qt::black);
if (pixmap.isNull())
{
qDebug()<<"W: Pixmap data null.";
painter.setPen(Qt::black);
painter.drawText(rect(), Qt::AlignCenter, "No Image Feed");
return;
}
painter.drawPixmap(10,10,pixmap);
qDebug()<<"Painting successful.";
}

void WebcamWidget::updatePixmap(QImage& image)
{
qDebug()<<"WebcamWidget::updatePixmap() invoked.";
pixmap = QPixmap::fromImage(image);
update();
}


I only used this in this .cpp file and I don't see this anywhere in my spawned threads' codes. Did I not use it right? TIA.

high_flyer
27th January 2010, 08:28
gdb's complaining about segmentation fault in QObject::thread (this=(incomplete type))
gdb will also tell you on which line it seg faults, which can give a better clue to what is wrong.
It sounds more like a problem in one of your threads.

wysota
27th January 2010, 10:58
Sending a reference to an image across threads is what causes the problem. You have to send a const reference or a copy instead.

freekill
27th January 2010, 14:16
Sending a reference to an image across threads is what causes the problem. You have to send a const reference or a copy instead.
Whoa! This actually worked like magic!:) Just curious though, the program now runs however, when I use gdb I still get a segmentation fault.
0x7c96df51 in ntdll! RtlpNtMakeTemporaryKey ()
from C:\WINDOWS\system32\ntdll.dll

I googled for the error and it points out to be internal to Windows dlls. How could I have accessed such? And why still the error in gdb?

high_flyer
27th January 2010, 15:05
are you protecting your image with mutexes?

freekill
27th January 2010, 17:15
are you protecting your image with mutexes?

No. I'm actually capturing images real-time through a webcam. But I made it multithreaded. I have a dedicated thread querying the webcam for a new image (which should happen every 30ms for typical webcams). When querying is successful, I place the image in a buffer and I wake up the rendering thread. The rendering thread converts the OpenCV's IplImage format to Qt's QImage format then painting happens.

Based on the clockings I'm currently observing, the conversion process (IplImage to QImage) along with the painting, takes some time and I get to skip some images captured by the webcam. This is acceptable though, as long as the latest image in the buffer gets to be displayed on screen. My image buffer contains only the latest frame captured by the webcam instead of stacking up the images in a queue.

high_flyer
28th January 2010, 08:27
No

You really should!
Even if its not the only problem in your application, it is a major one!
You have to protect mutual exclusive data, otherwise you get situations in which two threads are accessing the same resource at the same time - and that is "not good"!

freekill
28th January 2010, 10:06
I see, thanks for the advice. But which data do you think I need to lock/unlock?
1. Write to image buffer? (Only a single thread is writing on to the buffer)
2. Read to the image buffer? (Might be, 2 threads are reading the same image in the buffer but I feel it's not an issue reading data at the same time)
3. Update of QPixmap data before painting? (I believe not the case, because even if I get to update it on and on, multiple calls to update() is fine.)

If in the case of 1 and 2, I ran into some trouble as I could not unlock the mutex after function return:


IplImage* ImageBuffer::getFrame()
{
QReadLocker readLocker(&rwLock);
return image; //rwLock fails to be unlocked on function return
}

boudie
28th January 2010, 18:06
Maybe you should use 2 image buffers:
- Renderer locks buffer #1 to read and render; you capture to buffer #2.
- As soon as the renderer is ready it unlocks buffer #1 and the capture goes to buffer #1 while releasing buffer #2 to be rendered.

So at the start of every capture you check which buffer is safe to use.
The renderer has to wait until the other buffer is released. Only in that case there is a new image availbale, because an image can never be written to the just rendered buffer.

Let us know if it actually works... ;)

high_flyer
29th January 2010, 08:24
But which data do you think I need to lock/unlock?
Any data which is accessed by more then one thread needs to be protected.

1. Write to image buffer? (Only a single thread is writing on to the buffer)
Yes, but if it is the SAME buffer that is being accessed by other threads, it has to be protected, even more so if you have references to this elements in other places (and you have).
Threaded programming can get very messy and very hard to debug if you don't understand the principals and traps associated with it.
You should really read some tutorials, and get to know threaded programming.
Its not trivial, and the way to think about it is different then non threaded programming.

freekill
30th January 2010, 01:17
Thanks high_flyer, I'll take those pointers.:)

@boudie
I'm very much open to your suggestion. Using two buffers could actually speed up data access as I could read and write simultaneously without worrying to much about having my buffer blocked. However, I'm also using the buffer for synchronization. My rendering thread goes to sleep whenever it is finished with its rendering. I wake up the thread when a new image has been placed in the buffer. I do this using a wait condition. I feel I could not implement my current idea of sleeping threads with this suggestion.