topical media & game development

talk show tell print

lib-of-vs-libs-openFrameworks-video-ofVideoGrabber.cpp / cpp



  include <ofVideoGrabber.h>
  include <ofUtils.h>
  
  ifdef OF_VIDEO_CAPTURE_V4L
          #include <ofV4LUtils.h>
  endif
  
  //--------------------------------------------------------------------
  ofVideoGrabber::ofVideoGrabber(){
  
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_QUICKTIME
          //---------------------------------
  
                  initializeQuicktime();
                  bSgInited                                = false;
                  pixels                                        = NULL;
                  gSeqGrabber                                = NULL;
                  offscreenGWorldPixels        = NULL;
  
          //---------------------------------
          #endif
          //---------------------------------
  
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_DIRECTSHOW
          //---------------------------------
  
                  bVerbose                         = false;
                  bDoWeNeedToResize         = false;
  
          //---------------------------------
          #endif
          //---------------------------------
  
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_V4L                                // kept around if people have unicap issues...
          //--------------------------------
  
                  bV4LGrabberInited         = false;
  
          //---------------------------------
          #endif
          //---------------------------------
  
          // common
          bIsFrameNew                                = false;
          bVerbose                                 = false;
          bGrabberInited                         = false;
          bUseTexture                                = true;
          bChooseDevice                        = false;
          deviceID                                = 0;
          width                                         = 320;        // default setting
          height                                         = 240;        // default setting
          pixels                                        = NULL;
  }
  
  //--------------------------------------------------------------------
  ofVideoGrabber::~ofVideoGrabber(){
  
          close();
  
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_QUICKTIME
          //---------------------------------
                  if (offscreenGWorldPixels != NULL){
                          delete[] offscreenGWorldPixels;
                  }
          //---------------------------------
          #endif
          //---------------------------------
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_UNICAP
          //--------------------------------
                  if(bGrabberInited)
                          ucGrabber.close_unicap();
  
          //---------------------------------
          #endif
          //---------------------------------
  
  }
  
  //--------------------------------------------------------------------
  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;
                          }
                  }
  
                  ofLog(OF_LOG_NOTICE, "-------------------------------------");
  
                  /*
                          //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);
                                          }
  
                                          ofLog(OF_LOG_NOTICE, "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{
                                  ofLog(OF_LOG_NOTICE, "(unavailable) device[\%i] \%s",  deviceCount, p2cstr(pascalName) );
                                  deviceCount++;
                          }
                  }
                  ofLog(OF_LOG_NOTICE, "-------------------------------------");
  
                  //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_V4L
          //--------------------------------
  
          struct stat st;
  
          ofLog(OF_LOG_NOTICE, "listing available capture devices");
          ofLog(OF_LOG_NOTICE, "---");
          for (int i = 0; i < 8; i++)
          {
                  sprintf(dev_name, "/dev/video\%i", i);
                  if (stat (dev_name, &st) == 0) {
                          ofLog(OF_LOG_NOTICE, "Video device \%i = /dev/video\%i",i,i);
                  } else {
  
                  }
          }
          ofLog(OF_LOG_NOTICE, "---");
  
          //---------------------------------
          #endif
          //---------------------------------
  
  }
  
  //--------------------------------------------------------------------
  void ofVideoGrabber::setVerbose(bool bTalkToMe){
          bVerbose = bTalkToMe;
  
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_UNICAP
          //--------------------------------
  
                  ucGrabber.verbose=bVerbose;
  
          //---------------------------------
          #endif
          //---------------------------------
  }
  
  //--------------------------------------------------------------------
  void ofVideoGrabber::setDeviceID(int _deviceID){
          deviceID                = _deviceID;
          bChooseDevice        = true;
  }
  
  //---------------------------------------------------------------------------
  unsigned char * ofVideoGrabber::getPixels(){
          return pixels;
  }
  
  //------------------------------------
  //for getting a reference to the texture
  ofTexture & ofVideoGrabber::getTextureReference(){
          if(!tex.bAllocated() ){
                  ofLog(OF_LOG_WARNING, "ofVideoGrabber - getTextureReference - texture is not allocated");
          }
          return tex;
  }
  
  //---------------------------------------------------------------------------
  bool  ofVideoGrabber::isFrameNew(){
          return bIsFrameNew;
  }
  
  //--------------------------------------------------------------------
  void ofVideoGrabber::update(){
          grabFrame();
  }
  
  //--------------------------------------------------------------------
  void ofVideoGrabber::grabFrame(){
  
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_QUICKTIME
          //---------------------------------
  
                  if (bGrabberInited == true){
                          SGIdle(gSeqGrabber);
                          // set the top pixel alpha = 0, so we can know if it
                          // was a new frame or not..
                          // or else we will process way more than necessary
                          // (ie opengl is running at 60fps +, capture at 30fps)
                          if (offscreenGWorldPixels[0] != 0x00){
                                  offscreenGWorldPixels[0] = 0x00;
                                  bHavePixelsChanged = true;
                                  convertPixels(offscreenGWorldPixels, pixels, width, height);
                                  if (bUseTexture){
                                          tex.loadData(pixels, width, height, GL_RGB);
                                  }
                          }
                  }
  
                  // newness test for quicktime:
                  if (bGrabberInited == true){
                          bIsFrameNew = false;
                          if (bHavePixelsChanged == true){
                                  bIsFrameNew = true;
                                  bHavePixelsChanged = false;
                          }
                  }
  
          //---------------------------------
          #endif
          //---------------------------------
  
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_DIRECTSHOW
          //---------------------------------
  
                  if (bGrabberInited == true){
                          bIsFrameNew = false;
                          if (VI.isFrameNew(device)){
  
                                  bIsFrameNew = true;
  
                                  /*
                                           rescale --
                                           currently this is nearest neighbor scaling
                                           not the greatest, but fast
                                           this can be optimized too
                                           with pointers, etc
  
                                           better --
                                           make sure that you ask for a "good" size....
  
  				*/
  
                                  unsigned char * viPixels = VI.getPixels(device, true, true);
  
                                  if (bDoWeNeedToResize == true){
  
                                          int inputW = VI.getWidth(device);
                                          int inputH = VI.getHeight(device);
  
                                          float scaleW =        (float)inputW / (float)width;
                                          float scaleH =        (float)inputH / (float)height;
  
                                          for(int i=0;i<width;i++){
                                                  for(int j=0;j<height;j++){
  
                                                          float posx = i * scaleW;
                                                          float posy = j * scaleH;
  
                                                          /*
  
                                                          // start of calculating
                                                          // for linear interpolation
  
                                                          int xbase = (int)floor(posx);
                                                          int xhigh = (int)ceil(posx);
                                                          float pctx = (posx - xbase);
  
                                                          int ybase = (int)floor(posy);
                                                          int yhigh = (int)ceil(posy);
                                                          float pcty = (posy - ybase);
  							*/
  
                                                          int posPix = (((int)posy * inputW * 3) + ((int)posx * 3));
  
                                                          pixels[(j*width*3) + i*3    ] = viPixels[posPix  ];
                                                          pixels[(j*width*3) + i*3 + 1] = viPixels[posPix+1];
                                                          pixels[(j*width*3) + i*3 + 2] = viPixels[posPix+2];
  
                                                  }
                                          }
  
                                  } else {
  
                                          memcpy(pixels, viPixels, width*height*3);
  
                                  }
  
                                  if (bUseTexture){
                                          tex.loadData(pixels, width, height, GL_RGB);
                                  }
                          }
                  }
  
          //---------------------------------
          #endif
          //---------------------------------
  
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_UNICAP
          //--------------------------------
  
                  if (bGrabberInited){
                          bIsFrameNew = ucGrabber.getFrameUC(&pixels);
                          if(bIsFrameNew) {
                                  if (bUseTexture){
                                          tex.loadData(pixels, width, height, GL_RGB);
                                  }
                          }
                  }
  
          //---------------------------------
          #endif
          //---------------------------------
  
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_V4L
          //--------------------------------
  
                  if (bV4LGrabberInited == true){
                          bIsFrameNew = getFrameV4L(pixels);
                          if(bIsFrameNew) {
                                  if (bUseTexture){
                                          tex.loadData(pixels, width, height, GL_RGB);
                                  }
                          }
                  }
  
          //---------------------------------
          #endif
          //---------------------------------
  
  }
  
  //--------------------------------------------------------------------
  void ofVideoGrabber::close(){
  
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_QUICKTIME
          //---------------------------------
  
                  qtCloseSeqGrabber();
  
          //---------------------------------
          #endif
          //---------------------------------
  
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_V4L
          //--------------------------------
  
                  closeV4L();
  
          //---------------------------------
          #endif
          //---------------------------------
  
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_DIRECTSHOW
          //---------------------------------
  
                  if (bGrabberInited == true){
                          VI.stopDevice(device);
                          bGrabberInited = false;
                  }
  
          //---------------------------------
          #endif
          //---------------------------------
  
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_UNICAP
          //--------------------------------
  
                  if(bGrabberInited){
                          ucGrabber.close_unicap();
                          bGrabberInited                 = false;
                          deviceID                         = 0;
                          bIsFrameNew                 = false;
                          bChooseDevice                 = false;
                  }
  
          //---------------------------------
          #endif
          //---------------------------------
          if (pixels != NULL){
                  delete[] pixels;
                  pixels = NULL;
          }
  
          tex.clear();
  
  }
  
  //--------------------------------------------------------------------
  void ofVideoGrabber::videoSettings(void){
  
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_QUICKTIME
          //---------------------------------
  
                  Rect curBounds, curVideoRect;
                  ComponentResult        err;
  
                  // Get our current state
                  err = SGGetChannelBounds (gVideoChannel, &curBounds);
                  if (err != noErr){
                          ofLog(OF_LOG_ERROR, "Error in SGGetChannelBounds");
                          return;
                  }
                  err = SGGetVideoRect (gVideoChannel, &curVideoRect);
                  if (err != noErr){
                          ofLog(OF_LOG_ERROR, "Error in SGGetVideoRect");
                          return;
                  }
  
                  // Pause
                  err = SGPause (gSeqGrabber, true);
                  if (err != noErr){
                          ofLog(OF_LOG_ERROR, "Error in SGPause");
                          return;
                  }
  
                  #ifdef TARGET_OSX
                          //load any saved camera settings from file
                          loadSettings();
  
                          static SGModalFilterUPP gSeqGrabberModalFilterUPP = NewSGModalFilterUPP(SeqGrabberModalFilterUPP);
                          ComponentResult result = SGSettingsDialog(gSeqGrabber,  gVideoChannel, 0, nil, seqGrabSettingsPreviewOnly, gSeqGrabberModalFilterUPP, nil);
                          if (result != noErr){
                                  ofLog(OF_LOG_ERROR, "error in  dialogue");
                                  return;
                          }
  
                          //save any changed settings to file
                          saveSettings();
                  #else
                          SGSettingsDialog(gSeqGrabber, gVideoChannel, 0, nil, seqGrabSettingsPreviewOnly, NULL, 0);
                  #endif
  
                  SGSetChannelBounds(gVideoChannel, &videoRect);
                  SGPause (gSeqGrabber, false);
  
          //---------------------------------
          #endif
          //---------------------------------
  
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_DIRECTSHOW
          //---------------------------------
  
                  if (bGrabberInited == true) VI.showSettingsWindow(device);
  
          //---------------------------------
          #endif
          //---------------------------------
  
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_UNICAP
          //--------------------------------
  
                  ucGrabber.queryUC_imageProperties();
  
          //---------------------------------
          #endif
          //---------------------------------
  
          //---------------------------------
          #ifdef OF_VIDEO_CAPTURE_V4L
          //--------------------------------
  
                  queryV4L_imageProperties();
  
          //---------------------------------
          #endif
          //---------------------------------
  
  }
  
  //--------------------------------------------------------------------
  ifdef TARGET_OSX
  //--------------------------------------------------------------------
  
  //---------------------------------------------------------------------
  bool ofVideoGrabber::saveSettings(){
  
                  if (bGrabberInited != true) return false;
                  ComponentResult        err;
  
                  UserData mySGVideoSettings = NULL;
                  // get the SGChannel settings cofigured by the user
                  err = SGGetChannelSettings(gSeqGrabber, gVideoChannel, &mySGVideoSettings, 0);
                  if ( err != noErr ){
                          ofLog(OF_LOG_ERROR, "Error getting camera settings \%i",err);
                          return false;
                  }
                  string pref = "ofVideoSettings-"+deviceName;
                  CFStringRef cameraString = CFStringCreateWithCString(kCFAllocatorDefault,pref.c_str(),kCFStringEncodingMacRoman);
  
                  //get the settings using the key "ofVideoSettings-the name of the device"
                  SaveSettingsPreference( cameraString, mySGVideoSettings);
                  DisposeUserData(mySGVideoSettings);
                  return true;
  
  }
  
  //---------------------------------------------------------------------
  bool ofVideoGrabber::loadSettings(){
  
     if (bGrabberInited != true || deviceName.length() == 0) return false;
  
     ComponentResult   err;
     UserData mySGVideoSettings = NULL;
  
     // get the settings using the key "ofVideoSettings-the name of the device"
     string pref = "ofVideoSettings-"+deviceName;
     CFStringRef cameraString = CFStringCreateWithCString(kCFAllocatorDefault,pref.c_str(),kCFStringEncodingMacRoman);
  
     GetSettingsPreference(cameraString, &mySGVideoSettings);
     if (mySGVideoSettings){
  
        Rect   curBounds, curVideoRect;
  
        //we need to make sure the dimensions don't get effected
        //by our preferences
  
        // Get our current state
        err = SGGetChannelBounds (gVideoChannel, &curBounds);
        if (err != noErr){
           ofLog(OF_LOG_ERROR, "Error in SGGetChannelBounds");
        }
        err = SGGetVideoRect (gVideoChannel, &curVideoRect);
        if (err != noErr){
           ofLog(OF_LOG_ERROR, "Error in SGGetVideoRect");
        }
  
        // use the saved settings preference to configure the SGChannel
        err = SGSetChannelSettings(gSeqGrabber, gVideoChannel, mySGVideoSettings, 0);
        if ( err != noErr ) {
           ofLog(OF_LOG_ERROR, "Error applying stored settings \%i", err);
           return false;
        }
        DisposeUserData(mySGVideoSettings);
  
        // Pause
        err = SGPause (gSeqGrabber, true);
        if (err != noErr){
           ofLog(OF_LOG_ERROR, "Error in SGPause");
        }
        SGSetChannelBounds(gVideoChannel, &videoRect);
        SGPause (gSeqGrabber, false);
  
     }else{
        ofLog(OF_LOG_WARNING, "No camera settings to load");
        return false;
     }
     return true;
  }
  
  //------------------------------------------------------
  bool ofVideoGrabber::qtInitSeqGrabber(){
  
                  if (bSgInited != true){
  
                          OSErr err = noErr;
  
                          ComponentDescription        theDesc;
                          Component                                sgCompID;
  
                          // this crashes when we get to
                          // SGNewChannel
                          // we get -9405 as error code for the channel
                          // -----------------------------------------
                          // gSeqGrabber = OpenDefaultComponent(SeqGrabComponentType, 0);
  
                          // this seems to work instead (got it from hackTV)
                          // -----------------------------------------
                          theDesc.componentType = SeqGrabComponentType;
                          theDesc.componentSubType = NULL;
                          theDesc.componentManufacturer = 'appl';
                          theDesc.componentFlags = NULL;
                          theDesc.componentFlagsMask = NULL;
                          sgCompID = FindNextComponent (NULL, &theDesc);
                          // -----------------------------------------
  
                          if (sgCompID == NULL){
                                  ofLog(OF_LOG_ERROR, "error:FindNextComponent did not return a valid component");
                                  return false;
                          }
  
                          gSeqGrabber = OpenComponent(sgCompID);
  
                          err = GetMoviesError();
                          if (gSeqGrabber == NULL || err) {
                                  ofLog(OF_LOG_ERROR, "error: can't get default sequence grabber component");
                                  return false;
                          }
  
                          err = SGInitialize(gSeqGrabber);
                          if (err != noErr) {
                                  ofLog(OF_LOG_ERROR, "error: can't initialize sequence grabber component");
                                  return false;
                          }
  
                          err = SGSetDataRef(gSeqGrabber, 0, 0, seqGrabDontMakeMovie);
                          if (err != noErr) {
                                  ofLog(OF_LOG_ERROR, "error: can't set the destination data reference");
                                  return false;
                          }
  
                          // windows crashes w/ out gworld, make a dummy for now...
                          // this took a long time to figure out.
                          err = SGSetGWorld(gSeqGrabber, 0, 0);
                          if (err != noErr) {
                                  ofLog(OF_LOG_ERROR, "error: setting up the gworld");
                                  return false;
                          }
  
                          err = SGNewChannel(gSeqGrabber, VideoMediaType, &(gVideoChannel));
                          if (err != noErr) {
                                  ofLog(OF_LOG_ERROR, "error: creating a channel.  Check if you have any qt capable cameras attached");
                                  return false;
                          }
  
                          bSgInited = true;
                          return true;
                  }
  
                  return false;
  }
  
  //--------------------------------------------------------------------
  bool ofVideoGrabber::qtCloseSeqGrabber(){
  
          if (gSeqGrabber != NULL){
                  SGStop (gSeqGrabber);
                  CloseComponent (gSeqGrabber);
                  gSeqGrabber = NULL;
                  bSgInited = false;
                  return true;
          }
  
          return false;
  
  }
  
  //--------------------------------------------------------------------
  bool ofVideoGrabber::qtSelectDevice(int deviceNumber, bool didWeChooseADevice){
  
          //note - check for memory freeing possibly needed for the all SGGetChannelDeviceList mac stuff
          // also see notes in listDevices() regarding new enunemeration method.
  
          //Generate a device list and enumerate
          //all devices availble to the channel
          SGDeviceList deviceList;
          SGGetChannelDeviceList(gVideoChannel, sgDeviceListIncludeInputs, &deviceList);
  
          unsigned char pascalName[256];
          unsigned char pascalNameInput[256];
  
          int numDevices = (*deviceList)->count;
          if(numDevices == 0){
                  ofLog(OF_LOG_ERROR, "error: No catpure devices found");
                  return false;
          }
  
          int deviceCount = 0;
          for(int i = 0 ; i < numDevices; ++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);
                  memset(pascalNameInput, 0, 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);
                                  }
  
                                  //if the device number matches we try and setup the device
                                  //if we didn't specifiy a device then we will try all devices till one works!
                                  if( deviceCount == deviceNumber || !didWeChooseADevice ){
                                          ofLog(OF_LOG_NOTICE, "attempting to open device[\%i] \%s   -   \%s",  deviceCount, p2cstr(pascalName), p2cstr(pascalNameInput) );
  
                                          OSErr err1 = SGSetChannelDevice(gVideoChannel, pascalName);
                                          OSErr err2 = SGSetChannelDeviceInput(gVideoChannel, j);
  
                                          int successLevel = 0;
  
                                          //if there were no errors then we have opened the device without issue
                                          if ( err1 == noErr && err2 == noErr){
                                                  successLevel = 2;
                                          }
                                                  //parameter errors are not fatal so we will try and open but will caution the user
                                          else if ( (err1 == paramErr || err1 == noErr) && (err2 == noErr || err2 == paramErr) ){
                                                  successLevel = 1;
                                          }
  
                                          //the device is opened!
                                          if ( successLevel > 0 ){
  
                                                  deviceName = (char *)p2cstr(pascalName);
                                                  deviceName  += "-";
                                                  deviceName +=  (char *)p2cstr(pascalNameInput);
  
                                                  if(successLevel == 2)ofLog(OF_LOG_NOTICE, "device opened successfully");
                                                  else ofLog(OF_LOG_WARNING, "device opened with some paramater errors - should be fine though!");
  
                                                  //no need to keep searching - return that we have opened a device!
                                                  return true;
  
                                          }else{
                                                  //if we selected a device in particular but failed we want to go through the whole list again - starting from 0 and try any device.
                                                  //so we return false - and try one more time without a preference
                                                  if( didWeChooseADevice ){
                                                          ofLog(OF_LOG_WARNING, "problems setting device[\%i] \%s - \%s *****", deviceNumber, p2cstr(pascalName), p2cstr(pascalNameInput));
                                                          return false;
                                                  }else{
                                                          ofLog(OF_LOG_WARNING, "unable to open device, trying next device");
                                                  }
                                          }
  
                                  }
  
                                  //we count this way as we need to be able to distinguish multiple inputs as devices
                                  deviceCount++;
                          }
                  }else{
                          //ofLog(OF_LOG_ERROR, "(unavailable) device[\%i] \%s",  deviceCount, p2cstr(pascalName) );
                          deviceCount++;
                  }
          }
  
          return false;
  }
  
  //---------------------------------
  endif
  //---------------------------------
  
  //--------------------------------------------------------------------
  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_V4L
          //--------------------------------
                  if (bChooseDevice){
                          device = deviceID;
                  } else {
                          device = 0;
                  }
                  sprintf(dev_name, "/dev/video\%i", device);
                  ofLog(OF_LOG_NOTICE, "choosing device "+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
          //---------------------------------
  
  }
  
  //------------------------------------
  void ofVideoGrabber::setUseTexture(bool bUse){
          bUseTexture = bUse;
  }
  
  //we could cap these values - but it might be more useful
  //to be able to set anchor points outside the image
  
  //----------------------------------------------------------
  void ofVideoGrabber::setAnchorPercent(float xPct, float yPct){
      if (bUseTexture)tex.setAnchorPercent(xPct, yPct);
  }
  
  //----------------------------------------------------------
  void ofVideoGrabber::setAnchorPoint(int x, int y){
      if (bUseTexture)tex.setAnchorPoint(x, y);
  }
  
  //----------------------------------------------------------
  void ofVideoGrabber::resetAnchor(){
             if (bUseTexture)tex.resetAnchor();
  }
  
  //------------------------------------
  void ofVideoGrabber::draw(float _x, float _y, float _w, float _h){
          if (bUseTexture){
                  tex.draw(_x, _y, _w, _h);
          }
  }
  
  //------------------------------------
  void ofVideoGrabber::draw(float _x, float _y){
          draw(_x, _y, (float)width, (float)height);
  }
  
  //----------------------------------------------------------
  float ofVideoGrabber::getHeight(){
          return (float)height;
  }
  
  //----------------------------------------------------------
  float ofVideoGrabber::getWidth(){
          return (float)width;
  }
  


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.