(u->refcount == 0) in deallocate
Hi,
I am having an issue that only occurs on Linux (arm) on my Raspberry Pi 3b. It works fine on windows.
I am trying to read a video file using this loop:
while (videoCapture.isOpened()) {
DebugWrite("Start Grabbing Frame from VIDEO stream.", "ImageGrabber::RunGrabber");
_shouldStop.mx.lock();
if (_shouldStop.stop) {
break;
}
_shouldStop.mx.unlock();
DebugWrite("Initiating MAT", "ImageGrabber::RunGrabber");
cv::Mat frame;
DebugWrite("Finished Initiating MAT, reading frame!", "ImageGrabber::RunGrabber");
if (videoCapture.read(frame)) {
DebugWrite("Frame written.", "ImageGrabber::RunGrabber");
if (cv::waitKey(30) >= 0 || frame.empty()) break;
DebugWrite("Copying frame to UMAT.", "ImageGrabber::RunGrabber");
_frameBuffer.mx.lock();
frame.copyTo(*_frameBuffer.writeFrame);
_frameBuffer.notempty = true;
DebugWrite("Frame copied to UMAT.", "ImageGrabber::RunGrabber");
_frameBuffer.mx.unlock();
DebugWrite("Videocapture (" + _imageSource.source + ").", "ImageGrabber::RunGrabber", frame);
}
else {
DebugWrite("Could not read video.", "ImageGrabber::RunGrabber");
break;
}
}
It read the first frame fine. But when I want to read the second frame from the video file it throws this error:
SmartPause::DetectionThread | Not Stopping Detection Thread
SmartPause::DetectionThread | Retreiving Frame
SmartPause::DetectionThread | Not Stopping Detection Thread
ImageGrabber::RunGrabber | Copying frame to UMAT.SmartPause::DetectionThread | Retreiving Frame
SmartPause::DetectionThread | Not Stopping Detection Thread
SmartPause::DetectionThread | Retreiving Frame
[ INFO:0] Initialize OpenCL runtime...
ImageGrabber::RunGrabber | Frame copied to UMAT.
ImageGrabber::RunGrabber | Videocapture (/home/pi/test.mp4).
SmartPause::DetectionThread | Reading frame from buf0
SmartPause::DetectionThread | Image To Process
ImagePreProcessor::PerformPreProcessing | Start Image PreProcessing
ImageGrabber::RunGrabber | Start Grabbing Frame from VIDEO stream.
ImageGrabber::RunGrabber | Initiating MAT
ImageGrabber::RunGrabber | Finished Initiating MAT, reading frame!
OpenCV(4.0.0-dev) Error: Assertion failed (u->refcount == 0) in deallocate, file /home/pi/opencv/modules/core/src/matrix.cpp, line 169
terminate called after throwing an instance of 'cv::Exception'
what(): OpenCV(4.0.0-dev) /home/pi/opencv/modules/core/src/matrix.cpp:169: error: (-215:Assertion failed) u->refcount == 0 in function 'deallocate'
Aborted
As can be seen from the debug messages, the error happens on the line:
if (videoCapture.read(frame))
Since it happens here, it feels like something that is out of my control.
This code runs fine on my windows machine. Another peculiar thing is the fact that it tries to open the "OpenCL runtime"? As far as I know, opencl is not supported on the raspberry pi. As can be seen, this runs in a seperate thread and the frame is accessed in another thread, but protected by mutexes. In the other thread a pointer swap is done to prevent the necessity to copy the frame.
I have no clue if I am doing something wrong or that something underwater (with opencv) is going wrong. If someone knows of a similar issue or can give me pointers (no pun intended ;) ) to a solution, I would be very glad.
Thanks in advance!
be so nice, and replace the screenshot of your errors with a text version, thank you !
uhmm, what is _framebuffer, and why do you neeed to lock it ?
can it be you're using multiple threads here (without telling us about it) ?
@berak Ok, no problem. Also something funky is going on, when running in gdb it shows that it's grabbing atleast a few more frames until it's aborted.
I mentioned that it's running accross multiple threads (so you probably didn't read the full post but thats fine). _framebuffer is a struct as follows:
yea, obviously missed that part, but there exactly might be your problem ;)
also this is terrible:
DON'T EVER use pointers to cv::Mat or UMAt, since you defeat the internal refcounting with aliased ponters
Oh that sucks. I didn't know that. So it isn't possible to do manual pointer swapping to improve performance? (I need it to be multithreaded tho). I didn't feel like copying the data to a new instance of UMat to squeeze out that little bit of extra performance. Then again, why is this working without issues on windows?
no, swap the actual mat using cv::swap(), NOT pointers to it
again, Mat's (and UMat's too) are refcounted objects. you only copy the Mat header( ~60bytes, not the pixel data). no reason to be afraid of it.
lookup "undefined behaviour" (that's what you made here.) it may or may not work, or even run for weeks w/o problems in a different env, and then crash in an entirely different part of your program.
again, to boil it down -- using pointers to UMat defeats the internal refcounting, do you understand that part ?
Sorry for the late reply. Yes, the UMat uses an internal reference counter much like shared_ptr to keep track if it's still in scope or not and by using pointers (cross scopes) it messes up this internal reference counter. Thats the gist of it right?
@berak, Sorry for bothering you with this again, I changed the pointer swapping to cv::swap. Now I write only to frameBuf0 in the videocapture thread. In the other thread, once a second, i lock the mutex, swap the buffers between frameBuf0 and 1 using cv::swap and then release the lock. After that, in the same thread I perform some processing on frameBuf1. But... no dice. Still the same assert failure occurs. Could this be because I am copying the local Mat to the UMat (using copyTo)(frameBuf0) that resides within ConcurrentFrameBuffer struct? (Also the fact is that the assertion failure happens on videoCapture.read() instead of the point where I read the swapped UMat is odd).