Thanks @karlphillip for pointing me in the right direction. cvCaptureFromCAM calls are cvCaptureFromCAM in a separate thread. When the camera turns off, the return value is NULL .
However, this feature does not seem to be thread safe. But a simple mutex to block concurrent calls to cvCaptureFromCAM seems to do the trick. I used boost::thread for this example, but you could easily configure it.
On a global scale:
// Create a mutex used to prevent simultaneous calls to cvCaptureFromCAM boost::shared_mutex mtxCapture; // Flag to notify when we're done. // NOTE: not bothering w/mutex for this example for simplicity sake bool done = false;
The entry point looks something like this:
int main() { // Create the work and the capture monitoring threads boost::thread workThread(&Work); boost::thread camMonitorThread(&CamMonitor); while (! done) { // Do whatever } // Wait for threads to close themselves workThread.join(); camMonitorThread.join(); return 0; }
Workflow is simple. The only caveat is that you need to block mutexes so that you do not receive concurrent calls to cvCaptureFromCAM .
// Work Thread void Work() { Capture * capture = NULL; mtxCapture.lock(); // Lock calls to cvCaptureFromCAM capture = cvCaptureFromCAM(-1); // Get the capture object mtxCapture.unlock(); // Release lock on calls to cvCaptureFromCAM //TODO: check capture != NULL... while (! done) { // Do work } // Release capture cvReleaseCapture(&capture); }
And finally, the capture monitoring flow suggested by @karlphillip, with the exception of a blocked call to cvCaptureFromCAM . In my tests, calls to cvReleaseCapture were pretty slow. I put the cvWaitKey call at the end of the loop because I don't want to eavesdrop on the constant check.
void CamMonitor() { while (! done) { CvCapture * capture = NULL; mtxCapture.lock(); // Lock calls to cvCaptureFromCAM capture = cvCaptureFromCAM(-1); // Get the capture object mtxCapture.unlock(); // Release lock on calls to cvCaptureFromCAM if (capture == NULL) done = true; // NOTE: not a thread-safe write... else cvReleaseCapture(&capture); // Wait a while, we don't need to be constantly checking. cvWaitKey(2500); }
I will probably end up implementing a ready state flag that can detect if the camera is connected again. But this is beyond the scope of this example. Hope someone finds this helpful. Thanks again @karlphillip.
Courtney christensen
source share