#include <boost/shared_array.hpp>
#include <errno.h>
#include "image_v4linput.h"
#include "colourspace.h"
using namespace boost;
using namespace std;
namespace mimas {
template<>
void image_v4linput< rgba< unsigned char > >::read
(image< rgba< unsigned char > > &img ) throw (mimasexception)
{
// State-variable never becomes false. Input from video4linux only comes
// to an end by an error.
assert( state == true );
shared_array< unsigned char > buffer;
void *src = NULL;
if ( map != MAP_FAILED ) {
video_mmap vmap;
vmap.frame = 0;
vmap.width = win.width;
vmap.height = win.height;
vmap.format = pic.palette;
MMERROR( xioctl( VIDIOCMCAPTURE, &vmap ) == 0, mimasexception, ,
"Error initiating capture of image: " << strerror( errno ) );
MMERROR( xioctl( VIDIOCSYNC, &vmap ) == 0, mimasexception, ,
"Error on synchronising with capture of image: "
<< strerror( errno ) );
src = map;
} else {
int size;
switch ( pic.palette ) {
case VIDEO_PALETTE_RGB24:
size = 3 * win.width * win.height;
break;
case VIDEO_PALETTE_YUV420P:
size = win.width * win.height * 3 / 2;
break;
case VIDEO_PALETTE_UYVY:
case VIDEO_PALETTE_YUV422:
size = win.width * win.height * 2;
break;
default:
assert( false );
MMERROR( false, mimasexception, ,
"Software error in colour-grabbing code. Encountered "
"unsupported palette number " << pic.palette << "." );
};
buffer = shared_array< unsigned char >( new unsigned char[ size ] );
src = (void *)buffer.get();
MMERROR( ::read( fd, src, size ) != -1, mimasexception, ,
"Error reading from device: " << strerror( errno ) );
};
img.init( win.width, win.height );
#ifndef NDEBUG
std::cerr << img.rawData() << ' '
<< img.getSize() << ' '
<< img.getWidth() << ' ' << img.getHeight() << std::endl;
#endif
switch ( pic.palette ) {
case VIDEO_PALETTE_RGB24:
rgb_to_rgba( (const char *)src, win.width, win.height,
(char *)img.rawData() );
break;
case VIDEO_PALETTE_YUV420P:
yuv420p_to_rgba( (const char *)src, win.width, win.height,
(char *)img.rawData() );
break;
case VIDEO_PALETTE_UYVY:
case VIDEO_PALETTE_YUV422:
uyvy_to_rgba( (const char *)src, win.width, win.height,
(char *)img.rawData() );
break;
default:
assert( false );
MMERROR( false, mimasexception, ,
"Software error in colour-grabbing code. Encountered "
"unsupported palette number " << pic.palette << "." );
};
}
template<>
void image_v4linput< rgba< unsigned char > >::selectPalette(void)
throw(mimasexception)
{
boost::array< __u16, 14 > palette;
palette[ 0 ] = VIDEO_PALETTE_YUV420P;// ->RGBA supported
palette[ 1 ] = VIDEO_PALETTE_UYVY;// ->RGBA supported
palette[ 2 ] = VIDEO_PALETTE_YUV422;// -> RGBA supported
palette[ 3 ] = VIDEO_PALETTE_RGB24;// ->RGBA supported
palette[ 4 ] = VIDEO_PALETTE_HI240;
palette[ 5 ] = VIDEO_PALETTE_RGB565;
palette[ 6 ] = VIDEO_PALETTE_RGB555;
palette[ 7 ] = VIDEO_PALETTE_RGB32;
palette[ 8 ] = VIDEO_PALETTE_YUYV;
palette[ 9 ] = VIDEO_PALETTE_YUV420;
palette[ 10 ] = VIDEO_PALETTE_YUV411;
palette[ 11 ] = VIDEO_PALETTE_RAW;
palette[ 12 ] = VIDEO_PALETTE_YUV422P;
palette[ 13 ] = VIDEO_PALETTE_YUV411P;
pic.brightness = pic.hue = pic.colour = pic.contrast = pic.whiteness = 32767;
pic.depth = 24;
int selected = 0;
while ( true ) {
pic.palette = palette[ selected ];
int r = xioctl( VIDIOCSPICT, &pic );
if ( r == 0 ) {
#ifndef NDEBUG
std::cerr << "Using " << ( selected + 1 ) << "th supported option."
<< std::endl;
#endif
break;
};
selected++;
MMERROR( selected < (signed)palette.size(),
mimasexception, ,
"Camera-driver doesn't offer a colour-video-palette known to "
"mimas." );
};
MMERROR( selected < 4, mimasexception, ,
"Colour-grabbing with video-palette "
<< palette[ selected ] << " (kmando-index " << selected
<< ") not supported by kmando. Please contact the developers." );
}
};