/******************************************************************** ** Image Component Library (ICL) ** ** ** ** Copyright (C) 2006-2012 CITEC, University of Bielefeld ** ** Neuroinformatics Group ** ** Website: www.iclcv.org and ** ** http://opensource.cit-ec.de/projects/icl ** ** ** ** File : ICLIO/src/GenericGrabber.cpp ** ** Module : ICLIO ** ** Authors: Christof Elbrechter ** ** ** ** ** ** Commercial License ** ** ICL can be used commercially, please refer to our website ** ** www.iclcv.org for more details. ** ** ** ** GNU General Public License Usage ** ** Alternatively, this file may be used under the terms of the ** ** GNU General Public License version 3.0 as published by the ** ** Free Software Foundation and appearing in the file LICENSE.GPL ** ** included in the packaging of this file. Please review the ** ** following information to ensure the GNU General Public License ** ** version 3.0 requirements will be met: ** ** http://www.gnu.org/copyleft/gpl.html. ** ** ** ** The development of this software was supported by the ** ** Excellence Cluster EXC 277 Cognitive Interaction Technology. ** ** The Excellence Cluster EXC 277 is a grant of the Deutsche ** ** Forschungsgemeinschaft (DFG) in the context of the German ** ** Excellence Initiative. ** ** ** *********************************************************************/ #include #include #include #include #include #ifdef ICL_SYSTEM_LINUX #ifdef HAVE_VIDEODEV #include #include #endif #ifdef HAVE_VIDEODEV #include #endif #endif #ifdef HAVE_LIBDC #include #endif #ifdef HAVE_UNICAP #include #endif #ifdef HAVE_XCF #include #include #include #endif #ifdef HAVE_LIBMESASR #include #endif #ifdef HAVE_MV #include #endif #ifdef HAVE_XINE #include #endif #ifdef HAVE_OPENCV #include #include #endif #ifdef HAVE_QT #include #endif #ifdef HAVE_LIBFREENECT #include #endif #ifdef HAVE_PYLON #include #endif #include #include #include #if defined(HAVE_RSB) && defined(HAVE_PROTOBUF) #include #endif namespace icl{ static std::vector deviceList; GenericGrabber::GenericGrabber(const std::string &desiredAPIOrder, const std::string ¶ms, bool notifyErrors) throw(ICLException):m_poGrabber(0){ init(desiredAPIOrder,params,notifyErrors); } GenericGrabber::GenericGrabber(const ProgArg &pa) throw (ICLException):m_poGrabber(0){ init(pa); } void GenericGrabber::init(const ProgArg &pa) throw (ICLException){ init(*pa,(*pa) + "=" + *icl::pa(pa.getID(),1)); } struct SpecifiedDevice{ std::string type; std::string id; std::vector options; }; static std::pair split_at_first(char c, const std::string &s){ size_t pAt = s.find(c); if(pAt != std::string::npos){ return std::pair(s.substr(0,pAt), s.substr(pAt)); }else{ return std::pair(s,""); } } typedef std::map ParamMap; static ParamMap create_param_map(const std::string &filter){ std::vector ts = tok(filter,","); ParamMap pmap; static const char *plugins[] = { "pwc","dc","dc800","unicap","file","demo","create", "xcfp","xcfs","xcfm","mv","sr","xine","cvvideo", "cvcam","sm","myr","kinectd","kinectc","kinecti", "pylon","rsb"}; static const int NUM_PLUGINS=sizeof(plugins)/sizeof(char*); for(unsigned int i=0;i tsi = split_at_first('@',ts[i]); std::vector ab = tok(tsi.first,"="); //SHOW(ab[0]); //if(ab.size() > 1) SHOW(ab[1]); unsigned int S = ab.size(); switch(S){ case 1: case 2: if(std::find(plugins, plugins+NUM_PLUGINS, ab[0])){ //std::pair p = S==2 ? split_options(ab[1]) : std::pair("",""); SpecifiedDevice s = { ab[0], (S==2 ? ab[1] : std::string("")), tok(tsi.second,"@") }; pmap[ab[0]] = s; //DEBUG_LOG("setting pmap[" << ab[0] << "] to '" << (pmap[ab[0]])<< '\''); }else{ ERROR_LOG("GenericGrabber: unsupported device: ["<< ab[0] << "] (skipping)"); } break; default: ERROR_LOG("GenericGrabber: invalid device filter token: [" << ts[i] << "] (skipping)"); } } return pmap; } #if HAVE_UNICAP static bool is_int(const std::string &x){ int i = parse(x); return i>0 || x=="0"; } #endif void GenericGrabber::init(const std::string &desiredAPIOrder, const std::string ¶ms, bool notifyErrors) throw(ICLException){ Mutex::Locker __lock(m_mutex); ICL_DELETE(m_poGrabber); m_sType = ""; ParamMap pmap = create_param_map(params); std::string errStr; #define ADD_ERR(P) errStr += errStr.size() ? std::string(",") : ""; \ errStr += std::string(P)+"("+pmap[P].id+")" std::vector l = tok(desiredAPIOrder,","); for(unsigned int i=0;i supportedDevices; #ifdef HAVE_LIBFREENECT if(createListOnly){ supportedDevices.push_back("kinectd:device ID:kinect depth camera source:"); supportedDevices.push_back("kinectc:device ID:kinect color camera source"); supportedDevices.push_back("kinecti:devide ID:kinect IR camera source"); } if(l[i] == "kinectd" || l[i] == "kinectc" || l[i] == "kinecti"){ KinectGrabber::Mode mode; switch(l[i][6]){ case 'd': mode = KinectGrabber::GRAB_DEPTH_IMAGE; break; case 'c': mode = KinectGrabber::GRAB_RGB_IMAGE; break; case 'i': mode = KinectGrabber::GRAB_IR_IMAGE_8BIT; break; default: break; } try{ // new KinectGrabber *kin = new KinectGrabber(format,to32s(pmap[l[i]])); KinectGrabber *kin = new KinectGrabber(mode,to32s(pmap[l[i]].id)); m_poGrabber = kin; m_sType = l[i]; break; }catch(...){ ADD_ERR(l[i]); continue; } } #endif #ifdef HAVE_VIDEODEV if(createListOnly){ supportedDevices.push_back("pwc:/dev/videoX index:Phillip 640 Webcam source"); supportedDevices.push_back("myr:/dev/videoX index:Myrmex tactile device source"); supportedDevices.push_back("v4l2:/dev/videoX index or device-file:V4l2 based camera source"); } if(l[i] == "pwc"){ PWCGrabber *pwc = new PWCGrabber; if(pwc->init(Size(640,480),24,to32s(pmap["pwc"].id),true)){ m_poGrabber = pwc; m_sType = "pwc"; break; }else{ ADD_ERR("pwc"); delete pwc; continue; } } if(l[i] == "myr"){ try{ MyrmexGrabber *myr = new MyrmexGrabber(parse(pmap["myr"].id)); m_poGrabber = myr; m_sType = "myr"; break; }catch(ICLException &ex){ ADD_ERR("myr [error message:" + str(ex.what()) + "]"); continue; } } if(l[i] == "v4l2"){ try{ V4L2Grabber *g = new V4L2Grabber(pmap["v4l2"].id); m_poGrabber = g; m_sType = "v4l2"; break; }catch(ICLException &ex){ ADD_ERR("v4l2 [error message:" + str(ex.what()) + "]"); continue; } } #endif #ifdef HAVE_LIBDC if(createListOnly){ supportedDevices.push_back("dc:camera ID or unique ID:IEEE-1394a based camera source (FireWire 400)"); supportedDevices.push_back("dc:camera ID or unique ID:IEEE-1394b based camera source (FireWire 800)"); } if(l[i] == "dc" || l[i] == "dc800"){ std::vector devs = DCGrabber::getDCDeviceList(false); // int idx = (l[i]=="dc") ? to32s(pmap["dc"]) : to32s(pmap["dc800"]); std::string d = (l[i]=="dc") ? pmap["dc"].id : pmap["dc800"].id; if(!d.length()) throw ICLException("GenericGrabber::init: got dc[800] with empty sub-arg!"); std::vector ts = tok(d,"|||",false); if(ts.size() > 1){ // we take the first one here, because usually no one defines both ... d = ts[0]; } int index = -1; std::string uniqueID; if(d.size() < 4){ //"0-999" -> very short string -> this is an index then index = to32s(d); }else{ //"something very long" -> this is a unique ID then uniqueID = d; } if(index < 0){ for(unsigned int j=0;j= (int)devs.size()){ if(l[i]=="dc"){ ADD_ERR("dc"); }else{ ADD_ERR("dc800"); } continue; }else{ m_poGrabber = new DCGrabber(devs[index], l[i]=="dc"?400:800); m_sType = l[i]; break; } } } #endif #ifdef HAVE_LIBMESASR if(createListOnly){ supportedDevices.push_back("sr:device Index or -1 for auto select:Mesa Imaging SwissRanger depth camera source"); } if(l[i] == "sr"){ std::vector srts = tok(pmap["sr"].id,"c"); int device = 0; int channel = -1; m_sType = "sr"; if(srts.size() > 1){ device = to32s(srts[0]); channel = to32s(srts[1]); }else{ device = to32s(srts[0]); } try{ m_poGrabber = new SwissRangerGrabber(device,depth32f,channel); }catch(ICLException &e){ ADD_ERR("sr"); errStr += "[error message: " + str(e.what()) + "]"; continue; } break; } #endif #ifdef HAVE_XINE if(createListOnly){ supportedDevices.push_back("xine:video filename:Xine library based video file source"); } if(l[i] == "xine"){ try{ m_poGrabber = new VideoGrabber(pmap["xine"].id); m_sType = "xine"; }catch(ICLException &e){ ADD_ERR("xine"); continue; } break; } #endif #ifdef HAVE_UNICAP if(createListOnly){ supportedDevices.push_back("unicap:camera ID or pattern:Unicap library based camera source"); } if(l[i] == "unicap"){ std::vector devs; if(is_int(pmap["unicap"].id)){ devs = UnicapGrabber::getUnicapDeviceList(""); int idx = parse(pmap["unicap"].id); if((int)devs.size() > idx){ m_poGrabber = new UnicapGrabber(devs[idx]); m_sType = "unicap"; break; }else{ ADD_ERR("unicap"); continue; } }else{ devs = UnicapGrabber::getUnicapDeviceList(pmap["unicap"].id); if(!devs.size()){ ADD_ERR("unicap"); continue; }else{ m_poGrabber = new UnicapGrabber(devs[0]); m_sType = "unicap"; break; } } } #endif #ifdef HAVE_XCF if(createListOnly){ supportedDevices.push_back("xcfs:xcf server stream name:XCF-based server network source"); supportedDevices.push_back("xcfp:xcf publisher stream name:XCF-based publisher network source"); supportedDevices.push_back("xcfm:xcf Active-Memory name:XCF-based ActiveMemory network source"); } if(l[i].size()==4 && l[i].substr(0,3) == "xcf"){ switch(l[i][3]){ case 's': try{ m_poGrabber = new XCFServerGrabber(pmap["xcfs"].id); }catch(...){ if(notifyErrors){ m_poGrabber = 0; ADD_ERR("xcfs"); } } break; case 'p': try{ m_poGrabber = new XCFPublisherGrabber(pmap["xcfp"].id); }catch(...){ if(notifyErrors){ m_poGrabber = 0; ADD_ERR("xcfp"); } } break; case 'm': try{ m_poGrabber = new XCFMemoryGrabber(pmap["xcfm"].id); }catch(...){ if(notifyErrors){ m_poGrabber = 0; ADD_ERR("xcfm"); } } break; default: break; } if(m_poGrabber){ m_sType = l[i]; break; }else{ continue; } } #endif #ifdef HAVE_MV if(createListOnly){ supportedDevices.push_back("mv:camera ID:MatrixVision driver based camera source"); } // not yet supported, and maybe, already replaced by pylon grabber? if(l[i] == "mv") { std::vector devs = MVGrabber::getDeviceList(); if(!devs.size()) { ADD_ERR("mv"); continue; } else { m_poGrabber = new MVGrabber(pmap["mv"].id); m_sType = "mv"; break; } } #endif #ifdef HAVE_OPENCV if(createListOnly){ supportedDevices.push_back("cvvideo:video filename:OpenCV based video file source"); supportedDevices.push_back("cvcam:camera ID:OpenCV based camera source"); } if(l[i] == "cvvideo") { try{ m_poGrabber = new OpenCVVideoGrabber(pmap["cvvideo"].id); m_sType = "cvvideo"; break; }catch(ICLException &e){ ADD_ERR("cvvideo"); continue; } } if(l[i] == "cvcam") { try{ m_poGrabber = new OpenCVCamGrabber(to32s(pmap["cvcam"].id)); m_sType = "cvcam"; break; }catch(ICLException &e){ ADD_ERR("cvcam"); continue; } } #endif #ifdef HAVE_QT if(createListOnly){ supportedDevices.push_back("sm:shared memory segment name:Qt-based shared memory source"); } if(l[i] == "sm") { try{ m_poGrabber = new SharedMemoryGrabber(pmap["sm"].id); m_sType = "sm"; break; }catch(ICLException &e){ ADD_ERR("sm"); continue; } } #endif #ifdef HAVE_PYLON if(createListOnly){ supportedDevices.push_back("pylon:camera ID ?? or IP-address:Basler Pylon based gigabit-ethernet (GIG-E) camera source"); } if(l[i] == "pylon"){ if (pmap["pylon"].id == "-help"){ pylon::PylonGrabber::printHelp(); ADD_ERR("pylon"); continue; } try{ m_poGrabber = new pylon::PylonGrabber(pmap["pylon"].id); m_sType = "pylon"; break; } catch (ICLException &e){ ADD_ERR("pylon"); continue; } } #endif #if defined(HAVE_RSB) && defined(HAVE_PROTOBUF) if(createListOnly){ supportedDevices.push_back("rsb:[comma sep. transport list=spread]\\:scope:Robotics Service Bus based image source"); } if(l[i] == "rsb"){ try{ std::vector ts = tok(pmap["rsb"].id,":"); if(!ts.size()) throw ICLException("invalid argument count (expected 1 or 2)"); else if(ts.size() == 1) m_poGrabber = new RSBGrabber(ts[0]); else if(ts.size() == 2){ m_poGrabber = new RSBGrabber(ts[1],ts[0]); }else{ throw ICLException("invalid definition string (exptected: [transport-list]:scope"); } m_sType = "rsb"; break; }catch(std::exception &e){ ADD_ERR("rsb"); continue; } } #endif if(createListOnly){ supportedDevices.push_back("file:file name or file-pattern (in ''):image source for single or a list of image files"); supportedDevices.push_back("demo:0:demo image source"); supportedDevices.push_back("create:parrot|lena|cameraman|mandril:everywhere available test images source"); } if(l[i] == "file"){ try{ if(FileList(pmap["file"].id).size()){ m_sType = "file"; m_poGrabber = new FileGrabber(pmap["file"].id); break; }else{ ADD_ERR("file"); continue; } }catch(icl::FileNotFoundException &ex){ ADD_ERR("file"); continue; } } if(l[i] == "demo"){ m_poGrabber = new DemoGrabber(to32f(pmap["demo"].id)); m_sType = "demo"; } if(l[i] == "create"){ m_poGrabber = new CreateGrabber(pmap["create"].id); m_sType = "create"; } if(createListOnly){ std::cout << "the following generic grabber plugins are available:" << std::endl; TextTable t(4,supportedDevices.size()+1,80); t[0] = tok("index,ID,parameter,description",","); for(size_t k=0;k &options = pmap[m_sType].options; /// setting extra properties ... for(unsigned int i=0;i p = split_at_first('=',options[i]); if(p.second.length()) p.second = p.second.substr(1); if(p.first == "load"){ m_poGrabber->loadProperties(p.second); }else if(p.first == "info"){ std::cout << "Property list for " << d << std::endl; std::vector ps = m_poGrabber->getPropertyList(); TextTable t(4,ps.size()+1,35); t[0] = tok("property,type,allowed values,current value",","); for(unsigned int j=0;jgetType(p2); const bool isCommand = ty == "command"; const bool isInfo = ty == "info"; t(0,j+1) = p2; t(1,j+1) = ty; t(2,j+1) = (isInfo||isCommand) ? str("-") : m_poGrabber->getInfo(p2); t(3,j+1) = isCommand ? "-" : m_poGrabber->getValue(p2); } std::cout << t << std::endl; std::terminate(); }else if(p.first == "udist"){ this->enableUndistortion(p.second); }else{ // DEBUG_LOG("setting property -" << p.first << "- to value -" << p.second << "-"); m_poGrabber->setProperty(p.first,p.second); } } } } void GenericGrabber::resetBus(const std::string &deviceList, bool verbose){ std::vector ts = tok(deviceList,","); for(unsigned int i=0;i static inline bool contains(const std::map &m,const std::string &t){ return m.find(t) != m.end(); } static const GrabberDeviceDescription *find_description(const std::vector &ds, const std::string &id){ for(unsigned int i=0;i ts = tok(ds[i].id,"|||",false); if(std::find(ts.begin(),ts.end(),id) != ts.end()){ return &ds[i]; } } return 0; } #ifdef HAVE_LIBFREENECT static const GrabberDeviceDescription *find_description_2(const std::vector &ds, const std::string &id, const std::string &type){ for(unsigned int i=0;i ts = tok(ds[i].id,"|||",false); if(std::find(ts.begin(),ts.end(),id) != ts.end()){ return &ds[i]; } } return 0; } #endif template static void add_devices(std::vector &all, const std::string &dev, bool useFilter, ParamMap &pmap){ if(!useFilter || contains(pmap,dev)){ std::vector ds = T::getDeviceList(true); if(dev.length() >= 2 && dev[0] == 'd' && dev[1] == 'c'){ // dirty hack for dc devices bool kick800 = dev.length()==2; std::vector newds; for(unsigned int i=0;i void add_devices(std::vector &all, const std::string &dev, bool useFilter, ParamMap &pmap){ if(!useFilter || contains(pmap,"kinectd") || contains(pmap,"kinectc") || contains(pmap,"kinecti")){ std::vector ds = KinectGrabber::getDeviceList(true); if(useFilter && (pmap["kinectd"].id.length() || pmap["kinectc"].id.length() || pmap["kinecti"].id.length())){ if(pmap["kinectd"].id.length()){ const GrabberDeviceDescription *d = find_description_2(ds,pmap["kinectd"].id,"kinectd"); if(d){ all.push_back(*d); } } if(pmap["kinectc"].id.length()){ const GrabberDeviceDescription *d = find_description_2(ds,pmap["kinectc"].id,"kinectc"); if(d){ all.push_back(*d); } } if(pmap["kinecti"].id.length()){ const GrabberDeviceDescription *d = find_description_2(ds,pmap["kinecti"].id,"kinecti"); if(d){ all.push_back(*d); } } }else{ std::copy(ds.begin(),ds.end(),std::back_inserter(all)); } } } #endif const std::vector &GenericGrabber::getDeviceList(const std::string &filter, bool rescan){ if(rescan){ deviceList.clear(); bool useFilter = filter.length(); ParamMap pmap; if(useFilter){ pmap = create_param_map(filter); } if(useFilter && pmap.find("demo") != pmap.end()){ deviceList.push_back(GrabberDeviceDescription("demo","0","Demo Grabber Device")); } #ifdef HAVE_VIDEODEV add_devices(deviceList,"pwc",useFilter,pmap); add_devices(deviceList,"myr",useFilter,pmap); add_devices(deviceList,"v4l2",useFilter,pmap); #endif #ifdef HAVE_LIBDC add_devices(deviceList,"dc",useFilter,pmap); add_devices(deviceList,"dc800",useFilter,pmap); #endif #ifdef HAVE_UNICAP add_devices(deviceList,"unicap",useFilter,pmap); #endif #ifdef HAVE_LIBMESASR add_devices(deviceList,"sr",useFilter,pmap); #endif #ifdef HAVE_OPENCV add_devices(deviceList,"cvcam",useFilter,pmap); #endif #ifdef HAVE_QT add_devices(deviceList,"sm",useFilter,pmap); #endif #ifdef HAVE_LIBFREENECT add_devices(deviceList,"",useFilter,pmap); #endif #ifdef HAVE_PYLON add_devices(deviceList,"pylon",useFilter,pmap); #endif #if defined(HAVE_RSB) && defined(HAVE_PROTOBUF) add_devices(deviceList,"rsb",useFilter,pmap); #endif } return deviceList; } }