#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
namespace mimas {
template< typename T >
image_v4linput< T >::image_v4linput
( const std::string &_device, int channel, int width, int height,
int channel_norm )
throw (mimasexception):
device(_device), fd( -1 ), map( MAP_FAILED )
{
struct stat st;
MMERROR( stat( device.c_str(), &st ) == 0, mimasexception, ,
"Couldn't read file-attributes of \"" << device << "\": "
<< strerror( errno ) );
MMERROR( S_ISCHR(st.st_mode), mimasexception, ,
'"' << device << "\" is not a device" );
fd = open( device.c_str(), O_RDWR, 0 );
MMERROR( fd != -1, mimasexception, ,
"Could not open device \"" << device << "\": "
<< strerror( errno ) );
try {
struct video_capability cap;
MMERROR( xioctl( VIDIOCGCAP, &cap ) == 0, mimasexception, ,
"Error " << errno << " requesting video capabilities of device \""
<< device << "\": " << strerror( errno ) );
#ifndef NDEBUG
std::cerr << cap.name << ":" << std::endl
<< "type = " << cap.type << std::endl
<< "channels = " << cap.channels << std::endl
<< "audios = " << cap.audios << std::endl
<< "minwidth = " << cap.minwidth << std::endl
<< "minheight = " << cap.minheight << std::endl
<< "maxwidth = " << cap.maxwidth << std::endl
<< "maxheight = " << cap.maxheight << std::endl;
#endif
selectPalette();
chan.channel = channel;
chan.type = VIDEO_TYPE_CAMERA;
chan.norm = channel_norm;
MMERROR( xioctl( VIDIOCSCHAN, &chan ) == 0, mimasexception, ,
"Error setting channel information for channel "
<< chan.channel << " of device \"" << device << "\": "
<< strerror( errno ) );
/* chan.type = VIDEO_TYPE_CAMERA;
chan.norm = VIDEO_MODE_PAL;
MMERROR( xioctl( VIDIOCSCHAN, &chan ) == 0, mimasexception, ,
"Error setting channel info." ); */
win.x = win.y = 0;
win.chromakey = 0 ;
win.width = width == -1 ? cap.maxwidth : width;
win.height = height == -1 ? cap.maxheight : height;
win.flags = 0;
// Try to set values.
#ifndef NDEBUG
int r = xioctl( VIDIOCSWIN, &win );
if ( r != 0 )
std::cerr << "Setting capture window failed." << std::endl;
#else
xioctl( VIDIOCSWIN, &win );
#endif
// Get values choosen by driver.
MMERROR( xioctl( VIDIOCGWIN, &win ) == 0, mimasexception, ,
"Error querying capture window of device \"" << device << "\": "
<< strerror( errno ) );
if ( xioctl( VIDIOCGMBUF, &buf ) == 0 ) {
#ifndef NDEBUG
std::cerr << "Memory-map interface:" << std::endl
<< "buffer-size = " << buf.size << std::endl
<< "frames = " << buf.frames << std::endl
<< "offset of each frame = " << buf.offsets << std::endl;
#endif
map = mmap( 0, buf.size, PROT_READ, MAP_SHARED, fd, 0 );
#ifndef NDEBUG
if ( map == MAP_FAILED )
std::cerr << "Failed to map memory." << std::endl;
#endif
} else {
#ifndef NDEBUG
std::cerr << "Memory-map interface is not supported." << std::endl;
#endif
};
} catch ( mimasexception &e ) {
if ( map != MAP_FAILED ) munmap( map, buf.size );
if ( fd != -1 ) close( fd );
throw e;
}
}
template< typename T >
image_v4linput< T >::~image_v4linput(void)
{
if( map != MAP_FAILED )
munmap( map, buf.size );
assert( fd != -1 );
close( fd );
}
template< typename T >
int image_v4linput< T >::xioctl( int request, void *arg )
{
int r;
do {
r = ioctl( fd, request, arg );
#ifndef NDEBUG
if ( r == -1 && errno == EINTR )
std::cerr << "ioctl returned " << r << std::endl
<< "errno is " << errno << std::endl;
#endif
} while ( r == -1 && errno == EINTR );
return r;
}
template< typename T >
void image_v4linput< T >::setSensivity( __u16 brightness,
__u16 hue,
__u16 colour,
__u16 contrast )
throw (mimasexception)
{
pic.brightness = brightness;
pic.hue = hue;
pic.colour = colour;
pic.contrast = contrast;
MMERROR( xioctl( VIDIOCSPICT, &pic ) == 0,
mimasexception, , "Error changing sensivity of video-device." );
}
};