前面说了使用USB摄像头采集bmp图片和yuv视频,显示过程直接就是把bmp图片在lcd显示出来就可以了。大体的USB摄像头操作和前面的一样,不清楚摄像头操作可以去
http://blog.csdn.net/zhangdaxia2/article/details/72763847。Framebuffer操作也不难,具体如下:
framebuffer设备节点为/dev/fbx。一般为/dev/fb0,一个液晶控制节点。操作步骤:
1、打开framebuffer。
int fd = -1;
fd = open("/dev/fb0", O_RDWR);
2、ioctl获取LCD参数。
static struct fb_fix_screeninfo fixinfo;
static struct fb_var_screeninfo varinfo;
ret = ioctl(fb_fd, FBIOGET_VSCREENINFO, &varinfo);
ret = ioctl(fb_fd, FBIOGET_FSCREENINFO, &fixinfo);
3、进行mmap内存地址映射,将内核地址映射到用户空间,用户直接向映射的地址写入数据,就可将数据显示到LCD上。
fbmmap = (int*)mmap(NULL, fixinfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED,
fb_fd, 0);
if(NULL == fbmmap){
printf("mmap memeory error.\n");
exit(0);
}
4、向映射后的地址中写入数据,绘制framebuffer。
void fb_drawbmp(uint height,uint width,unsigned char* pdata)
{
uint x,y,cnt;
uint a = height*width*3;
uint cnt1 = 0;
uint* p = fbmmap;
for(x=0; xfor(y=0; y// LCD像素位置
cnt1 = (x*width+width-y)*3; // 图片像素位置,width-y用于解决图像显示左右反了的问题
*(p+cnt) = (pdata[cnt1]<<0) | (pdata[cnt1+1]<<8) | (pdata[cnt1+2]<<16);
}
}
5、在USB摄像头操作readfram()中,将fb_drawbmp()放到里头,把摄像头采集的数据转成RGB后,直接写入framebuffer,就可以完成LCD显示摄像头图像。
static int readfram()
{
struct pollfd pollfd;
int ret,i;
char filename[50];
for(i =0; i<10 ;i++){
memset(&pollfd, 0, sizeof(pollfd));
pollfd.fd = fd;
pollfd.events = POLLIN;
ret = poll(&pollfd, 1, 800);
if(-1 == ret){
perror("VIDIOC_QBUF fail.\n");
return -1;
}else if(0 == ret){
printf("poll time out\n");
continue;
}
if(pollfd.revents & POLLIN){
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd, VIDIOC_DQBUF, &buf);
if(0 != ret){
perror("VIDIOC_QBUF fail.\n");
return -1;
}
//v4l2_buffer
// 直接保存的yuyv数据
//FILE *file = fopen(YUYV_FILE, "wb");
//ret = fwrite((char*)framebuf[buf.index].start, 1, buf.length, file);
//fclose(file);
// RGB格式数据
starter = (unsigned char*)framebuf[buf.index].start;
newBuf = (unsigned char*)calloc((unsigned int)(framebuf[buf.index].length*3/2),sizeof(unsigned char));
yuv422_2_rgb();
// 将RGB数据写入到framebuffer,在LCD上显示
fb_drawbmp(height, width, newBuf);
ret = ioctl(fd, VIDIOC_QBUF, &buf);
}
}
return ret;
}
由于Ubuntu和Android会不断的刷新屏幕,所以在这些系统上实验不一定有想过。在Linux开发板上可以正
常运行,显示出摄像头图像。
包括USB摄像头操作的完整代码可从以下网址下载:
https://github.com/zhangdalei/video_lcd_show