# include < stdio. h>
# include < stdlib. h>
# include < unistd. h>
# include < linux/ videodev. h>
# include < sys/ ioctl. h>
# include < fcntl. h>
# include < linux/ fb. h>
# include < sys/ mman. h>
# include < linux/ delay. h>
# include < time . h>
# define ERR_FRAME_BUFFER 1
# define ERR_VIDEO_OPEN 2
# define ERR_VIDEO_GCAP 3
# define ERR_VIDEO_GPIC 4
# define ERR_VIDEO_SPIC 5
# define ERR_SYNC 6
# define ERR_FRAME_USING 7
# define ERR_GET_FRAME 8
typedef struct _fb_v4l
{
int fbfd ;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
char * fbp;
int fd;
struct video_capability capability;
struct video_buffer buffer;
struct video_window window;
struct video_channel channel[ 8] ;
struct video_picture picture;
struct video_tuner tuner;
struct video_audio audio[ 8] ;
struct video_mmap mmap;
struct video_mbuf mbuf;
unsigned char * map ;
int frame_current;
int frame_using[ VIDEO_MAX_FRAME] ;
} fb_v41;
struct file_header
{
unsigned short bfType; // Picture tpye, must set to 19778
int bfSize; // The file size in bytes
int bfRev; // Reserved
int bfOffBits; // the offset from the beginning of the file to the bitmap data.
} __attribute__ ( ( packed) ) ;
struct info_header
{
int biSize; // info_header's size in bytes
int biWidth; // width in pixels
int biHeight; //height in pixels
short biPlanes; //the number of planes of the target device
short biBitCount; //the number of bits per pixel
int biCompression; //the type of compression
int biSizeImage; //
int biXPelsPerMeter; //usually set to zero
int biYPelsPerMeter; //usually set to zero
int biClrUsed; //the number of colors used in the bitmap
int biClrImportant;
} __attribute__ ( ( packed) ) ;
struct bmp_file
{
struct file_header header;
struct info_header info;
unsigned char bits[ 640* 480* 3] ;
} __attribute__ ( ( packed) ) ;
# define V4L_FILE "/dev/video0"
int get_grab_frame( fb_v41 * vd, int frame)
{
if ( vd- > frame_using[ frame] )
{
fprintf ( stderr , "get_grab_frame: frame %d is already used./n" , frame) ;
return ERR_FRAME_USING;
}
vd- > mmap. frame = frame;
if ( ioctl( vd- > fd, VIDIOCMCAPTURE, & ( vd- > mmap) ) < 0)
{
perror ( "v4l_grab_frame" ) ;
return ERR_GET_FRAME;
}
vd- > frame_using[ frame] = 1;
vd- > frame_current = frame;
return 0;
}
int get_first_frame( fb_v41 * vd)
{
int ret;
vd- > frame_current = 0;
ret = get_grab_frame( vd, 0 ) ;
if ( ret< 0 )
return ret;
if ( ioctl( vd- > fd, VIDIOCSYNC, & ( vd- > frame_current) ) < 0)
{
perror ( "v4l_grab_sync" ) ;
return ERR_SYNC;
}
vd- > frame_using[ vd- > frame_current] = 0 ;
return ( 0) ;
}
int get_next_frame( fb_v41 * vd)
{
int ret;
vd- > frame_current ^= 1;
ret = get_grab_frame( vd, vd- > frame_current) ;
if ( ret < 0 )
return ret;
if ( ioctl( vd- > fd, VIDIOCSYNC, & ( vd- > frame_current) ) < 0)
{
perror ( "v4l_grab_sync" ) ;
return ERR_SYNC;
}
vd- > frame_using[ vd- > frame_current] = 0 ;
return 0;
}
unsigned char * get_frame_address( fb_v41 * vd)
{
return ( vd- > map + vd- > mbuf. offsets[ vd- > frame_current] ) ;
}
int open_video( char * fileptr, fb_v41 * vd , int dep, int pal, int width, int height)
{
if ( ( vd- > fd = open ( fileptr, O_RDWR) ) < 0)
{
perror ( "v4l_open:" ) ;
return ERR_VIDEO_OPEN;
}
if ( ioctl( vd- > fd, VIDIOCGCAP, & ( vd- > capability) ) < 0)
{
perror ( "v4l_get_capability:" ) ;
return ERR_VIDEO_GCAP;
}
if ( ioctl( vd- > fd, VIDIOCGPICT, & ( vd- > picture) ) < 0)
{
perror ( "v4l_get_picture" ) ;
return ERR_VIDEO_GPIC;
}
vd- > picture. palette = pal;
vd- > picture. depth = dep;
vd- > mmap. format = pal;
if ( ioctl( vd- > fd, VIDIOCSPICT, & ( vd- > picture) ) < 0)
{
perror ( "v4l_set_palette" ) ;
return ERR_VIDEO_SPIC;
}
vd- > mmap. width = width;
vd- > mmap. height = height;
vd- > mmap. format = vd- > picture. palette;
vd- > frame_current = 0;
vd- > frame_using[ 0] = 0;
vd- > frame_using[ 1] = 0;
if ( ioctl( vd- > fd, VIDIOCGMBUF, & ( vd- > mbuf) ) < 0)
{
perror ( "v4l_get_mbuf" ) ;
return - 1;
}
vd- > map = mmap( 0, vd- > mbuf. size, PROT_READ| PROT_WRITE, MAP_SHARED, vd- > fd, 0) ;
if ( vd- > map < 0)
{
perror ( "v4l_mmap_init:mmap" ) ;
return - 1;
}
printf ( "The video device was opened successfully./n" ) ;
return 0;
}
static void cvt_420p_to_rgb( int width, int height, const unsigned char * src, unsigned char * dst)
{
int r, g, b;
int rdif, gdif, bdif, y;
int yy, uu, vv;
int xoff, yoff;
int numpix = width* height;
unsigned char * pout = dst + width* height* 3;
for ( yoff= 0; yoff< height; yoff+ + )
{
for ( xoff= 0; xoff< width; xoff+ + )
{
yy = * ( src+ yoff* 640+ xoff) ;
uu = * ( src+ ( yoff/ 2) * 320+ xoff/ 2+ numpix) ;
vv = * ( src+ ( yoff/ 2) * 320+ xoff/ 2+ numpix+ numpix/ 4) ;
uu - = 128;
vv - = 128;
r = yy + vv + ( ( vv* 103) > > 8) ;
g = yy - ( ( uu* 88) > > 8) - ( ( vv* 183) > > 8) ;
b = yy + uu + ( ( uu* 198) > > 8) ;
if ( r> 255) { r = 255; }
if ( g> 255) { g = 255; }
if ( b> 255) { b = 255; }
if ( r< 0) { r = 0; }
if ( g< 0) { g = 0; }
if ( b< 0) { b = 0; }
* pout = ( unsigned char ) b;
pout- - ;
* pout = ( unsigned char ) r;
pout- - ;
* pout = ( unsigned char ) g;
pout- - ;
}
}
}
int main( void )
{
fb_v41 vd;
int ret, i;
int k= 0;
unsigned char * imageptr;
struct bmp_file myfile;
int fd;
printf ( "sizeof short is %d/n" , sizeof ( short ) ) ;
myfile. header. bfType = 19778;
myfile. header. bfSize = sizeof ( struct bmp_file) ;
myfile. header. bfRev = 0;
myfile. header. bfOffBits = 54;
myfile. info. biSize = 0x28;
myfile. info. biWidth = 640;
myfile. info. biHeight = 480;
myfile. info. biPlanes = 1;
myfile. info. biBitCount = 24;
myfile. info. biCompression = 0;
myfile. info. biSizeImage = 0;
myfile. info. biClrUsed = 256* 256* 256;
myfile. info. biClrImportant = 0;
myfile. info. biXPelsPerMeter = 2048;
myfile. info. biYPelsPerMeter = 2048;
fd = open ( "./first.bmp" , O_RDWR) ;
if ( fd < 0)
{
printf ( "open file error!/n" ) ;
return 0;
}
ret = open_video( V4L_FILE, & vd, 24, VIDEO_PALETTE_YUV420P, 640, 480) ;
if ( ret )
{
printf ( "Open video failed!/n" ) ;
goto err;
}
printf ( vd. capability. name) ;
printf ( ", Type:%d/n" , vd. capability. type) ;
printf ( "Maxwidth:%d,Maxheight:%d/n" , vd. capability. maxwidth , vd. capability. maxheight) ;
printf ( "Minwidth:%d,Minheight:%d/n" , vd. capability. minwidth, vd. capability. minheight) ;
printf ( "Channels:%d,Audios:%d/n" , vd. capability. channels, vd. capability. audios) ;
for ( i= 0; i< 10; i+ + )
{
imageptr = ( unsigned char * ) get_frame_address( & vd ) ;
if ( get_next_frame( & vd ) ! = 0 )
{
goto err;
}
printf ( "i = %d/n" , i) ;
}
cvt_420p_to_rgb( 640, 480, imageptr, myfile. bits) ;
write ( fd, & myfile, sizeof ( struct bmp_file) ) ;
err:
if ( vd. fbfd)
close ( vd. fbfd) ;
if ( vd. fd)
close ( vd. fd) ;
exit ( 0) ;
return 0;
}
video4linux——包含yuv转rgb
最新推荐文章于 2024-07-31 08:47:03 发布