主题 : USB摄像头采集图像 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 33661
精华: 0
发帖: 3
金钱: 15 两
威望: 3 点
综合积分: 6 分
注册时间: 2010-12-04
最后登录: 2010-12-06
楼主  发表于: 2010-12-04 17:02

 USB摄像头采集图像

#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。
问一下可能是什么原因啊?
该怎么解决这个问题?
级别: 新手上路
UID: 33661
精华: 0
发帖: 3
金钱: 15 两
威望: 3 点
综合积分: 6 分
注册时间: 2010-12-04
最后登录: 2010-12-06
1楼  发表于: 2010-12-04 23:44
没人回复呀,我知道大家高手,一起交流一下嘛,附上执行时的信息:
[root@FriendlyARM plg]# ./camera
240x320,16bpp,xoffest=0, yoffest=0
screensize=153600
The framebuffer device was mmaped successfully.
Segmentation fault
[root@FriendlyARM plg]#