Linux 获取摄像头数据并实时显示

联想笔记本z475,Ubuntu16;

使用v4l2获取摄像头数据;

使用SDL来显示YUV数据;

#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include//if SDL2 then use texture instead of overlay
#include





#define DEV_CAMERA "/dev/video0"
#define REQBUF_COUNT    4
#define handle_err(msg) \
                do  {   perror(msg);    exit(EXIT_FAILURE);     } while(0)
#define FREE(fp) \
                while(fp) { free(fp);   fp =NULL;   }

typedef struct {
    void* start;
    unsigned int length;
}BUFFER;

SDL_Surface *pscreen = NULL;
SDL_Overlay *overlay = NULL;
SDL_Rect drect;
SDL_Event sdlevent;
SDL_mutex *affmutex = NULL;
unsigned char frmrate;
unsigned char *p = NULL;
unsigned int currtime;
unsigned int lasttime;
char* status = NULL;





int process_image(BUFFER *buf, int width, int height);


int main()
{
    //SDL INIT
    //if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO |  SDL_INIT_TIMER ) < 0)
     if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
    {
        fprintf(stderr, "Can not initialize SDL: %s\n", SDL_GetError());
        exit(1);
    }

    //dev info
    struct v4l2_capability cap;
    int fd;
    //fd = open(DEV_CAMERA,O_RDONLY);//the mmap MAP_SHARED will fail:Invalid argument
    fd = open(DEV_CAMERA,O_RDWR);
    if(fd<0)
    {
        printf("can not open %s\n",DEV_CAMERA);
        return -1;
    }
    ioctl(fd,VIDIOC_QUERYCAP,&cap);
    printf("DriverName:%s\nCard Name:%s\nBus info:%s\nDriverVersion:%u.%u.%u\n",cap.driver,cap.card,cap.bus_info,(cap.version>>16) & 0xFF,(cap.version>>8) & 0xFF,cap.version & 0xFF);

    //format
    struct v4l2_fmtdesc fmtdesc;
    fmtdesc.index = 0;
    fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    printf("support format:\n");
    while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc) != -1)
    {
        printf("\t%d.%s\n",1 + fmtdesc.index++,fmtdesc.description);
    }

    struct v4l2_format fmt;
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     ioctl(fd,VIDIOC_G_FMT,&fmt);
     printf("Current format information:\n\twidth:%d\n\theight:%d\n",fmt.fmt.pix.width,fmt.fmt.pix.height);

     fmtdesc.index = 0;
     fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc) != -1)
     {
         if(fmtdesc.pixelformat & fmt.fmt.pix.pixelformat)
         {
            printf("\tformat:%s\n",fmtdesc.description);
            break;
         }
         fmtdesc.index++;
     }

     fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
     if(ioctl(fd,VIDIOC_TRY_FMT,&fmt) == -1)
     {
         perror("ioctl err");
         if(errno == EINVAL)
             printf("not support format RGB32\n");
     }
     else
        printf("RGB32 is supported\n");

     //query buf
     struct v4l2_requestbuffers reqbuf;
     reqbuf.count = REQBUF_COUNT;
     reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     reqbuf.memory = V4L2_MEMORY_MMAP;
     ioctl(fd,VIDIOC_REQBUFS,&reqbuf);

     BUFFER *buffers;

     buffers = (BUFFER*)calloc(reqbuf.count,sizeof(*buffers));
     if(!buffers)
     {
         handle_err("calloc");
     }
     for(unsigned int n_buf = 0;n_buf < reqbuf.count;n_buf++)
     {
         struct v4l2_buffer buf;
         memset(&buf,0,sizeof(buf));
         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
         buf.memory = V4L2_MEMORY_MMAP;
         buf.index = n_buf;

         if(-1 == ioctl(fd,VIDIOC_QUERYBUF,&buf))
         {
             handle_err("ioctl");
         }
         buffers[n_buf].length = buf.length;
         printf("buf.length = %d,buf.m.offset = %d\n", buf.length,buf.m.offset);

         buffers[n_buf].start = mmap(NULL,buf.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,buf.m.offset);
         //buffers[n_buf].start = mmap(NULL,buf.length,PROT_READ,MAP_SHARED,fd,buf.m.offset);
         if(MAP_FAILED == buffers[n_buf].start)
         {
             handle_err("mmap");
         }
     }

     //get camera data
     unsigned int i;
     enum v4l2_buf_type type;
     for(i=0;ipixels[0];
     drect.x = 0;
     drect.y = 0;
     drect.w = pscreen->w;
     drect.h = pscreen->h;
     int quit = 0;
     while (quit == 0)
     {
         while (SDL_PollEvent(&sdlevent))
         {
             if (sdlevent.type == SDL_QUIT)
             {
                 quit =1;
                 break;
             }
         }

         for(i =0;istart, width * height * 2 /*buf->length*/);
    SDL_UnlockYUVOverlay(overlay);
    SDL_UnlockSurface(pscreen);

    SDL_DisplayYUVOverlay(overlay, &drect); /* dispaly it */

    SDL_WM_SetCaption("Jun's camera", NULL);
    SDL_Delay(40);
    return 0;
}


你可能感兴趣的:(Linux系统编程,视)