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 NDEBUG
m_cameraNode =
dc1394_get_camera_nodes( m_handle, &numCameras, 1 );
#else
m_cameraNode =
dc1394_get_camera_nodes( m_handle, &numCameras, 0 );
#endif
MMERROR( 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=108157
for ( 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_OLD
0,// Extra-buffering (?)
#endif
1,// 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." );
int
modesMin = 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." );
}
};