0

I have three periodic real-time tasks that execute simultaneously, each on a different processor(core) for video capturing using OpenCV.

In order to synchronize between the three tasks, I used an array of cv::Mat and each time I swap the index in order to avoid a data race. Thanks to the answers to my previous post on buffer reading/writing synchronization, I come up with this solution :

cv::Mat frame[3];
int frame_index_write = 0;
int frame_index_read = 1;
int frame_index_read_ = 2;

int SwapIndex(int *fi){
return *fi = (*fi + 1) % 3;
}

Now, the first task grabs a capture and stores it in a buffer and broadcast a signal to the other tasks, so they can get the captured frames :

 while (1)
{
    capture.grab();
    capture.retrieve(frame[frame_index_write], CHANNEL);
    SwapIndex(&frame_index_write);
    pthread_cond_broadcast(&synch_condition); /* After capturing the frame
                                                signal the displaying tasks*/
   }

The second task gets the captured frame and displays it:

 while (1)
{
    pthread_cond_wait(&synch_condition, &frame_rw); /*wait for the capturing
                                                      func to send a signal*/
    if (frame[frame_index_read].data)
    {
        cv::imshow(CAPTURED_IMAGE_WINDOW_NAME, frame[frame_index_read]);
        SwapIndex(&frame_index_read);
        cv::waitKey(1);
    }
    else{
        std::cout << "Frame reading error" << std::endl;
    }
    }

The third task gets the captured frame and applies an edge detection process before displaying it :

while (1)
{
    pthread_cond_wait(&synch_condition, &frame_rw); /*wait for the capturing
                                                      func to send a signal*/
    if (frame[frame_index_read_].data)
    {
        cv::cvtColor(frame[frame_index_read_], gray_capture, cv::COLOR_BGR2GRAY);
        cv::blur(gray_capture, detected_edges, cv::Size(3, 3));
        cv::Canny(detected_edges, detected_edges, 0, 100, 3);
        cv::imshow(EDGE_IMAGE_WINDOW_NAME, detected_edges);
        SwapIndex(&frame_index_read_);
        cv::waitKey(1);
    }
    else{
        std::cout << "Frame reading error" << std::endl;
    }
    }

My code seems to work perfectly and the results were also as expected but when I stop the execution on the terminal I got the following output indicating an error :

VIDIOC_DQBUF: Invalid argument

OpenCV Error: Bad argument (Unknown array type) in cvarrToMat, file /build/opencv-L2vuMj/opencv-3.2.0+dfsg/modules/core/src/matrix.cpp, line 943 terminate called after throwing an instance of 'cv::Exception' what(): /build/opencv-L2vuMj/opencv-3.2.0+dfsg/modules/core/src/matrix.cpp:943: error: (-5) Unknown array type in function cvarrToMat

Is there a way to handle this kind of error?

The complete code is hosted at Github

Any help would be so greatly appreciated on this topic.

asendjasni
  • 963
  • 1
  • 16
  • 36
  • 2
    You should stop the consumer threads as well when you "stop the execution on the terminal" – Botje Feb 19 '19 at 16:36
  • @Botje What do you mean by that? I thought by terminating the program, the created threads are automatically terminated. – asendjasni Feb 19 '19 at 18:18
  • Yes, they are terminated automatically. But before that happens, lots of objects get destructed. Can your worker threads survive the destruction of, say, `frame[0].data` while they are still using it? – Botje Feb 20 '19 at 09:24
  • @Botje I totally agree with what you are saying, that why if you noticed in the complete code, I added an else clause to each reading task that prints to the terminal the message **Frame reading error** if the `frame.data` is tested to empty. so why am I getting the error above instead of this message? – asendjasni Feb 20 '19 at 19:10
  • ... what if the shutdown starts in between the if test and the first access? This is a basic race condition and you should protect yourself against it. Either by delaying the shutdown unless both threads have finished, or killing them preemptively. – Botje Feb 21 '19 at 08:47
  • @Botje I think it a good idea. I'll try that and come back with an update. – asendjasni Feb 21 '19 at 09:09

0 Answers0