I’ve got a piece that uses five webcams, some of them HD. The display only shows one of their feeds at a time, but keeps them active continuously so it can switch between them.
I can usually get it to work for a few hours but eventually one or two cameras lock up. It’s never the same cam or the same USB port. I’m using PCIe USB cards in addition to the built-in ports to try and spread it all out, but it failes regardless. And I need it to run indefinitely.
So now I’m working on trying to detect when a camera is having problems so I can automatically reinitialize it. I’ll just have the app avoid that camera while it’s doing the reinit. Using isFrameNew(), I’ve found that I get more failed frames the higher my frame rate. However, those failed frames are intermixed with successfully grabbed frames. Therefore the trick is to look for a succession of failed frames in a row. Once they’re over some threshold I should be able to presume the camera has locked up. I also have to deal with the fact that isFrameNew() sometimes returns true on the first frame requested even though the cam isn’t up and running yet (a typical startup on my built-in iSight is to get one true from isFrameNew(), followed by about 50 false, then the camera seems live).
So below is a simple example that seems to be doing the job for one camera. However, since one camera never locks up I’ll have to expand it out for the five to really test it. I’m a bit worried about the overhead of all this if/else checking.
I’m including it here to see if anyone else has alternative ideas on how to deal with this issue? Any ideas? Any suggestions for improving my approach?
Thanks!
#include "testApp.h"
#define BAD_FRAME_THRESHOLD 5
//--------------------------------------------------------------
void testApp::setup(){
camWidth = CAPTURE_WIDTH; // try to grab at this size.
camHeight = CAPTURE_HEIGHT;
ofSetFrameRate(30);
ofSetVerticalSync(true);
failed = 0;
good = 0;
startupcount = 0;
starting = false;
vidGrabber.setVerbose(true);
bool done = vidGrabber.initGrabber(camWidth,camHeight);
if(done) {
printf("init done\n");
starting = true;
}
}
//--------------------------------------------------------------
void testApp::update(){
// ofBackground(100,100,100);
vidGrabber.grabFrame();
// got a new frame
if(vidGrabber.isFrameNew()) {
// for some reason isFrameNew returns true on the first frame sometimes
// even though it's not yet capturing. this bit allows me to track
// whether we're starting up and and to toss out a first frame glitch
// once we're beyond some threshold of failed frames (40) then we can presume
// the next good frame is a real one
if(starting && startupcount > 40) {
starting = false;
startupcount = 0;
printf("startup is finished\n");
}
// if this new frame immediately followed a failed frame then we want to
// start checking to see if the camera has locked up
if(failed) {
// if the number of failed frames is over a threshold, then we presume
// the camera really is locked up. close the connection and reinit.
if(failed > BAD_FRAME_THRESHOLD) {
printf("num failed frames before good: %d\n", failed);
// trigger close and reinit routines here
}
// reset our failed frame tracker
failed = 0;
}
// increment our good frame tracker
good ++;
}
// our request to get a new frame failed
else {
// if this failed request immediately followed a successful request
// then just reset our good frame counter because it's probably just
// a case of the camera not keeping up with update
if(good) {
good = 0;
}
// if we're not in a camera startup situation, then we need to increment
// our failed frame counter
if(!starting) {
failed ++;
}
// otherwise keep track of how many frames into the startup we are so we can
// easily get past that first frame glitch from isFrameNew
else {
startupcount++;
}
}
}
//--------------------------------------------------------------
void testApp::draw(){
vidGrabber.draw(0,0);
}