//////////////////////////////////////////////////////// // // GEM - Graphics Environment for Multimedia // // zmoelnig@iem.kug.ac.at // // Implementation file // // Copyright (c) 1997-1998 Mark Danks. // Copyright (c) Günther Geiger. // Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at // For information on usage and redistribution, and for a DISCLAIMER OF ALL // WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution. // ///////////////////////////////////////////////////////// #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "videoDC1394.h" using namespace gem::plugins; #include "Gem/RTE.h" #include "Gem/Exception.h" #include "plugins/PluginFactory.h" #ifdef HAVE_LIBDC1394 #include REGISTER_VIDEOFACTORY("dc1394", videoDC1394); ///////////////////////////////////////////////////////// // // videoDC1394 // ///////////////////////////////////////////////////////// // Constructor // ///////////////////////////////////////////////////////// videoDC1394 :: videoDC1394() : videoBase("dc1394"), m_dccamera(NULL), m_dcframe(NULL), m_dc(NULL) { m_dc = dc1394_new(); /* Initialize libdc1394 */ if(!m_dc) throw(GemException("unable to initialize DC1394")); m_frame.xsize=1600; m_frame.ysize=1200; m_frame.setCsizeByFormat(GL_RGBA); m_frame.allocate(); provide("iidc"); } //////////////////////////////////////////////////////// // Destructor // //////////////////////////////////////////////////////// videoDC1394 :: ~videoDC1394(){ close(); if(m_dccamera)dc1394_camera_free (m_dccamera);m_dccamera=NULL; if(m_dc)dc1394_free(m_dc);m_dc=NULL; } //////////////////////////////////////////////////////// // render // ///////////////////////////////////////////////////////// bool videoDC1394 :: grabFrame() { dc1394video_frame_t*frame, *colframe; dc1394error_t err=dc1394_capture_dequeue(m_dccamera, DC1394_CAPTURE_POLICY_POLL, &frame);/* Capture */ if((DC1394_SUCCESS!=err)||(NULL==frame)) { usleep(10); return true; } /* do something with the frame */ colframe=( dc1394video_frame_t*)calloc(1,sizeof(dc1394video_frame_t)); colframe->color_coding=DC1394_COLOR_CODING_RGB8; dc1394_convert_frames(frame, colframe); m_frame.xsize=frame->size[0]; m_frame.ysize=frame->size[1]; m_frame.setCsizeByFormat(GL_RGBA); m_frame.fromRGB(colframe->image); lock(); m_image.image.convertFrom(&m_frame, m_reqFormat); m_image.newimage=true; m_image.image.upsidedown=true; unlock(); free(colframe->image); free(colframe); /* Release the buffer */ err=dc1394_capture_enqueue(m_dccamera, frame); if(DC1394_SUCCESS!=err) { return false; } return true; } //////////////////////////////////////////////////////// // openDevice // ///////////////////////////////////////////////////////// static std::string guid2string(uint64_t guid, int unit=-1) { std::string result; char buf[64]; uint32_t value[2]; value[0]= guid & 0xffffffff; value[1]= (guid >>32) & 0xffffffff; snprintf(buf, 64, "0x%08x%08x", value[0], value[1]); buf[63]=0; result=buf; if(unit>=0) { snprintf(buf, 64, "%d", unit); buf[63]=0; result+=":"; result+=buf; } return result; } bool videoDC1394 :: openDevice(gem::Properties&props){ dc1394error_t err; dc1394camera_list_t *list=NULL; err=dc1394_camera_enumerate (m_dc, &list); /* Find cameras */ if(DC1394_SUCCESS!=err) { error("videoDC1394: %s: failed to enumerate", dc1394_error_get_string(err)); return false; } if (list->num < 1) { error("videoDC1394: no cameras found"); dc1394_camera_free_list (list); return false; } int devicenum=-1; if(m_devicenum>=0)devicenum=m_devicenum; else if (!m_devicename.empty()) { int i=0; for(i=0; inum; i++) { // find camera based on its GUID std::string name=guid2string(list->ids[i].guid); if(guid2string(list->ids[i].guid)==m_devicename){ devicenum=i; break; } if(guid2string(list->ids[i].guid, list->ids[i].unit)==m_devicename){ devicenum=i; break; } } } if(devicenum<0) { return false; } if (devicenum < list->num) { /* Work with first camera */ m_dccamera = dc1394_camera_new_unit(m_dc, list->ids[devicenum].guid, list->ids[devicenum].unit); } else { m_dccamera=NULL; error("videoDC1394: only found %d cameras but requested #%d!", list->num, devicenum); } dc1394_camera_free_list (list); if(!m_dccamera) { error("videoDC1394: could not access camera!"); return false; } verbose(1, "videoDC1394: using camera with GUID %s", guid2string(m_dccamera->guid, m_dccamera->unit).c_str()); setProperties(props); if(gem::Properties::UNSET==props.type("mode")){ /* check supported video modes */ dc1394video_modes_t video_modes; dc1394video_mode_t video_mode; dc1394color_coding_t coding; err=dc1394_video_get_supported_modes(m_dccamera,&video_modes); if(DC1394_SUCCESS!=err) { error("can't get video modes"); closeDevice(); return false; } int mode=-1; double d; if(props.get("channel", d)) // this used to be 'channel' rather than 'isochannel' mode=d; verbose(1, "trying mode %d", mode); if(mode>=0) { if(mode>=video_modes.num) { error("requested channel %d/%d out of bounds", mode, video_modes.num); mode=-1; } } int i; for (i=video_modes.num-1;i>=0;i--) { unsigned int w=0, h=0; if(DC1394_SUCCESS==dc1394_get_image_size_from_video_mode(m_dccamera, video_modes.modes[i], &w, &h)) { verbose(1, "videomode[%02d/%d]=%dx%d", i, video_modes.num, w, h); } else verbose(1, "videomode %d refused dimen: %d", i, video_modes.modes[i]); dc1394_get_color_coding_from_video_mode(m_dccamera,video_modes.modes[i], &coding); dc1394bool_t iscolor=DC1394_FALSE; if(DC1394_SUCCESS==dc1394_is_color(coding, &iscolor)) { verbose(1, "videomode[%02d/%d] %d is%scolor", i, video_modes.num, coding, (iscolor?" ":" NOT ")); } if(mode<0) { // find a mode matching the user's needs if(m_width==w && m_height==h) { // what about color? mode=i; break; } } } if(mode<0) { // select highest res mode: for (i=video_modes.num-1;i>=0;i--) { if (!dc1394_is_video_mode_scalable(video_modes.modes[i])) { dc1394_get_color_coding_from_video_mode(m_dccamera,video_modes.modes[i], &coding); video_mode=video_modes.modes[i]; break; } } if (i < 0) { error("Could not get a valid mode"); closeDevice(); return false; } } else { verbose(1, "using mode %d", mode); video_mode=video_modes.modes[mode]; } if(1) { unsigned int w=0, h=0; if(DC1394_SUCCESS==dc1394_get_image_size_from_video_mode(m_dccamera, video_mode, &w, &h)) { verbose(1, "videomode[%d]=%dx%d", video_mode, w, h); } dc1394_get_color_coding_from_video_mode(m_dccamera,video_mode, &coding); dc1394bool_t iscolor=DC1394_FALSE; if(DC1394_SUCCESS==dc1394_is_color(coding, &iscolor)) { verbose(1, "videomode %d is%scolor", coding, (iscolor?" ":" NOT ")); } } err=dc1394_video_set_mode(m_dccamera, video_mode); if(DC1394_SUCCESS!=err) { error("unable to set specified mode, using default"); } } if(gem::Properties::UNSET==props.type("operationmode")){ // try to set highest possible operation mode // FIXME this should be done via properties int operation_mode=DC1394_OPERATION_MODE_MAX; while(operation_mode>=DC1394_OPERATION_MODE_MIN) { err=dc1394_video_set_operation_mode(m_dccamera, (dc1394operation_mode_t)operation_mode); if(DC1394_SUCCESS==err) break; verbose(1, "failed to set operation mode to %d", operation_mode); operation_mode--; } if(DC1394_SUCCESS!=err) { error("unable to set operation mode...continuing anyhow"); } } if(gem::Properties::UNSET==props.type("speed")){ // FIXME this should be done via properties dc1394speed_t orgspeed; dc1394_video_get_iso_speed(m_dccamera, &orgspeed); int speed=DC1394_ISO_SPEED_MAX; while(speed>=DC1394_ISO_SPEED_MIN) { err=dc1394_video_set_iso_speed(m_dccamera, (dc1394speed_t)speed); if(DC1394_SUCCESS==err) break; verbose(1, "failed to set ISO speed to %d", 100*(1<videoDC1394 :: enumerate(){ std::vectorresult; dc1394camera_list_t *list=NULL; dc1394error_t err=dc1394_camera_enumerate (m_dc, &list); /* Find cameras */ if(DC1394_SUCCESS!=err) { return result; } int i=0; for(i=0; inum; i++) { // post("IIDC#%02d: %"PRIx64"\t%x\t%s", i, list->ids[i].guid, list->ids[i].unit, buf); result.push_back(guid2string(list->ids[i].guid, list->ids[i].unit)); } return result; } bool videoDC1394 :: setColor(int format){ if (format<=0)return false; m_reqFormat=format; return true; } bool videoDC1394::enumProperties(gem::Properties&readable, gem::Properties&writeable) { /* framerate mode operationmode isospeed isochannel transmission oneshot multishot */ gem::any type; std::string key; readable.clear(); writeable.clear(); key="framerate"; type=0; readable .set(key, type); writeable.set(key, type); key="mode"; type=std::string(""); readable .set(key, type); writeable.set(key, type); key="operationmode"; type=std::string(""); readable .set(key, type); writeable.set(key, type); key="speed"; type=0; readable .set(key, type); writeable.set(key, type); key="channel"; type=0; readable .set(key, type); writeable.set(key, type); key="transmission"; type=0; readable .set(key, type); writeable.set(key, type); key="oneshot"; type=0; readable .set(key, type); writeable.set(key, type); key="multishot"; type=0; readable .set(key, type); writeable.set(key, type); dc1394featureset_t feature_set; dc1394error_t err; err = dc1394_feature_get_all(m_dccamera, &feature_set); dc1394bool_t is_readable; if ( err ) return false; for ( int i = 0 ; i < DC1394_FEATURE_NUM ; i++ ) { if ( feature_set.feature[i].available ) { // TODO remove space in feature name (eg. "Trigger Delay") key = dc1394_feature_get_string(feature_set.feature[i].id); type=0; // what is this ? dc1394_feature_is_readable(m_dccamera, feature_set.feature[i].id, &is_readable ); if ( is_readable ) readable.set(key,type); writeable.set(key,type); } } return true; } void videoDC1394::getProperties(gem::Properties&props) { if(!m_dccamera)return; std::vectorkeys=props.keys(); double value; std::string svalue; int i=0; for(i=0; ikeys=props.keys(); double value; std::string svalue; int i=0; for(i=0; i>=1) r=r+1; if(r>DC1394_FRAMERATE_MAX)r=DC1394_FRAMERATE_MAX; dc1394framerate_t rate=(dc1394framerate_t)r; err=dc1394_video_set_framerate(m_dccamera, rate); } } else if("mode" == key) { dc1394video_mode_t mode; if(props.get(key, svalue)) { if("160x120_YUV444"==svalue) { mode=DC1394_VIDEO_MODE_160x120_YUV444; } else if("320x240_YUV422"==svalue) { mode=DC1394_VIDEO_MODE_320x240_YUV422; } else if("640x480_YUV411"==svalue) { mode=DC1394_VIDEO_MODE_640x480_YUV411; } else if("640x480_YUV422"==svalue) { mode=DC1394_VIDEO_MODE_640x480_YUV422; } else if("640x480_RGB8"==svalue) { mode=DC1394_VIDEO_MODE_640x480_RGB8; } else if("640x480_MONO8"==svalue) { mode=DC1394_VIDEO_MODE_640x480_MONO8; } else if("640x480_MONO16"==svalue) { mode=DC1394_VIDEO_MODE_640x480_MONO16; } else if("800x600_YUV422"==svalue) { mode=DC1394_VIDEO_MODE_800x600_YUV422; } else if("800x600_RGB8"==svalue) { mode=DC1394_VIDEO_MODE_800x600_RGB8; } else if("800x600_MONO8"==svalue) { mode=DC1394_VIDEO_MODE_800x600_MONO8; } else if("1024x768_YUV422"==svalue) { mode=DC1394_VIDEO_MODE_1024x768_YUV422; } else if("1024x768_RGB8"==svalue) { mode=DC1394_VIDEO_MODE_1024x768_RGB8; } else if("1024x768_MONO8"==svalue) { mode=DC1394_VIDEO_MODE_1024x768_MONO8; } else if("800x600_MONO16"==svalue) { mode=DC1394_VIDEO_MODE_800x600_MONO16; } else if("1024x768_MONO16"==svalue) { mode=DC1394_VIDEO_MODE_1024x768_MONO16; } else if("1280x960_YUV422"==svalue) { mode=DC1394_VIDEO_MODE_1280x960_YUV422; } else if("1280x960_RGB8"==svalue) { mode=DC1394_VIDEO_MODE_1280x960_RGB8; } else if("1280x960_MONO8"==svalue) { mode=DC1394_VIDEO_MODE_1280x960_MONO8; } else if("1600x1200_YUV422"==svalue) { mode=DC1394_VIDEO_MODE_1600x1200_YUV422; } else if("1600x1200_RGB8"==svalue) { mode=DC1394_VIDEO_MODE_1600x1200_RGB8; } else if("1600x1200_MONO8"==svalue) { mode=DC1394_VIDEO_MODE_1600x1200_MONO8; } else if("1280x960_MONO16"==svalue) { mode=DC1394_VIDEO_MODE_1280x960_MONO16; } else if("1600x1200_MONO16"==svalue) { mode=DC1394_VIDEO_MODE_1600x1200_MONO16; } else if("EXIF"==svalue) { mode=DC1394_VIDEO_MODE_EXIF; } else if("FORMAT7_0"==svalue) { mode=DC1394_VIDEO_MODE_FORMAT7_0; } else if("FORMAT7_1"==svalue) { mode=DC1394_VIDEO_MODE_FORMAT7_1; } else if("FORMAT7_2"==svalue) { mode=DC1394_VIDEO_MODE_FORMAT7_2; } else if("FORMAT7_3"==svalue) { mode=DC1394_VIDEO_MODE_FORMAT7_3; } else if("FORMAT7_4"==svalue) { mode=DC1394_VIDEO_MODE_FORMAT7_4; } else if("FORMAT7_5"==svalue) { mode=DC1394_VIDEO_MODE_FORMAT7_5; } else if("FORMAT7_6"==svalue) { mode=DC1394_VIDEO_MODE_FORMAT7_6; } else if("FORMAT7_7"==svalue) { mode=DC1394_VIDEO_MODE_FORMAT7_7; } else continue; } else if (props.get(key, value)) { int m=value; if(mDC1394_VIDEO_MODE_MAX) continue; mode=(dc1394video_mode_t)m; } else continue; err=dc1394_video_set_mode(m_dccamera, mode); } else if("operationmode" == key) { dc1394operation_mode_t mode; if(props.get(key, svalue)) { if("1394a"==svalue || "1394A"==svalue || "legacy"==svalue) mode=DC1394_OPERATION_MODE_LEGACY; else if("1394b"==svalue || "1394B"==svalue) mode=DC1394_OPERATION_MODE_1394B; else continue; } else if (props.get(key, value)) { if(value<=480) mode=DC1394_OPERATION_MODE_LEGACY; else mode=DC1394_OPERATION_MODE_1394B; } else continue; err=dc1394_video_set_operation_mode(m_dccamera, mode); } else if("speed" == key) { dc1394speed_t speed=DC1394_ISO_SPEED_MIN; if (props.get(key, value) && value>0) { int s; for(s=DC1394_ISO_SPEED_MIN; s=(100*(1<=0) { uint32_t channel=value; err=dc1394_video_set_iso_channel(m_dccamera, channel); } } else if("transmission" == key) { if (props.get(key, value)) { bool b=value; dc1394switch_t pwr=(b?DC1394_ON:DC1394_OFF); err=dc1394_video_set_transmission(m_dccamera, pwr); } } else if("oneshot" == key) { if (props.get(key, value)) { bool b=value; dc1394switch_t pwr=(b?DC1394_ON:DC1394_OFF); err=dc1394_video_set_one_shot(m_dccamera, pwr); } } else if("multishot" == key) { if (props.get(key, value)) { dc1394switch_t pwr=DC1394_OFF; uint32_t numFrames=0; if(value>0) { pwr=DC1394_ON; numFrames=value; } err=dc1394_video_set_multi_shot(m_dccamera, numFrames, pwr); } } else { dc1394featureset_t feature_set; dc1394error_t err; err = dc1394_feature_get_all(m_dccamera, &feature_set); dc1394bool_t is_readable; // if ( err ) return false; uint32_t dc1394_value; for ( int i = 0 ; i < DC1394_FEATURE_NUM ; i++ ) { if (feature_set.feature[i].available && key == dc1394_feature_get_string(feature_set.feature[i].id)) { props.get(key, value); dc1394_value = value; dc1394_feature_set_value(m_dccamera, feature_set.feature[i].id, dc1394_value); // TODO : limit to min / max value for each parametter } } } if(DC1394_SUCCESS!=err) { error("videoDC1394: setting '%s' failed with '%s'", key.c_str(), dc1394_error_get_string(err)); } } } #else videoDC1394 :: videoDC1394() : videoBase("") {} videoDC1394 :: ~videoDC1394() {} #endif // HAVE_LIBDC1394