Example #1
0
//--------------------------------------------------------------------
bool ofVideoGrabber::initGrabber(int w, int h, bool setUseTexture){

	bUseTexture = setUseTexture;

	//---------------------------------
	#ifdef OF_VIDEO_CAPTURE_QUICKTIME
	//---------------------------------

		//---------------------------------- 1 - open the sequence grabber
		if( !qtInitSeqGrabber() ){
			ofLog(OF_LOG_ERROR, "error: unable to initialize the seq grabber");
			return false;
		}

		//---------------------------------- 2 - set the dimensions
		width 		= w;
		height 		= h;

		MacSetRect(&videoRect, 0, 0, width, height);

		//---------------------------------- 3 - buffer allocation
		// Create a buffer big enough to hold the video data,
		// make sure the pointer is 32-byte aligned.
		// also the rgb image that people will grab

		offscreenGWorldPixels 	= (unsigned char*)malloc(4 * width * height + 32);
		pixels					= new unsigned char[width*height*3];
		QTNewGWorldFromPtr (&videogworld, k32ARGBPixelFormat, &videoRect, NULL, NULL, 0, offscreenGWorldPixels, 4 * width);
		LockPixels(GetGWorldPixMap(videogworld));
		SetGWorld (videogworld, NULL);
		SGSetGWorld(gSeqGrabber, videogworld, nil);


		//---------------------------------- 4 - device selection
		bool didWeChooseADevice = bChooseDevice;
		bool deviceIsSelected	=  false;

		//if we have a device selected then try first to setup
		//that device
		if(didWeChooseADevice){
			deviceIsSelected = qtSelectDevice(deviceID, true);
			if(!deviceIsSelected && bVerbose) ofLog(OF_LOG_WARNING, "unable to open device[%i] - will attempt other devices", deviceID);
		}

		//if we couldn't select our required device
		//or we aren't specifiying a device to setup
		//then lets try to setup ANY device!
		if(deviceIsSelected == false){
			//lets list available devices
			listDevices();

			setDeviceID(0);
			deviceIsSelected = qtSelectDevice(deviceID, false);
		}

		//if we still haven't been able to setup a device
		//we should error and stop!
		if( deviceIsSelected == false){
			goto bail;
		}

		//---------------------------------- 5 - final initialization steps
		OSStatus err;

	 	err = SGSetChannelUsage(gVideoChannel,seqGrabPreview);
		if ( err != noErr ) goto bail;

		err = SGSetChannelBounds(gVideoChannel, &videoRect);
		if ( err != noErr ) goto bail;

		err = SGPrepare(gSeqGrabber,  true, false); //theo swapped so preview is true and capture is false
		if ( err != noErr ) goto bail;

		err = SGStartPreview(gSeqGrabber);
		if ( err != noErr ) goto bail;

		bGrabberInited = true;
		loadSettings();

		ofLog(OF_LOG_NOTICE,"end setup ofVideoGrabber");
		ofLog(OF_LOG_NOTICE,"-------------------------------------\n");


		//---------------------------------- 6 - setup texture if needed

		if (bUseTexture){
			// create the texture, set the pixels to black and
			// upload them to the texture (so at least we see nothing black the callback)
			tex.allocate(width,height,GL_RGB);
			memset(pixels, 0, width*height*3);
			tex.loadData(pixels, width, height, GL_RGB);
		}

		// we are done
		return true;


		//--------------------- (bail) something's wrong -----
		bail:

			ofLog(OF_LOG_ERROR, "***** ofVideoGrabber error *****");
			ofLog(OF_LOG_ERROR, "-------------------------------------\n");

			//if we don't close this - it messes up the next device!
			if(bSgInited) qtCloseSeqGrabber();

			bGrabberInited = false;
			return false;

	//---------------------------------
	#endif
	//---------------------------------


	//---------------------------------
	#ifdef OF_VIDEO_CAPTURE_DIRECTSHOW
	//---------------------------------

		if (bChooseDevice){
			device = deviceID;
			ofLog(OF_LOG_NOTICE, "choosing %i", deviceID);
		} else {
			device = 0;
		}

		width = w;
		height = h;
		bGrabberInited = false;

		bool bOk = VI.setupDevice(device, width, height);

		int ourRequestedWidth = width;
		int ourRequestedHeight = height;

		if (bOk == true){
			bGrabberInited = true;
			width 	= VI.getWidth(device);
			height 	= VI.getHeight(device);

			if (width == ourRequestedWidth && height == ourRequestedHeight){
				bDoWeNeedToResize = false;
			} else {
				bDoWeNeedToResize = true;
				width = ourRequestedWidth;
				height = ourRequestedHeight;
			}


			pixels	= new unsigned char[width * height * 3];

			if (bUseTexture){
				// create the texture, set the pixels to black and
				// upload them to the texture (so at least we see nothing black the callback)
				tex.allocate(width,height,GL_RGB);
				memset(pixels, 0, width*height*3);
				tex.loadData(pixels, width, height, GL_RGB);
			}

			return true;
		} else {
			ofLog(OF_LOG_ERROR, "error allocating a video device");
			ofLog(OF_LOG_ERROR, "please check your camera with AMCAP or other software");
			bGrabberInited = false;
			return false;
		}

	//---------------------------------
	#endif
	//---------------------------------



	//---------------------------------
	#ifdef OF_VIDEO_CAPTURE_UNICAP
	//--------------------------------
		if( !bGrabberInited ){
			if ( !bChooseDevice ){
				deviceID = 0;
			}

			width 	= w;
			height 	= h;
			pixels	= new unsigned char[width * height * 3];

			if (bUseTexture){
				// create the texture, set the pixels to black and
				// upload them to the texture (so at least we see nothing black the callback)
				tex.allocate(width,height,GL_RGB);
				memset(pixels, 0, width*height*3);
				tex.loadData(pixels, width, height, GL_RGB);
			}

			bGrabberInited = ucGrabber.open_device (deviceID);
			if( bGrabberInited ){
			ofLog(OF_LOG_NOTICE, "choosing device %i: %s", deviceID,ucGrabber.device_identifier());
				ucGrabber.set_format(w,h);
				ucGrabber.start_capture();
			}

		}
			return bGrabberInited;
	//---------------------------------
	#endif
	//---------------------------------

	//---------------------------------
	#ifdef OF_VIDEO_CAPTURE_GSTREAMER
	//--------------------------------
		if(gstUtils.initGrabber(w,h)){
			if ( !bChooseDevice ){
				deviceID = 0;
			}

			width 	= w;
			height 	= h;
			if (bUseTexture){
				// create the texture, set the pixels to black and
				// upload them to the texture (so at least we see nothing black the callback)
				tex.allocate(width,height,GL_RGB);
				tex.loadData(gstUtils.getPixels(), width, height, GL_RGB);
			}
			bGrabberInited = true;
			ofLog(OF_LOG_VERBOSE, "ofVideoGrabber: initied");
		}else{
			bGrabberInited = false;
			ofLog(OF_LOG_ERROR, "ofVideoGrabber: couldn't init");
		}
		return bGrabberInited;


	//---------------------------------
	#endif
	//---------------------------------

	//---------------------------------
	#ifdef OF_VIDEO_CAPTURE_V4L
	//--------------------------------
		if (bChooseDevice){
			device = deviceID;
		} else {
			device = 0;
		}
		sprintf(dev_name, "/dev/video%i", device);
		ofLog(OF_LOG_NOTICE, "choosing device %s",dev_name);

		bool bOk = initV4L(w, h, dev_name);

		if (bOk == true){
			bV4LGrabberInited = true;
			width 	= getV4L_Width();
			height 	= getV4L_Height();
			pixels	= new unsigned char[width * height * 3];

			if (bUseTexture){
				// create the texture, set the pixels to black and
				// upload them to the texture (so at least we see nothing black the callback)
				tex.allocate(width,height,GL_RGB);
				//memset(pixels, 0, width*height*3);
				//tex.loadData(pixels, width, height, GL_RGB);
			}

			ofLog(OF_LOG_NOTICE, "success allocating a video device ");
			return true;
		} else {
			ofLog(OF_LOG_ERROR, "error allocating a video device");
			ofLog(OF_LOG_ERROR, "please check your camera and verify that your driver is correctly installed.");
			return false;
		}	//---------------------------------


	//---------------------------------
	#endif
	//---------------------------------



}
//--------------------------------------------------------------------
vector<ofVideoDevice> ofQuickTimeGrabber::listDevices(){

    vector <ofVideoDevice> devices; 
    
	//---------------------------------
	#ifdef OF_VIDEO_CAPTURE_QUICKTIME
	//---------------------------------

		bool bNeedToInitGrabberFirst = false;

		if (!bSgInited) bNeedToInitGrabberFirst = true;

		//if we need to initialize the grabbing component then do it
		if( bNeedToInitGrabberFirst ){
			if( !qtInitSeqGrabber() ){
				return devices;
			}
		}

		ofLogNotice("ofQuickTimeGrabber") << "-------------------------------------";

		/*
			//input selection stuff (ie multiple webcams)
			//from http://developer.apple.com/samplecode/SGDevices/listing13.html
			//and originally http://lists.apple.com/archives/QuickTime-API/2008/Jan/msg00178.html
		*/

		SGDeviceList deviceList;
		SGGetChannelDeviceList (gVideoChannel, sgDeviceListIncludeInputs, &deviceList);
		unsigned char pascalName[64];
		unsigned char pascalNameInput[64];

		//this is our new way of enumerating devices
		//quicktime can have multiple capture 'inputs' on the same capture 'device'
		//ie the USB Video Class Video 'device' - can have multiple usb webcams attached on what QT calls 'inputs'
		//The isight for example will show up as:
		//USB Video Class Video - Built-in iSight ('input' 1 of the USB Video Class Video 'device')
		//Where as another webcam also plugged whill show up as
		//USB Video Class Video - Philips SPC 1000NC Webcam ('input' 2 of the USB Video Class Video 'device')

		//this means our the device ID we use for selection has to count both capture 'devices' and their 'inputs'
		//this needs to be the same in our init grabber method so that we select the device we ask for
		int deviceCount = 0;

		ofLogNotice("ofQuickTimeGrabber") << "listing available capture devices";
		for(int i = 0 ; i < (*deviceList)->count ; ++i)
		{
			SGDeviceName nameRec;
			nameRec = (*deviceList)->entry[i];
			SGDeviceInputList deviceInputList = nameRec.inputs;

			int numInputs = 0;
			if( deviceInputList ) numInputs = ((*deviceInputList)->count);

			memcpy(pascalName, (*deviceList)->entry[i].name, sizeof(char) * 64);

			//this means we can use the capture method
			if(nameRec.flags != sgDeviceNameFlagDeviceUnavailable){

				//if we have a capture 'device' (qt's word not mine - I would prefer 'system' ) that is ready to be used
				//we go through its inputs to list all physical devices - as there could be more than one!
				for(int j = 0; j < numInputs; j++){


					//if our 'device' has inputs we get their names here
					if( deviceInputList ){
						SGDeviceInputName inputNameRec  = (*deviceInputList)->entry[j];
						memcpy(pascalNameInput, inputNameRec.name, sizeof(char) * 64);
					}

					ofLogNotice() << "device [" << deviceCount << "] " << p2cstr(pascalName) << " - " << p2cstr(pascalNameInput);

                    ofVideoDevice vd; 
                    vd.id           = deviceCount; 
                    vd.deviceName   = p2cstr(pascalName);
                    vd.bAvailable   = true; 
                    devices.push_back(vd);
                    
					//we count this way as we need to be able to distinguish multiple inputs as devices
					deviceCount++;
				}

			}else{
				ofLogNotice("ofQuickTimeGrabber") << "(unavailable) device [" << deviceCount << "] " << p2cstr(pascalName);
                
                ofVideoDevice vd;
                vd.id           = deviceCount; 
                vd.deviceName   = p2cstr(pascalName);
                vd.bAvailable   = false; 
                devices.push_back(vd);

				deviceCount++;
			}
		}
		ofLogNotice("ofQuickTimeGrabber") << "-------------------------------------";

		//if we initialized the grabbing component then close it
		if( bNeedToInitGrabberFirst ){
			qtCloseSeqGrabber();
		}

	//---------------------------------
	#endif
	//---------------------------------

    return devices; 
}
Example #3
0
//--------------------------------------------------------------------
void ofVideoGrabber::listDevices(){

	//---------------------------------
	#ifdef OF_VIDEO_CAPTURE_QUICKTIME
	//---------------------------------

		bool bNeedToInitGrabberFirst = false;

		if (!bSgInited) bNeedToInitGrabberFirst = true;

		//if we need to initialize the grabbing component then do it
		if( bNeedToInitGrabberFirst ){
			if( !qtInitSeqGrabber() ){
				return;
			}
		}

		printf("-------------------------------------");

		/*
			//input selection stuff (ie multiple webcams)
			//from http://developer.apple.com/samplecode/SGDevices/listing13.html
			//and originally http://lists.apple.com/archives/QuickTime-API/2008/Jan/msg00178.html
		*/

		SGDeviceList deviceList;
		SGGetChannelDeviceList (gVideoChannel, sgDeviceListIncludeInputs, &deviceList);
		unsigned char pascalName[256];
		unsigned char pascalNameInput[256];

		//this is our new way of enumerating devices
		//quicktime can have multiple capture 'inputs' on the same capture 'device'
		//ie the USB Video Class Video 'device' - can have multiple usb webcams attached on what QT calls 'inputs'
		//The isight for example will show up as:
		//USB Video Class Video - Built-in iSight ('input' 1 of the USB Video Class Video 'device')
		//Where as another webcam also plugged whill show up as
		//USB Video Class Video - Philips SPC 1000NC Webcam ('input' 2 of the USB Video Class Video 'device')

		//this means our the device ID we use for selection has to count both capture 'devices' and their 'inputs'
		//this needs to be the same in our init grabber method so that we select the device we ask for
		int deviceCount = 0;

		ofLog(OF_LOG_NOTICE, "listing available capture devices");
		for(int i = 0 ; i < (*deviceList)->count ; ++i)
		{
			SGDeviceName nameRec;
			nameRec = (*deviceList)->entry[i];
			SGDeviceInputList deviceInputList = nameRec.inputs;

			int numInputs = 0;
			if( deviceInputList ) numInputs = ((*deviceInputList)->count);

			memcpy(pascalName, (*deviceList)->entry[i].name, sizeof(char) * 256);

			//this means we can use the capture method
			if(nameRec.flags != sgDeviceNameFlagDeviceUnavailable){

				//if we have a capture 'device' (qt's word not mine - I would prefer 'system' ) that is ready to be used
				//we go through its inputs to list all physical devices - as there could be more than one!
				for(int j = 0; j < numInputs; j++){


					//if our 'device' has inputs we get their names here
					if( deviceInputList ){
						SGDeviceInputName inputNameRec  = (*deviceInputList)->entry[j];
						memcpy(pascalNameInput, inputNameRec.name, sizeof(char) * 256);
					}

					printf( "device[%i] %s - %s",  deviceCount, p2cstr(pascalName), p2cstr(pascalNameInput) );

					//we count this way as we need to be able to distinguish multiple inputs as devices
					deviceCount++;
				}

			}else{
				printf( "(unavailable) device[%i] %s",  deviceCount, p2cstr(pascalName) );
				deviceCount++;
			}
		}
		printf( "-------------------------------------");

		//if we initialized the grabbing component then close it
		if( bNeedToInitGrabberFirst ){
			qtCloseSeqGrabber();
		}

	//---------------------------------
	#endif
	//---------------------------------


	//---------------------------------
	#ifdef OF_VIDEO_CAPTURE_DIRECTSHOW
	//---------------------------------
		ofLog(OF_LOG_NOTICE, "---");
		VI.listDevices();
		ofLog(OF_LOG_NOTICE, "---");

	//---------------------------------
	#endif
	//---------------------------------


	//---------------------------------
	#ifdef OF_VIDEO_CAPTURE_UNICAP
	//--------------------------------


		ucGrabber.listUCDevices();

	//---------------------------------
	#endif
	//---------------------------------

	//---------------------------------
	#ifdef OF_VIDEO_CAPTURE_GSTREAMER
	//--------------------------------


		gstUtils.listDevices();

	//---------------------------------
	#endif
	//---------------------------------

	//---------------------------------
	#ifdef OF_VIDEO_CAPTURE_V4L
	//--------------------------------

	struct stat st;

	printf( "listing available capture devices");
	printf( "---");
	for (int i = 0; i < 8; i++)
	{
		sprintf(dev_name, "/dev/video%i", i);
		if (stat (dev_name, &st) == 0) {
			printf( "Video device %i = /dev/video%i",i,i);
		} else {

		}
	}
	printf( "---");

	//---------------------------------
	#endif
	//---------------------------------

}
//--------------------------------------------------------------------
bool ofQuickTimeGrabber::initGrabber(int w, int h){

	//---------------------------------
	#ifdef OF_VIDEO_CAPTURE_QUICKTIME
	//---------------------------------

		//---------------------------------- 1 - open the sequence grabber
		if( !qtInitSeqGrabber() ){
			ofLogError("ofQuickTimeGrabber") << "initGrabber(): unable to initialize the seq grabber";
			return false;
		}

		//---------------------------------- 2 - set the dimensions
		//width 		= w;
		//height 		= h;

		MacSetRect(&videoRect, 0, 0, w, h);

		//---------------------------------- 3 - buffer allocation
		// Create a buffer big enough to hold the video data,
		// make sure the pointer is 32-byte aligned.
		// also the rgb image that people will grab

		offscreenGWorldPixels 	= (unsigned char*)malloc(4 * w * h + 32);
		pixels.allocate(w, h, OF_IMAGE_COLOR);
		
		#if defined(TARGET_OSX) && defined(__BIG_ENDIAN__)
			QTNewGWorldFromPtr (&(videogworld), k32ARGBPixelFormat, &(videoRect), NULL, NULL, 0, (offscreenGWorldPixels), 4 * w);		
		#else
			QTNewGWorldFromPtr (&(videogworld), k24RGBPixelFormat, &(videoRect), NULL, NULL, 0, (pixels.getPixels()), 3 * w);
		#endif		
		
		LockPixels(GetGWorldPixMap(videogworld));
		SetGWorld (videogworld, NULL);
		SGSetGWorld(gSeqGrabber, videogworld, nil);

		
		//---------------------------------- 4 - device selection
		bool didWeChooseADevice = bChooseDevice;
		bool deviceIsSelected	=  false;

		//if we have a device selected then try first to setup
		//that device
		if(didWeChooseADevice){
			deviceIsSelected = qtSelectDevice(deviceID, true);
			if(!deviceIsSelected && bVerbose)
				ofLogError("ofQuickTimeGrabber") << "initGrabber(): unable to open device[" << deviceID << "], will attempt other devices";
		}

		//if we couldn't select our required device
		//or we aren't specifiying a device to setup
		//then lets try to setup ANY device!
		if(deviceIsSelected == false){
			//lets list available devices
			listDevices();

			setDeviceID(0);
			deviceIsSelected = qtSelectDevice(deviceID, false);
		}

		//if we still haven't been able to setup a device
		//we should error and stop!
		if( deviceIsSelected == false){
			goto bail;
		}

		//---------------------------------- 5 - final initialization steps
		OSStatus err;

	 	err = SGSetChannelUsage(gVideoChannel,seqGrabPreview);
		if ( err != noErr ) goto bail;

	
		//----------------- callback method for notifying new frame
		err = SGSetChannelRefCon(gVideoChannel, (long)&bHavePixelsChanged );
		if(!err) {

			VideoBottles vb; 
			/* get the current bottlenecks */ 
			vb.procCount = 9; 
			err = SGGetVideoBottlenecks(gVideoChannel, &vb); 
			if (!err) { 			
				myGrabCompleteProc = NewSGGrabCompleteBottleUPP(frameIsGrabbedProc);
				vb.grabCompleteProc = myGrabCompleteProc;
			
				/* add our GrabFrameComplete function */ 
				err = SGSetVideoBottlenecks(gVideoChannel, &vb); 	
			}
		
		}
				
		err = SGSetChannelBounds(gVideoChannel, &videoRect);
		if ( err != noErr ) goto bail;

		err = SGPrepare(gSeqGrabber,  true, false); //theo swapped so preview is true and capture is false
		if ( err != noErr ) goto bail;

		err = SGStartPreview(gSeqGrabber);
		if ( err != noErr ) goto bail;

		bGrabberInited = true;
		loadSettings();
		
		if( attemptFramerate >= 0 ){
			err = SGSetFrameRate(gVideoChannel, IntToFixed(attemptFramerate) );
			if ( err != noErr ){
				ofLogError("ofQuickTimeGrabber") << "initGrabber: couldn't setting framerate to " << attemptFramerate << ": OSStatus " << err;
			}		
		}
		
		ofLogNotice("ofQuickTimeGrabber") << "           inited grabbed            ";
		ofLogNotice("ofQuickTimeGrabber") << "-------------------------------------";

		// we are done
		return true;


		//--------------------- (bail) something's wrong -----
		bail:

			ofLogError("ofQuickTimeGrabber") << "***** ofQuickTimeGrabber error *****";
			ofLogError("ofQuickTimeGrabber") << "------------------------------------";

			//if we don't close this - it messes up the next device!
			if(bSgInited) qtCloseSeqGrabber();

			bGrabberInited = false;
			return false;
			
	//---------------------------------
	#else
	//---------------------------------
		return false;
	//---------------------------------
	#endif
	//---------------------------------

}