namespace mimas {template< typename T >image_dc1394input< T >::image_dc1394input( const char *device,int node,int channel,int preferredFormat,int preferredMode,int preferredFormat7Colour,int speed )throw (mimasexception):m_device(device), m_cameraNode(NULL), m_node(-1), m_handle(NULL),m_format(-1), m_mode(-1), m_format7Colour(-1),m_colourSpace(Unknown), m_frameRate(-1), m_bufferUsed( false ){try {m_handle = dc1394_create_handle( 0 );MMERROR( m_handle != NULL, mimasexception, ,"Unable to acquire raw1394 handle. Please check, wether ""the kernel modules 'ieee1394','raw1394' and 'ohci1394' ""are loaded and wether you have read/write permission on ""\"/dev/raw1394\"." );int numNodes = raw1394_get_nodecount(m_handle);int numCameras;#ifndef NDEBUGm_cameraNode =dc1394_get_camera_nodes( m_handle, &numCameras, 1 );#elsem_cameraNode =dc1394_get_camera_nodes( m_handle, &numCameras, 0 );#endifMMERROR( numCameras >= 0, mimasexception, ,"Failed to acquire list of digital camera nodes." );MMERROR( numCameras >= 1, mimasexception, , "Did not find a single digital ""camera on the firewire bus." );// Check for iso-transfer bug of old raw1394 system// (before kernel 2.4.21-pre2).// Compare http://sourceforge.net/tracker/index.php?func=detail&aid=435107&group_id=8157&atid=108157for ( int i=0; i<numCameras; i++ ) {MMERROR( m_cameraNode[i] != numNodes - 1, mimasexception, ,"A digital camera has become the root-node of the ""firewire bus. Try to fix this problem by reloading the ""'ohci1394'-module with option 'attempt_root=1'." );};MMERROR( node >= 0 && node < numCameras, mimasexception, ,"Camera-node number " << node << " out of range. The ""range is [ 0; " << numCameras << " )." );MMERROR( dc1394_camera_on( m_handle, node ), mimasexception, ,"Could not switch on camera" );m_node = node;selectFormat( preferredFormat );selectMode( preferredMode );if ( m_mode >= MODE_FORMAT7_MIN && m_mode <= MODE_FORMAT7_MAX ) {selectFormat7Colour( preferredFormat7Colour );// Setup DMA capture (allocates ringbuffer).MMERROR( dc1394_dma_setup_format7_capture( m_handle, m_cameraNode[ m_node ], channel,m_mode, speed, QUERY_FROM_CAMERA,(unsigned int)QUERY_FROM_CAMERA,(unsigned int)QUERY_FROM_CAMERA,(unsigned int)QUERY_FROM_CAMERA,(unsigned int)QUERY_FROM_CAMERA,4,// Number of dma-buffers.1,// Drop frames.m_device.empty() ? (const char *)NULL : device,&m_camera ) == DC1394_SUCCESS,mimasexception, ,"Error setting up format7 DMA capture. Please check, wether ""the kernel modules 'video1394' is loaded and wether ""you have read/write permission on \"/dev/video1394/*\"" );} else {selectFrameRate( -1 );// Setup DMA capture (allocates ringbuffer).MMERROR( dc1394_dma_setup_capture( m_handle, m_cameraNode[ m_node ], channel,m_format, m_mode, speed, m_frameRate,4,// Number of dma-buffers.#ifdef LIBDC1394_OLD0,// Extra-buffering (?)#endif1,// Drop frames.m_device.empty() ? (const char *)NULL : device,&m_camera ) == DC1394_SUCCESS,mimasexception, ,"Error setting up DMA capture. Please check, wether ""the kernel modules 'video1394' is loaded and wether ""you have read/write permission on \"/dev/video1394/*\"" );};// Start capture.MMERROR( dc1394_start_iso_transmission( m_handle, m_camera.node )== DC1394_SUCCESS, mimasexception, ,"Error starting camera iso transmission." );} catch ( mimasexception &e ) {if ( m_node != -1 ) dc1394_camera_off( m_handle, m_node );if ( m_cameraNode != NULL ) dc1394_free_camera_nodes( m_cameraNode );if ( m_handle != NULL ) dc1394_destroy_handle( m_handle );throw e;};}template< typename T >image_dc1394input< T >::~image_dc1394input(void){if ( m_handle != NULL ) close();}template< typename T >void image_dc1394input< T >::close(void){if ( m_bufferUsed ) {dc1394_dma_done_with_buffer( &m_camera );m_bufferUsed = false;};if ( m_handle != NULL ) {// Halt iso reception.dc1394_dma_unlisten( m_handle, &m_camera );// Stop iso transmission.dc1394_stop_iso_transmission( m_handle, m_camera.node );// Free mapped memory.dc1394_dma_release_camera( m_handle, &m_camera );// Free list of nodes.dc1394_free_camera_nodes( m_cameraNode ); m_cameraNode = NULL;// Switch off camera.dc1394_camera_off( m_handle, m_node );// Free handle.dc1394_destroy_handle( m_handle ); m_handle = NULL;};}template< typename T >dc1394_feature_info image_dc1394input< T >::get_feature( int _id )throw (mimasexception){dc1394_feature_info retval; retval.feature_id = _id;MMERROR( dc1394_get_camera_feature( m_handle, m_node, &retval ) != 0,mimasexception, ,"Error requesting feature " << _id << " from firewire ""digital camera." );return retval;}template< typename T >unsigned int image_dc1394input< T >::get_feature_value( int id )throw (mimasexception){MMERROR( m_handle != NULL, mimasexception, ,"Camera device was closed already." );unsigned int retval;MMERROR( dc1394_get_feature_value( m_handle, m_node, id, &retval ) != 0,mimasexception, ,"Error requesting value of feature " << id<< " from firewire digital camera." );return retval;}template< typename T >void image_dc1394input< T >::set_feature_value( int id,unsigned int value )throw (mimasexception){MMERROR( m_handle != NULL, mimasexception, ,"Camera device was closed already." );MMERROR( dc1394_set_feature_value( m_handle, m_node, id, value ) != 0,mimasexception, ,"Error setting feature " << id << " from firewire ""digital camera." );}template< typename T >void image_dc1394input< T >::selectFormat( int preferredFormat ) throw (mimasexception){typedef struct {int format;const char *name;} FormatEntry;FormatEntry format[] = {{ FORMAT_SCALABLE_IMAGE_SIZE , "FORMAT_SCALABLE_IMAGE_SIZE" },{ FORMAT_SVGA_NONCOMPRESSED_2, "FORMAT_SVGA_NONCOMPRESSED_2" },{ FORMAT_SVGA_NONCOMPRESSED_1, "FORMAT_SVGA_NONCOMPRESSED_1" },{ FORMAT_VGA_NONCOMPRESSED , "FORMAT_VGA_NONCOMPRESSED" },{ FORMAT_STILL_IMAGE , "FORMAT_STILL_IMAGE" }};const char *namePreferred = "invalid format number";// Get list of supported formats.quadlet_t formats = 0;MMERROR( dc1394_query_supported_formats( m_handle, m_cameraNode[ m_node ], &formats )== DC1394_SUCCESS, mimasexception, ,"Error requesting supported video formats." );int selected = 0;std::ostringstream s;while ( true ) {if ( format[ selected ].format == preferredFormat )namePreferred = format[ selected ].name;// Check wether format is supported.if ( ( formats & ( 1U << ( 31 + FORMAT_MIN -format[ selected ].format ) ) ) != 0 ) {if ( preferredFormat == format[ selected ].format ||preferredFormat == -1 ) {m_format = format[ selected ].format;break;};s << " " << format[ selected ].name;};selected++;if ( selected >= (signed)(sizeof(format)/sizeof(FormatEntry)) ) {MMERROR( preferredFormat == -1, mimasexception, ,"Preferred format \"" << namePreferred<< "\" not supported by camera (supported:"<< s.str() << ")." );MMERROR( false, mimasexception, ,"Camera-driver doesn't offer a known video-format." );};};assert( m_format != -1 );}template< typename T >void image_dc1394input< T >::selectMode( int preferredMode ) throw (mimasexception){typedef struct {ColourSpace colourSpace;int mode;const char *name;} ModeEntry;ModeEntry mode[] = {{ UYVY , MODE_640x480_YUV422 , "MODE_640x480_YUV422" },{ UYVY , MODE_320x240_YUV422 , "MODE_320x200_YUV422" },{ Grey8 , MODE_640x480_MONO , "MODE_640x480_MONO" },{ RGB24 , MODE_640x480_RGB , "MODE_640x480_RGB" },{ Unknown, MODE_640x480_YUV411 , "MODE_640x480_YUV411" },{ Unknown, MODE_640x480_MONO16 , "MODE_640x480_MONO16" },{ Unknown, MODE_160x120_YUV444 , "MODE_160x120_YUV444" },{ UYVY , MODE_1024x768_YUV422 , "MODE_1024x768_YUV422" },{ Grey8 , MODE_1024x768_MONO , "MODE_1024x768_MONO" },{ RGB24 , MODE_1024x768_RGB , "MODE_1024x768_RGB" },{ UYVY , MODE_800x600_YUV422 , "MODE_800x600_YUV422" },{ Grey8 , MODE_800x600_MONO , "MODE_800x600_MONO" },{ RGB24 , MODE_800x600_RGB , "MODE_800x600_RGB" },{ Unknown, MODE_1024x768_MONO16 , "MODE_1024x768_MONO16" },{ Unknown, MODE_800x600_MONO16 , "MODE_800x600_MONO16" },{ UYVY , MODE_1600x1200_YUV422, "MODE_1600x1200_YUV422" },{ Grey8 , MODE_1600x1200_MONO , "MODE_1600x1200_MONO" },{ RGB24 , MODE_1600x1200_RGB , "MODE_1600x1200_RGB" },{ UYVY , MODE_1280x960_YUV422 , "MODE_1280x960_YUV422" },{ Grey8 , MODE_1280x960_MONO , "MODE_1280x960_MONO" },{ RGB24 , MODE_1280x960_RGB , "MODE_1280x960_RGB" },{ Unknown, MODE_1600x1200_MONO16, "MODE_1600x1200_MONO16" },{ Unknown, MODE_1280x960_MONO16 , "MODE_1280x960_MONO16" },{ Unknown, MODE_EXIF , "MODE_EXIF" },{ Unknown, MODE_FORMAT7_7 , "MODE_FORMAT7_7" },{ Unknown, MODE_FORMAT7_6 , "MODE_FORMAT7_6" },{ Unknown, MODE_FORMAT7_5 , "MODE_FORMAT7_5" },{ Unknown, MODE_FORMAT7_4 , "MODE_FORMAT7_4" },{ Unknown, MODE_FORMAT7_3 , "MODE_FORMAT7_3" },{ Unknown, MODE_FORMAT7_2 , "MODE_FORMAT7_2" },{ Unknown, MODE_FORMAT7_1 , "MODE_FORMAT7_1" },{ Unknown, MODE_FORMAT7_0 , "MODE_FORMAT7_0" }};const char *namePreferred = "invalid mode number";// Get list of supported video modes.quadlet_t videoModes = 0;MMERROR( dc1394_query_supported_modes( m_handle, m_cameraNode[ m_node ], m_format,&videoModes )== DC1394_SUCCESS, mimasexception, ,"Error requesting supported video modes." );intmodesMin = 0,modesMax = -1;switch ( m_format ) {case FORMAT_VGA_NONCOMPRESSED:modesMin = MODE_FORMAT0_MIN;modesMax = MODE_FORMAT0_MAX;break;case FORMAT_SVGA_NONCOMPRESSED_1:modesMin = MODE_FORMAT1_MIN;modesMax = MODE_FORMAT1_MAX;break;case FORMAT_SVGA_NONCOMPRESSED_2:modesMin = MODE_FORMAT2_MIN;modesMax = MODE_FORMAT2_MAX;break;case FORMAT_STILL_IMAGE:modesMin = MODE_FORMAT6_MIN;modesMax = MODE_FORMAT6_MAX;break;case FORMAT_SCALABLE_IMAGE_SIZE:modesMin = MODE_FORMAT7_MIN;modesMax = MODE_FORMAT7_MAX;break;default:assert( false );};int selected = 0;std::ostringstream s;while ( true ) {if ( mode[ selected ].mode == preferredMode )namePreferred = mode[ selected ].name;if ( mode[ selected ].mode >= modesMin &&mode[ selected ].mode <= modesMax ) {if ( ( videoModes & ( 1U << ( 31 + modesMin -mode[ selected ].mode ) ) ) != 0 ) {if ( preferredMode == mode[ selected ].mode ||preferredMode == -1 ) {m_mode = mode[ selected ].mode;m_colourSpace = mode[ selected ].colourSpace;break;};s << " " << mode[ selected ].name;};};selected++;if ( selected >= (signed)(sizeof(mode)/sizeof(ModeEntry)) ) {MMERROR( preferredMode == -1 ||( preferredMode >= modesMin &&preferredMode <= modesMax ),mimasexception, ,"Mode \"" << namePreferred << "\" not allowed with ""current format (allowed and supported:"<< s.str() << ")." );MMERROR( preferredMode == -1, mimasexception, ,"Preferred mode \"" << namePreferred<< "\" not supported in this format (supported:"<< s.str() << ")." );MMERROR( false, mimasexception, ,"The current video format doesn't offer a known mode." );};};assert( m_mode != -1 );MMERROR( m_colourSpace != Unknown ||m_format == FORMAT_SCALABLE_IMAGE_SIZE,mimasexception, , "Colourspace transformation for "<< mode[ selected ].name<< "-images not implemented." );}template< typename T >void image_dc1394input< T >::selectFrameRate( int preferredFrameRate ) throw (mimasexception){typedef struct {int rate;const char *name;} RateEntry;RateEntry rate[] = {{ FRAMERATE_240 , "FRAMERATE_240" },{ FRAMERATE_120 , "FRAMERATE_120" },{ FRAMERATE_60 , "FRAMERATE_60" },{ FRAMERATE_30 , "FRAMERATE_30" },{ FRAMERATE_15 , "FRAMERATE_15" },{ FRAMERATE_7_5 , "FRAMERATE_7_5" },{ FRAMERATE_3_75 , "FRAMERATE_3_75" },{ FRAMERATE_1_875, "FRAMERATE_1_875" }};const char *namePreferred = "invalid frame rate index";// Get list of possible framerates.quadlet_t frameRates = 0;MMERROR( dc1394_query_supported_framerates( m_handle, m_cameraNode[ m_node ], m_format,m_mode, &frameRates )== DC1394_SUCCESS, mimasexception, ,"Error requesting supported framerates." );int selected = 0;std::ostringstream s;while ( true ) {if ( rate[ selected ].rate == preferredFrameRate )namePreferred = rate[ selected ].name;// Check wether frameRate is supported.if ( ( frameRates & ( 1U << ( 31 + FRAMERATE_MIN -rate[ selected ].rate ) ) ) != 0 ) {if ( preferredFrameRate == rate[ selected ].rate ||preferredFrameRate == -1 ) {m_frameRate = rate[ selected ].rate;break;};s << " " << rate[ selected ].name;};selected++;if ( selected >= (signed)(sizeof(rate)/sizeof(RateEntry)) ) {MMERROR( preferredFrameRate == -1, mimasexception, ,"Preferred frameRate \"" << namePreferred<< "\" not supported in this mode (supported:"<< s.str() << ")." );MMERROR( false, mimasexception, ,"Camera-driver doesn't offer a known frame-rate." );};};assert( m_frameRate != -1 );}template< typename T >void image_dc1394input< T >::selectFormat7Colour( int preferredFormat7Colour )throw (mimasexception){assert( m_format == FORMAT_SCALABLE_IMAGE_SIZE );typedef struct {ColourSpace colourSpace;int colour;const char *name;} ColourEntry;ColourEntry colour[] = {{ UYVY , COLOR_FORMAT7_YUV422 , "COLOR_FORMAT7_YUV422" },{ Grey8 , COLOR_FORMAT7_MONO8 , "COLOR_FORMAT7_MONO8" },{ RGB24 , COLOR_FORMAT7_RGB8 , "COLOR_FORMAT7_RGB8" },{ Unknown, COLOR_FORMAT7_YUV411 , "COLOR_FORMAT7_YUV411" },{ Unknown, COLOR_FORMAT7_YUV444 , "COLOR_FORMAT7_YUV444" },{ Unknown, COLOR_FORMAT7_MONO16 , "COLOR_FORMAT7_MONO16" },{ Unknown, COLOR_FORMAT7_RGB16 , "COLOR_FORMAT7_RGB16" },{ Unknown, COLOR_FORMAT7_MONO16S, "COLOR_FORMAT7_MONO16S" },{ Unknown, COLOR_FORMAT7_RGB16S , "COLOR_FORMAT7_RGB16S" },{ Unknown, COLOR_FORMAT7_RAW8 , "COLOR_FORMAT7_RAW8" },{ Unknown, COLOR_FORMAT7_RAW16 , "COLOR_FORMAT7_RAW16" }};const char *namePreferred = "invalid format7 color index";// Get list of possible format7 colours.quadlet_t colours = 0;MMERROR( dc1394_query_format7_color_coding( m_handle, m_cameraNode[ m_node ],m_mode, &colours ) == DC1394_SUCCESS, mimasexception, ,"Error requesting format7 colourspaces." );int selected = 0;std::ostringstream s;while ( true ) {if ( colour[ selected ].colour == preferredFormat7Colour )namePreferred = colour[ selected ].name;// Check wether colour is supported.if ( ( colours & ( 1U << ( 31 + COLOR_FORMAT7_MIN -colour[ selected ].colour ) ) ) != 0 ) {if ( preferredFormat7Colour == colour[ selected ].colour ||preferredFormat7Colour == -1 ) {m_format7Colour = colour[ selected ].colour;m_colourSpace = colour[ selected ].colourSpace;break;};s << " " << colour[ selected ].name;};selected++;if ( selected >= (signed)(sizeof(colour)/sizeof(ColourEntry)) ) {MMERROR( preferredFormat7Colour == -1, mimasexception, ,"Preferred format7 colour \"" << namePreferred<< "\" not supported in this mode (supported:"<< s.str() << ")." );MMERROR( false, mimasexception, ,"Camera-driver doesn't offer a known format7 colour in ""this mode." );};}assert( m_format7Colour != -1 );MMERROR( m_colourSpace != Unknown,mimasexception, , "Colourspace transformation for "<< colour[ selected ].name << "-images not implemented." );}};