#include<stdlib.h>
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<linux/videodev.h>
#include<linux/fb.h>
#include<sys/mman.h>
#include<sys/ioctl.h>
typedef struct _fb_v4l
{ int fbfd; //设备句柄
struct fb_var_screeninfo vinfo; //屏幕可变信息
struct fb_fix_screeninfo finfo; //屏幕不变信息
char *fpb; //内存指针
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_v4l;
#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
#define DEFAULT_PALETTE VIDEO_PALETTE_RGB565
#define FB_FILE "/dev/fb/0"
#define V4L_FILE "/dev/v4l/video0"
int open_framebuffer(char *ptr,fb_v4l *vd)
{
int fbfd,screensize;
fbfd=open(ptr,O_RDWR);
if(fbfd<0)
{
printf("Error:cannot open framebuffer device.%x\n",fbfd);
return ERR_FRAME_BUFFER;
}
vd->fbfd=fbfd;
if(ioctl(fbfd,FBIOGET_FSCREENINFO,&vd->finfo))
{
printf("Error reading variable information.\n");
return ERR_FRAME_BUFFER;
}
printf("%dx%d,%dbpp,xoffest=%d, yoffest=%d\n",
vd->vinfo.xres,vd->vinfo.yres,
vd->vinfo.bits_per_pixel,
vd->vinfo.xoffest,vd->vinfo.yoffest);
sreensize=vd->vinfo.xres* vd->vinfo.yres* vd->vinfo.bits_per_pixel/8;
//映射到内存
vd->fb=(char*)mmap(0,sreensize,PORT_READ|PORT_WRITE,
MAP_SHARED,fbfd,0);
if((int)vd->fbp==-1)
{
printf("Error:failed to map framebuffer device to memory.\n");
return ERR_FRAME_BUFFER;
}
printf("The framebuffer device was mmaped successfully.\n");
return 0;
}
int open_video(char *fileptr,fb_v4l *vd,int dep,int pal,
int width,int hei)
{
if((vd->fd=open(fileptr,O_RDWR))<0)
{
perror("v4l_open:");
return ERR_VIDEO_OPEN;
}
printf("=============Open video success========");
//获取设备
if(ioctl(vd->fd,VIDEOCGCAP,&(vd->capability))<0)
{
perror("v4l_get_capability;");
return ERR_VIDEO_GCAP;
}
printf("=============Get device success========");
//获取图像
if(ioctl(vd->fd,VIDEOCGPICT,&(vd->picture))<0)
{
perror("v4l_get_picture;");
return ERR_VIDEO_GPIC;
}
printf("=============Get picture success========");
//设置图像
vd->picture.palette=pal;
vd->picture.depth=dep;
if(ioctl(vd->fd,VIDEOSPICT,&(vd->picture))<0)
{
perror("v4l_get_palette;");
return ERR_VIDEO_SPIC;
}
vd->mmap.format=pal;
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,VIDEOCGMBUF,&(vd->mbuf))<0)
{
perror("v4l_get_buf;");
return -1;
}
//建立设备内存映射
vd->mmap=mmap(0,vd->mmap,PORT_READ|PORT_WRITE,
MAP_SHARED,vd->fd,0);
if(vd->mmap<0)
{
perror("v4l_mmap_init:mmap");
return 0;
}
printf("The video opened successfully'\n");
return 0;
}
//帧获取
int get_grab_frame(fb_v4l *vd,int frame)
{
if(vd->frame_using[frame])
{
fprintf(stderr,"get_grab_frame:frame %d is already used.\n",frame);
return ERR_FRAME_USING;
}
//开始获取图像
if(ioctl(vd->fd,VIDEOCMCAPTURE,&(vd->mmap))<0)
{
perror("v4l_get_frame;");
return ERR_GET_FRAME;
}
//置为采集忙状态
vd->frame_using[frame]=1;
vd->frame_current=1;
return 0;
}
//采集一帧
int get_first_frame(fb_v4l *vd)
{
int ret;
vd->frame_current=0;
ret=get_grab_frame(vd,vd->frame_current);
if(ret<0)
return ret;
if(ioctl(vd->fd,VIDEOSYNC,&(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_v4l *vd)
{
return(vd->map+vd->mbuf.offsets[vd->frame_current]);
}
//RGB填充
void rgb_to_framebuffer(fb_v4l *vd,
int width,int height,
int xoffset,int yoffset,
usigend short *img_ptr)
{
int x,y;
int location;
unsigned short *loca_ptr;
for(y=0;y<height;y++)
{location=xoffset*2+(y+yoffset)*vd->finfo.line_length;
loca_ptr=(unsigned short*)(vd->fbp+location);
for(x=0;x<width;x++)
{*(loca_ptr+x)=*img_ptr++;}
}
}
//主函数
int main(void)
{
fb_v4l vd;
int ret,i;
usigned short *imagepyr;
usigned short tempbuf[640*480];
if((ret=open_framebuffer(FB_FILE,&vd))!=0)
{goto err;}
for(i=0;i<640*480;i++)
tempbuf=0xffff;
rgb_to_framebuffer(&vd,640,480,0,0,tempbuf);
//填充0xff到整个屏幕
if(ret=open_video(V4L_FILE,&vd,16,VIDEO_PALETTE_RGB565,
320,240)!=0)
{ goto err; }
printf("------picture size:%d-------,vd.mbuf.size);
while(1)
{
imageptr=(unsigned short*)fet_frame_adress(&vd);
rgb_to_framebuffer(&vd,vd.mmap.width,vd.mmap.height,
160,120,imageptr );
}
err:
if(vb.fbfd)
close(vd.fbfd);
if(vd.fd)
close(vd.fd);
exit(0);
return 0;
}
以上是我的源代码。
接了USB摄像头,良田的,可以用迷你2440板子自带的USB程序抓图。
但是上面的camera.c我自己写的v4l程序就有点问题
现在可以打印输出framebuffer设备映射到内存之前的那些信息,但是,映射到内存时就一直提示错误信息:Error:failed to map framebuffer device to memory。
问一下可能是什么原因啊?
该怎么解决这个问题?