00001 /*!@file Devices/XCgrabberFlex.C Interface with a Silicon imaging digital camera */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Farhan Baluch <fbaluch@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Devices/XCgrabberFlex.C $ 00035 // $Id: XCgrabberFlex.C$ 00036 // 00037 00038 #include <cstddef> 00039 #include <string> 00040 00041 #include "Component/OptionManager.H" // for option alias requests 00042 #include "Devices/DeviceOpts.H" 00043 #include "Image/Image.H" 00044 #include "Image/Pixels.H" 00045 #include "Image/MathOps.H" 00046 #include "Raster/GenericFrame.H" 00047 #include "Raster/Raster.H" 00048 #include "Util/Assert.H" 00049 #include "Util/SimTime.H" 00050 #include "Util/sformat.H" 00051 #include "Video/VideoFrame.H" 00052 00053 #include "Devices/XCgrabberFlex.H" 00054 00055 // wait when polling for a frame (in us): 00056 #define XCWAIT 50 00057 //define the imaging board, (we have only one board) 00058 #define UNITMAP 1 00059 #define USEDBUFFER 16 00060 00061 // ###################################################################### 00062 XCgrabberFlex::XCgrabberFlex(OptionManager& mgr, 00063 const std::string& descrName, 00064 const std::string& tagName, 00065 const ParamFlag flags) : 00066 FrameIstream(mgr, descrName, tagName), 00067 itsDims(&OPT_FrameGrabberDims, this, Dims(1920, 1080), USE_MY_VAL), 00068 itsGrabMode(&OPT_FrameGrabberMode, this, VIDFMT_BAYER_GB, USE_MY_VAL), 00069 itsByteSwap(&OPT_FrameGrabberByteSwap, this, false, USE_MY_VAL), 00070 itsWhiteBalTarR(&OPT_FrameGrabberWhiteBalTargetR, this, false, USE_MY_VAL), 00071 itsWhiteBalTarG(&OPT_FrameGrabberWhiteBalTargetG, this, false, USE_MY_VAL), 00072 itsWhiteBalTarB(&OPT_FrameGrabberWhiteBalTargetB, this, false, USE_MY_VAL), 00073 itsWhiteBalRefR(&OPT_FrameGrabberWhiteBalReferenceR, this, false, USE_MY_VAL), 00074 itsWhiteBalRefG(&OPT_FrameGrabberWhiteBalReferenceG, this, false, USE_MY_VAL), 00075 itsWhiteBalRefB(&OPT_FrameGrabberWhiteBalReferenceB, this, false, USE_MY_VAL), 00076 itsGamma(&OPT_XCFrameGrabberGamma, this, 1.0, USE_MY_VAL | ALLOW_ONLINE_CHANGES), 00077 itsFPS(&OPT_FrameGrabberFPS, this, 30.0, USE_MY_VAL) 00078 #ifdef HAVE_XCLIB 00079 ,itsFormatFile(&OPT_XCFormatFileName, this), 00080 itsCameraOk(false), 00081 itsImgBuf(NULL) 00082 #endif 00083 { 00084 #ifdef HAVE_XCLIB 00085 memset(&itsXclib, 0, sizeof(itsXclib)); 00086 itsXclib.ddch.len = sizeof(itsXclib); 00087 itsXclib.ddch.mos = XCMOS_LIBS; 00088 00089 itsStatep = NULL; 00090 itsLastBuf = 0; 00091 #endif 00092 } 00093 00094 // ###################################################################### 00095 void XCgrabberFlex::start1() 00096 { 00097 #ifndef HAVE_XCLIB 00098 LFATAL("you must have XC support and the xclib library in order to use XCgrabberFlex"); 00099 #else 00100 // open the XC cameralink imaging board 00101 int i; 00102 if(!strcmp(itsFormatFile.getVal().c_str(),"noFile")) 00103 { 00104 LINFO("use default setup configure format"); 00105 char* format =(char*)("default"); 00106 i = xclib::xclib_open(&itsXclib, NULL,NULL, format, NULL); 00107 } 00108 else 00109 { 00110 LINFO("use input format file as configure file"); 00111 char* formatFile = (char*)(itsFormatFile.getVal().c_str()); 00112 i = xclib::xclib_open(&itsXclib, NULL, NULL, NULL, formatFile); 00113 } 00114 if(i != 0) 00115 { 00116 LINFO("error code %d\n", i); 00117 LFATAL("can not open the XC camera"); 00118 } 00119 00120 switch(itsGrabMode.getVal()) 00121 { 00122 case VIDFMT_BAYER_GB12: itsBitDepth = 12; break; 00123 case VIDFMT_BAYER_GR12: itsBitDepth = 12; break; 00124 case VIDFMT_BAYER_RG12: itsBitDepth = 12; break; 00125 case VIDFMT_BAYER_BG12: itsBitDepth = 12; break; 00126 case VIDFMT_BAYER_GB: itsBitDepth = 8; break; 00127 case VIDFMT_BAYER_GR: itsBitDepth = 8; break; 00128 case VIDFMT_BAYER_RG: itsBitDepth = 8; break; 00129 case VIDFMT_BAYER_BG: itsBitDepth = 8; break; 00130 default: LFATAL("ERROR in specify the xc grab mode"); 00131 } 00132 00133 // list basic camera info 00134 struct xclib::pxdevinfo pxinfo; 00135 memset(&pxinfo, 0, sizeof(pxinfo)); 00136 pxinfo.ddch.len = sizeof(pxinfo); 00137 pxinfo.ddch.mos = PXMOS_DEVINFO; 00138 00139 itsXclib.pxdev.getDevInfo(&(itsXclib.pxdev), UNITMAP, 0, &pxinfo); 00140 LINFO("find %d baords, frame buffer memory = %.4f Kbytes", 00141 pxinfo.nunits,(double)pxinfo.memsize/1024); 00142 00143 //white balance 00144 WhiteBalance(); 00145 00146 struct xclib::pxlibservice pxlib = itsXclib.pxlib; 00147 struct xclib::xcdevservice xcdev = itsXclib.xcdev; 00148 00149 // initialize pxvidstate 00150 i = pxlib.allocStateCopy(&pxlib, 0, 0, &itsStatep); 00151 LINFO("allocate state copy (video state), result code: %d", i); 00152 00153 i = pxlib.initStateCopy(&pxlib, 0, 0, 00154 itsStatep, &pxinfo, (char*)("default"), PXMODE_DIGI); 00155 LINFO("init state copy (video state), result code: %d",i); 00156 pxlib.defineState(&pxlib, 0, itsStateid, itsStatep); 00157 00158 // itsStatep->vidres->x.vidoffset = 640;//1920/2-itsDims.getVal().w()/2; 00159 //itsStatep->vidres->x.vidoffsend = 1920; //1920/2+itsDims.getVal().w()/2; 00160 00161 LINFO("pxvidimage dims = %d,%d\n",itsStatep->vidres->x.vidoffset, 00162 itsStatep->vidres->x.vidoffsend); 00163 00164 //! show some info of pxvidstate structure 00165 /* 00166 LINFO("the pxvidimage bayerpattern: %d, %d, %d, %d, %d, %d\n", 00167 itsStatep->vidimage->bp.order, 00168 itsStatep->vidimage->bp.mode, 00169 itsStatep->vidimage->bp.arg[0], 00170 itsStatep->vidimage->bp.arg[1], 00171 itsStatep->vidimage->bp.arg[2], 00172 itsStatep->vidimage->bp.arg[3]); 00173 00174 LINFO("the pxvidimage colorspace: %d, %d, %d", 00175 itsStatep->vidimage->cs.order, 00176 itsStatep->vidimage->cs.mode, 00177 (int)itsStatep->vidimage->cs.scale); 00178 00179 LINFO("the pxvid image whitebalance: %d, %d, %d", 00180 itsStatep->vidimage->wb.order, 00181 itsStatep->vidimage->wb.mode, 00182 (int)itsStatep->vidimage->wb.gamma[0][0]); 00183 00184 LINFO("the pxvid image sharp :%d, %d, %d, %d, %d", 00185 itsStatep->vidimage->sh.order, 00186 itsStatep->vidimage->sh.mode, 00187 itsStatep->vidimage->sh.scale, 00188 itsStatep->vidimage->sh.into[0], 00189 itsStatep->vidimage->sh.from[0]); 00190 00191 for(int i=0; i<6; i++) 00192 for(int j=0; j<4; j++) 00193 { 00194 itsStatep->vidimage->wb.gamma[i][j] = 100; 00195 itsStatep->vidimage->wb.darkreference[i][j] = 30; 00196 itsStatep->vidimage->wb.darktarget[i][j] = 30; 00197 itsStatep->vidimage->wb.brightreference[i][j] = 120; 00198 itsStatep->vidimage->wb.brighttarget[i][j] = 200; 00199 } 00200 itsStatep->vidimage->wb.mode = 3; 00201 itsStatep->vidimage->wb.order = 1; 00202 00203 itsStatep->vidimage->sh.order = 1; 00204 itsStatep->vidimage->sh.mode = 3; 00205 itsStatep->vidimage->sh.into[0] = 120; 00206 itsStatep->vidimage->sh.into[1] = 120; 00207 itsStatep->vidimage->sh.into[2] = 120; 00208 itsStatep->vidimage->sh.from[0] = 200; 00209 itsStatep->vidimage->sh.from[1] = 200; 00210 itsStatep->vidimage->sh.from[2] = 200; 00211 itsStatep->vidimage->sh.scale = 2; 00212 itsStatep->vidimage->sh.arg[0] = 1; 00213 itsStatep->vidimage->sh.arg[1] = 1; 00214 00215 i = xcdev.setCameraConfig(&xcdev, UNITMAP, 0, 0, itsStatep, NULL); 00216 LINFO("set camera config res code: %d", i); 00217 LINFO("after wb, gamma is %d", (int)itsStatep->vidimage->wb.gamma[0][0]); 00218 00219 i = pxlib.exportStateCopy(&pxlib,0, itsStateid, itsStatep, 0,(char*) 00220 "trash_xc_format.txt",NULL,NULL,NULL); 00221 LINFO("export state res code: %d", i); 00222 */ 00223 i = xcdev.setVideoConfig(&xcdev,UNITMAP, 0, 0, itsStatep, NULL); 00224 LINFO("set video configure code %d", i); 00225 00226 00227 i = xcdev.setLiveSeqBuf 00228 (&xcdev, UNITMAP, 0, 0, itsStatep, NULL, 1, USEDBUFFER, 1, 0, 1, 0); 00229 if(i != 0) 00230 { 00231 LINFO("start capture error code %d", i); 00232 LFATAL("the imaging board can not work on live mode\n"); 00233 } 00234 00235 // make sure the camera start to work for capture 00236 // get the captured buffer ID 00237 xclib::pxbuffer_t bufferID = 00238 (xclib::pxbuffer_t)xcdev.getLiveStatus(&xcdev, UNITMAP, 0, PXVIST_DONE | PXVIST_BUFFER); 00239 if(bufferID ==0) LINFO("Grab not ready..."); 00240 00241 while( bufferID == 0 ) 00242 { usleep(XCWAIT); 00243 bufferID = (xclib::pxbuffer_t)xcdev.getLiveStatus 00244 (&xcdev, UNITMAP, 0, PXVIST_DONE | PXVIST_BUFFER); 00245 } 00246 00247 const unsigned int bufSz = itsDims.getVal().sz() * (int)ceil(itsBitDepth/8); 00248 itsImgBuf = (byte*)malloc(bufSz); 00249 00250 itsCameraOk = true; 00251 00252 #endif // HAVE_XCLIB 00253 } 00254 00255 // ###################################################################### 00256 void XCgrabberFlex::stop2() 00257 { 00258 #ifndef HAVE_XCLIB 00259 // don't LFATAL() in stop() since it may be called in a destructor chain 00260 LERROR("you must have XC support and the xclib library in order to use XCgrabberFlex"); 00261 #else 00262 if (itsCameraOk) 00263 { 00264 xclib_close(&itsXclib); 00265 itsCameraOk = false; 00266 } 00267 #endif // HAVE_XCLIB 00268 } 00269 00270 // ###################################################################### 00271 XCgrabberFlex::~XCgrabberFlex() 00272 { 00273 #ifdef HAVE_XCLIB 00274 free(itsImgBuf); 00275 #endif 00276 } 00277 00278 // ###################################################################### 00279 void XCgrabberFlex::WhiteBalance() 00280 { 00281 #ifdef HAVE_XCLIB 00282 /* 00283 LINFO("Please put a white board in front of the camera then press any key"); 00284 Raster::waitForKey(); 00285 00286 LINFO("ready for white balance"); 00287 pxd_doSnap(UNITMAP, 1, 0); 00288 uint reference[3] = {0,0,0}; 00289 uint target[3] = {0,0,0}; 00290 00291 if(0 != pxd_setImageBrightBalance(1,reference,target, 0.0)) 00292 LFATAL("can not initial the bright balance"); 00293 00294 double masses[] = {0, 0, 0}; 00295 int sz = 99; 00296 ushort* pixels = (ushort*)malloc(sz*sz*sizeof(ushort)); 00297 int midx, midy, i; 00298 00299 midx = pxd_imageXdim()/2; 00300 midy = pxd_imageYdim()/2; 00301 pxd_readushort(UNITMAP,1,midx-sz/2,midy-sz/2, 00302 midx+1+sz/2,midy+1+sz/2,pixels,sz*sz,(char*)"RofRGB"); 00303 for (i = 0; i < sz*sz; i++) 00304 masses[0] += pixels[i]; 00305 pxd_readushort(UNITMAP,1,midx-sz/2,midy-sz/2, 00306 midx+1+sz/2,midy+1+sz/2,pixels,sz*sz,(char*)"GofRGB"); 00307 for (i = 0; i < sz*sz; i++) 00308 masses[1] += pixels[i]; 00309 pxd_readushort(UNITMAP,1,midx-sz/2,midy-sz/2, 00310 midx+1+sz/2,midy+1+sz/2,pixels,sz*sz,(char*)"BofRGB"); 00311 for (i = 0; i < sz*sz; i++) 00312 masses[2] += pixels[i]; 00313 reference[0] = masses[0]/(sz*sz); 00314 reference[1] = masses[1]/(sz*sz); 00315 reference[2] = masses[2]/(sz*sz); 00316 target[0] = target[1] = target[2] 00317 = std::max(std::max(reference[0], reference[1]), reference[2]); 00318 00319 if(0 != pxd_setImageBrightBalance(UNITMAP, reference, target, 0.60)) 00320 LFATAL("can not do the bright balance"); 00321 LINFO("white balance finished"); 00322 00323 free(pixels); 00324 */ 00325 00326 #endif 00327 } 00328 00329 // ###################################################################### 00330 GenericFrameSpec XCgrabberFlex::peekFrameSpec() 00331 { 00332 GenericFrameSpec result; 00333 00334 result.nativeType = GenericFrame::VIDEO; 00335 result.videoFormat = itsGrabMode.getVal(); 00336 result.videoByteSwap = itsByteSwap.getVal(); 00337 result.dims = itsDims.getVal(); 00338 result.floatFlags = 0; 00339 00340 return result; 00341 } 00342 00343 // ###################################################################### 00344 SimTime XCgrabberFlex::getNaturalFrameTime() const 00345 { 00346 return SimTime::HERTZ(itsFPS.getVal()); 00347 } 00348 00349 00350 00351 // ###################################################################### 00352 GenericFrame XCgrabberFlex::readFrame() 00353 { 00354 return GenericFrame(this->grabRaw()); 00355 } 00356 00357 // ###################################################################### 00358 VideoFrame XCgrabberFlex::grabRaw() 00359 { 00360 #ifndef HAVE_XCLIB 00361 LFATAL("you must have XC support and the xclib library in order to use XCgrabberFlex"); 00362 return VideoFrame(); /* can't happen */ 00363 #else 00364 ASSERT(itsCameraOk); 00365 int i = 0; 00366 00367 struct xclib::xcdevservice xcdev = itsXclib.xcdev; 00368 struct xclib::pxlibservice pxlib = itsXclib.pxlib; 00369 00370 // get the captured buffer ID 00371 xclib::pxbuffer_t bufferID = (xclib::pxbuffer_t)xcdev.getLiveStatus 00372 (&xcdev, UNITMAP, 0, PXVIST_DONE | PXVIST_BUFFER); 00373 00374 while( bufferID == itsLastBuf) 00375 { 00376 bufferID = (xclib::pxbuffer_t)xcdev.getLiveStatus 00377 (&xcdev, UNITMAP, 0, PXVIST_DONE | PXVIST_BUFFER); 00378 usleep(100); 00379 } 00380 if(itsLastBuf != 0 && bufferID != (itsLastBuf)%USEDBUFFER + 1) 00381 { 00382 LINFO("last buf id= %4d, curr buf id= %4d",(int)itsLastBuf,(int)bufferID); 00383 LERROR("buffer error: buffer mis order"); 00384 } 00385 00386 pthread_mutex_lock(&qmutex_buf); 00387 itsLastBuf = bufferID; 00388 pthread_mutex_unlock(&qmutex_buf); 00389 00390 // is the captured image base on byte or uint16 type 00391 int dataMode = (itsBitDepth == 8 ? PXDATUINT8:PXDATUINT16); 00392 00393 const unsigned int bufSz = itsDims.getVal().sz() * (int)ceil(itsBitDepth/8); 00394 const unsigned int imgSz = itsDims.getVal().sz(); 00395 00396 //! define the image from frame buffer 00397 struct xclib::pximage pximg; 00398 00399 i = pxlib.initPximage(&pxlib, UNITMAP, 00400 &pximg, 1, PXHINTBAYER, 0, itsStateid, bufferID, 0); 00401 00402 pximg.wind.nw.x = 1920/2 - itsDims.getVal().w()/2; 00403 pximg.wind.nw.y = 1080/2 - itsDims.getVal().h()/2; 00404 pximg.wind.se.x = 1920/2 + itsDims.getVal().w()/2; 00405 pximg.wind.se.y = 1080/2 + itsDims.getVal().h()/2; 00406 00407 LINFO("pximgsize %d,%d", pximg.wind.nw.x,pximg.wind.se.x); 00408 00409 if (i<1) 00410 LFATAL("error, can not define a pximage, code: %d",i); 00411 00412 00413 if(pximg.ioset(&pximg, PXRXSCAN | PXIWRAP, dataMode, 0x01) < 0) 00414 { 00415 LFATAL("error in ioset, can not set frame buffer read"); 00416 return VideoFrame(); 00417 } 00418 00419 if(imgSz != pximg.ioread(&pximg, PXRXSCAN | PXIWRAP, itsImgBuf,bufSz,0,0)) 00420 { 00421 LFATAL("error in reading frame buffer(size error)," 00422 "expected size = %d", imgSz); 00423 return VideoFrame(); 00424 } 00425 return VideoFrame(itsImgBuf, bufSz, itsDims.getVal(), 00426 itsGrabMode.getVal(), itsByteSwap.getVal(), false); 00427 00428 #endif // HAVE_XCLIB 00429 } 00430 00431 // ###################################################################### 00432 void XCgrabberFlex::paramChanged(ModelParamBase* const param, 00433 const bool valueChanged, 00434 ParamClient::ChangeStatus* status) 00435 { 00436 #ifndef HAVE_XCLIB 00437 LFATAL("you must have XC support and the xclib library in order to use XCgrabberFlex"); 00438 #else 00439 FrameIstream::paramChanged(param, valueChanged, status); 00440 #endif // HAVE_XCLIB 00441 } 00442 00443 // ###################################################################### 00444 #ifdef HAVE_XCLIB 00445 xclib::pxbuffer_t XCgrabberFlex::getCurrBufID() 00446 { 00447 xclib::pxbuffer_t tmp; 00448 pthread_mutex_lock(&qmutex_buf); 00449 tmp = itsLastBuf; 00450 pthread_mutex_unlock(&qmutex_buf); 00451 return tmp; 00452 } 00453 #endif 00454 00455 // ###################################################################### 00456 /* So things look consistent in everyone's emacs... */ 00457 /* Local Variables: */ 00458 /* indent-tabs-mode: nil */ 00459 /* End: */ 00460