Hi all!
I got an app using OpenCV and OFX and it’s working great, except one of our needs is to have multiple windows correspond to a respective webcam. To achieve this, we were planning on running the app multiple times, with each instance configured to use a different webcam for ofVideoGrabber. However, when there is a USB webcam plugged into my Mac, the second instance of my ofx app throws an error:
log
2020-12-28 17:49:55.701 ofx[73218:4915323] OSXVideoGrabber Init Error: Error Domain=AVFoundationErrorDomain Code=-11815 "Cannot Use USB Color Camera" UserInfo={NSLocalizedRecoverySuggestion=Stop any other actions using the USB Color Camera and try again., AVErrorDeviceKey=<AVCaptureDALDevice: 0x7fa5fb62aa60 [USB Color Camera][0x142000000c456366]>, NSLocalizedDescription=Cannot Use USB Color Camera}
2020-12-28 17:49:55.756 ofx[73218:4915323] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** Can't add a nil AVCaptureInput'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff34926b57 __exceptionPreprocess + 250
1 libobjc.A.dylib 0x00007fff6d7a05bf objc_exception_throw + 48
2 AVFoundation 0x00007fff300f27d0 -[AVCaptureDALDevice supportsAVCaptureSessionPreset:] + 0
3 AVFoundation 0x00007fff300cc7a5 -[AVCaptureSession addInput:] + 71
4 ofx 0x000000010632107b -[OSXVideoGrabber initCapture:capWidth:capHeight:] + 3207
5 ofx 0x00000001063226d7 _ZN21ofAVFoundationGrabber5setupEii + 105
6 ofx 0x00000001063272ab _ZN14ofVideoGrabber5setupEiib + 243
7 ofx 0x000000010625214c _ZN5ofApp19cameraDeviceChangedERi + 300
8 ofx 0x000000010625185c _ZN5ofApp5setupEv + 254
9 ofx 0x0000000106253d03 _ZNSt3__110__function6__funcIZN7ofEventI16ofMouseEventArgsNS_15recursive_mutexEE13make_functionI10ofxBaseGuiEENS_10shared_ptrIN2of4priv8FunctionIS3_S4_EEEEPT_MSE_FvRS3_EiEUlPKvSG_E_NS_9allocatorISL_EEFbSK_SG_EEclEOSK_SG_ + 37
10 ofx 0x00000001063bfa5d _ZN7ofEventI11ofEventArgsNSt3__115recursive_mutexEE6notifyERS0_ + 149
11 ofx 0x0000000106352c24 _ZN10ofMainLoop3runENSt3__110shared_ptrI15ofAppBaseWindowEEONS1_I9ofBaseAppEE + 1678
12 ofx 0x0000000106352c6e _ZN10ofMainLoop3runEONSt3__110shared_ptrI9ofBaseAppEE + 58
13 ofx 0x000000010635b408 _Z8ofRunAppP9ofBaseApp + 81
14 ofx 0x0000000106254292 main + 180
15 libdyld.dylib 0x00007fff6e948cc9 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
/bin/sh: line 1: 73218 Abort trap: 6 ./ofx
make: *** [RunRelease] Error 134
It fails when I call camera.initGrabber(1280, 720);
, even if I’ve switched to use a different webcam.
Other info:
- This error is somewhat a lie–when I don’t have the USB webcam plugged in, two instances of the app can run off of the built-in webcam on my laptop just fine.
- Even if I use the webcam through some other app, the first instance always works. Zoom happily shares the webcam with OFX.
- I’m on a Macbook Pro Retina mid-2015, running Catalina and latest stable openframeworks version 11.0.
Any advice or thoughts would be welcome! Thanks so much.
Source code
//--------------------------------------------------------------
void ofApp::setup(){
settings.loadFile("settings.xml");
int cd = settings.getValue("settings:cameraDevice", 0);
this->cameraDeviceChanged(cd); // needs to be lvalue
// setup face detection
haar.setup(
settings.getValue("settings:detectionModel", ""));
haar.setScaleHaar(2);
baseMovie.load(
settings.getValue("settings:baseVideo", ""));
baseMovie.setLoopState(OF_LOOP_NORMAL);
baseMovie.play();
overlayMovie.load(
settings.getValue("settings:overlayVideo", ""));
overlayMovie.setLoopState(OF_LOOP_NORMAL);
overlayMovie.play();
cameraDevice.addListener(this, &ofApp::cameraDeviceChanged);
gui.setup(); // most of the time you don't need a name
gui.add(cameraDevice.set("cameraDevice", settings.getValue("settings:cameraDevice", 1), 0, 10));
gui.add(increasePresenceSpeed.setup("increasePresenceSpeed", settings.getValue("settings:increasePresenceSpeed", 2.3), 0, 10));
gui.add(decreasePresenceSpeed.setup("decreasePresenceSpeed", settings.getValue("settings:decreasePresenceSpeed", .2), 0, 10));
gui.add(minPlaybackSpeed.setup("minPlaybackSpeed", settings.getValue("settings:minPlaybackSpeed", .4), 0, 3));
gui.add(maxPlaybackSpeed.setup("maxPlaybackSpeed", settings.getValue("settings:maxPlaybackSpeed", 2.3), 0, 3));
gui.add(minOverlayOpacity.setup("minOverlayOpacity", settings.getValue("settings:minOverlayOpacity", .3), 0, 1));
gui.add(maxOverlayOpacity.setup("maxOverlayOpacity", settings.getValue("settings:maxOverlayOpacity", 1), 0, 1));
gui.add(presenceDebounceDelay.setup("presenceDebounceDelay", settings.getValue("settings:presenceDebounceDelay", .2), 0, 10));
gui.loadFromFile("settings.xml");
}
//--------------------------------------------------------------
void ofApp::update(){
baseMovie.update();
overlayMovie.update();
if (camera.isInitialized()) {
camera.update();
if(camera.isFrameNew()) {
// update textures
rgbImage.setFromPixels(camera.getPixels());
bwImage = rgbImage;
haar.findHaarObjects(bwImage);
}
}
double dt = ofGetLastFrameTime();
if (haar.blobs.size() > 0) {
presenceDebounceCounter = presenceDebounceDelay;
}
else if(presenceDebounceCounter > 0) {
presenceDebounceCounter -= dt;
}
if (presenceDebounceCounter > 0){
currentPresence += dt * increasePresenceSpeed;
}
else {
currentPresence -= dt * decreasePresenceSpeed;
}
currentPresence = ofClamp(currentPresence, 0, 1);
baseMovie.setSpeed(minPlaybackSpeed + (maxPlaybackSpeed - minPlaybackSpeed) * currentPresence);
overlayOpacityValue = 255 * (minOverlayOpacity + (maxOverlayOpacity - minOverlayOpacity) * currentPresence);
}
//--------------------------------------------------------------
void ofApp::draw(){
ofSetColor(ofColor::white);
baseMovie.draw(0,0, ofGetWindowWidth(),ofGetWindowHeight());
ofSetColor(255,255,255, overlayOpacityValue);
overlayMovie.draw(0,0, ofGetWindowWidth(),ofGetWindowHeight());
if (settings.getValue("settings:debug",0) == 1) {
ofSetColor(ofColor::white);
bwImage.draw(0, 0);
for (int i = 0; i < haar.blobs.size(); i++) {
ofRectangle rect;
rect = haar.blobs[i].boundingRect;
ofSetColor(ofColor::cadetBlue);
ofNoFill();
ofDrawRectangle(rect);
}
gui.draw();
}
}
//--------------------------------------------------------------
void ofApp::cameraDeviceChanged(int & cd){
camera.setDeviceID(cd);
camera.initGrabber(1280, 720, false);
// create camera textures
rgbImage.allocate(camera.getWidth(), camera.getHeight());
bwImage.allocate(camera.getWidth(), camera.getHeight());
}
//--------------------------------------------------------------
void ofApp::keyPressed(int key){
if (settings.getValue("settings:debug",0) == 1) {
settings.setValue("settings:debug",0);
}
else {
settings.setValue("settings:debug",1);
}
settings.saveFile("settings.xml");
}
//--------------------------------------------------------------
void ofApp::keyReleased(int key){
}
//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){
}
//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){
}
//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){
}
//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){
}
//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){
}
//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){
}