v4l2採集代碼

雖然網上很多了,還是貼一下吧,自己剛入門的時候也是找苦逼很久找代碼,代碼我也是總結的,算是轉載吧。
一、v4l2_uvc.c

void get_cam_info(struct camera *cam)
{
    if(ioctl(cam->fd, VIDIOC_QUERYCAP, &cam->cap) < 0)
    {
        perror("query camera information error.\n");
        exit(0);
    }
    if(!(cam->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
    {
        printf("device is not a capture device.\n");
        exit(0);
    }
    printf("\nCapability Informations:\n");
    printf("Driver Name:%s\nCard Name:%s\nBus info:%s\nDriver Version:%u.%u.%u\nCapabilities: %d\n",
           cam->cap.driver,cam->cap.card,cam->cap.bus_info,
           (cam->cap.version>>16)&0XFF, (cam->cap.version>>8)&0XFF,cam->cap.version&0XFF,
           cam->cap.capabilities );
}
void get_cam_fmtdesc(struct camera *cam)
{
    cam->fmtdesc.index  = 0;
    cam->fmtdesc.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    while ((ioctl(cam->fd, VIDIOC_ENUM_FMT, &cam->fmtdesc)) == 0)
    {
        printf("\t%d.\n\t{\n\tpixelformat = '%c%c%c%c',\n\tdescription = '%s'\n \t}\n",
                cam->fmtdesc.index+1,
                cam->fmtdesc.pixelformat & 0xFF,
               (cam->fmtdesc.pixelformat >> 8) & 0xFF,
               (cam->fmtdesc.pixelformat >> 16) & 0xFF,
               (cam->fmtdesc.pixelformat >> 24) & 0xFF,
                cam->fmtdesc.description);
                cam->fmtdesc.index++;
    }
}
void set_cap_format(struct camera *cam)
{
    memset(&cam->format, 0, sizeof(cam->format));

    cam->format.fmt.pix.width       = cam->width;
    cam->format.fmt.pix.height      = cam->height;
    cam->format.fmt.pix.pixelformat = cam->cap_format;
    //cam->format.fmt.pix.field       = V4L2_FIELD_INTERLACED;
    cam->format.fmt.pix.field       = V4L2_FIELD_ANY;
    cam->format.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    if(ioctl(cam->fd, VIDIOC_S_FMT, &cam->format) < 0)
    {
        perror("set capture format error.\n");
        exit(0);
    }
}
void get_cap_format(struct camera *cam)
{
    struct v4l2_format fmt;
    struct v4l2_fmtdesc fmtdesc;
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if(ioctl(cam->fd, VIDIOC_G_FMT, &fmt) < 0)
    {
        perror("get_cap_format:error.\n");
        exit(0);
    }
    printf("\nCurrent data format information:\n width:%d\n height:%d\n",
           fmt.fmt.pix.width,fmt.fmt.pix.height);

    fmtdesc.index       = 0;
    fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    while(ioctl(cam->fd, VIDIOC_ENUM_FMT, &fmtdesc) != -1)
    {
        if(fmtdesc.pixelformat == cam->format.fmt.pix.pixelformat)
        {
            printf(" format:%s\n",fmtdesc.description);
            break;
        }
        fmtdesc.index ++;
    }
}
void get_framerate(struct camera *cam)
{
    int ret;
    memset(&cam->setfps, 0, sizeof(struct v4l2_streamparm));
    cam->setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
    cam->setfps.parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
    ret = ioctl(cam->fd, VIDIOC_G_PARM, &cam->setfps);
    if(ret < 0)
    {
        perror("get fps error.\n");
    }
    printf(" fps:%d\n",cam->setfps.parm.capture.timeperframe.denominator);
}
void set_framerate(struct camera *cam)
{   
    int ret ;
    memset(&cam->setfps, 0, sizeof(struct v4l2_streamparm));
    cam->setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    cam->setfps.parm.capture.timeperframe.numerator = 1;
    cam->setfps.parm.capture.timeperframe.denominator = 25;
    ret = ioctl(cam->fd, VIDIOC_S_PARM, &cam->setfps);
    if(ret < 0)
    {
        perror("set fps error.\n");
    }
}
void req_buffer(struct camera *cam)
{
    memset(&cam->reqbuf, 0, sizeof(cam->reqbuf));

    cam->reqbuf.count   = cam->buf_num;
    cam->reqbuf.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    cam->reqbuf.memory  = V4L2_MEMORY_MMAP;

    if(ioctl(cam->fd, VIDIOC_REQBUFS, &cam->reqbuf) < 0)
    {
        perror("reqbuf error.\n");
        exit(0);
    }
}

void init_mmap(struct camera *cam)
{   

    unsigned int i;
    for(i=0; i<cam->buf_num; i++)
    {
        //memset(&cam->buf, 0, sizeof(cam->buf));

        cam->buf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        cam->buf.memory = V4L2_MEMORY_MMAP;
        cam->buf.index  = i;

        if(-1 == ioctl(cam->fd, VIDIOC_QUERYBUF, &cam->buf))
        {
            perror("ioctl querybuf error.\n");
            exit(0);
        }

        cam->buffers[i].length = cam->buf.length;

        cam->buffers[i].start = (unsigned char *)mmap(NULL,
                                cam->buf.length,
                                PROT_READ | PROT_WRITE,
                                MAP_SHARED,
                                cam->fd,
                                cam->buf.m.offset);

        if(MAP_FAILED == cam->buffers[i].start)
        {
            perror("mmap error.\n");
            exit(0);
        }
    }
}

void start_capture(struct camera *cam)
{
    unsigned int i;

    for(i=0; i<cam->buf_num; i++)
    {
        //memset(&cam->buf, 0, sizeof(cam->buf));
        cam->buf.type       = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        cam->buf.memory     = V4L2_MEMORY_MMAP;
        cam->buf.index      = i;

        if(-1 == ioctl(cam->fd, VIDIOC_QBUF, &cam->buf))
        {
            perror("start capture:video ioctl qbuf error.\n");
            exit(0);
        }   
    }
    if(-1 == ioctl(cam->fd, VIDIOC_STREAMON, &cam->buf.type))
    {
        perror("start capture:video ioctl streamon error.\n");
        exit(0);
    }
}

int isHaveData(int fd)
{
    fd_set fds;
    struct timeval tv;
    int r;

    FD_ZERO (&fds);//將指定的文件描述符集清空
    FD_SET (fd, &fds);//在文件描述符集合中增加一個新的文件描述符

    tv.tv_sec = 2;
    tv.tv_usec = 0;
    for (;;) //這一段涉及到異步IO
    {
        r = select (fd + 1, &fds, NULL, NULL, &tv);//判斷是否可讀(即攝像頭是否準備好),tv是定時
        if (-1 == r)
        {
            if (EINTR == errno)
            {
                printf("select err\n");
                continue;
            }  
        }
        if (0 == r)
        {
            fprintf (stderr, "select timeout:%d\n",errno);
            return 0;
        }           
        return 1;
    }
}

int get_one_frame_buf(struct camera * cam)
{
    int index ;
    if(isHaveData(cam->fd))
    {
        memset(&cam->buf, 0, sizeof(cam->buf));

        cam->buf.type       = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        cam->buf.memory     = V4L2_MEMORY_MMAP;
        if(ioctl(cam->fd, VIDIOC_DQBUF, &cam->buf) < 0)
        {
            perror("get one frame buffer:video ioctl dqbuf error.\n");
            exit(0);
        }

        assert(cam->buf.index < cam->buf_num);

        index = cam->buf.index;
        //starter = (unsigned char *)buffers[cam->buf.index].start;
        if(ioctl(cam->fd, VIDIOC_QBUF, &cam->buf) < 0)
        {
            perror("get one frame buffer:video ioctl qbuf error.\n");
            exit(0);
        }   
        return index;
    }
    else
    {
        printf("get one frame buffer error.\n");
        exit(0);
    }
}

void stop_capture(struct camera *cam)
{           
    if(-1 == ioctl(cam->fd,VIDIOC_STREAMOFF,&cam->fmtdesc.type))
    {
        perror("stop capture error.\n");
        exit(0);
    }   

    close(cam->fd);

    printf("stop capture successfully!\n"); 
}

void Munmap(int req_num, struct mmap_buffer *buffers)
{
    unsigned int i;
    for (i = 0; i < req_num; ++i)
        if (-1 == munmap(buffers[i].start, buffers[i].length))   
            free (buffers);
}

二、v4l2_uvc.h
這裏的h4all.h包含的庫函數,動手man一下吧 :-D

#ifndef _V4L2_UVC_H
#define _V4L2_UVC_H
#include "h4all.h"
struct mmap_buffer{
    void *start;
    size_t length;
};
typedef struct camera{  
    int fd; //攝像頭文件描述符
    int width;
    int height;
    int cap_format;
    int buf_num;
    struct v4l2_capability      cap;
    struct v4l2_fmtdesc         fmtdesc;
    struct v4l2_format          format;
    struct v4l2_streamparm      setfps;
    struct v4l2_requestbuffers  reqbuf;
    struct v4l2_buffer          buf;
    struct mmap_buffer          buffers[4];
}Camera;

void get_cam_info(struct camera *cam);

void get_cam_fmtdesc(struct camera *cam);

void set_cap_format(struct camera *cam);

void get_cap_format(struct camera *cam);

void get_framerate(struct camera *cam);

void set_framerate(struct camera *cam);

void req_buffer(struct camera *cam);

void init_mmap(struct camera *cam);

void start_capture(struct camera *cam);

int get_one_frame_buf(struct camera * cam);

void stop_capture(struct camera *cam);

void Munmap(int req_num, struct mmap_buffer *buffers);

void Init_v4l2(struct camera *cam);

#endif 

四、初始化,main.c

#define DRIVER      "/dev/video2"
#define WIDTH       176
#define HEIGHT      144
#define CAP_FORMAT  V4L2_PIX_FMT_YUYV
#define REQ_BUFFER  4

Camera *cam;
struct mmap_buffer buffers[REQ_BUFFER];
cam = (Camera *)malloc(sizeof(Camera));

void set_cam(Camera *cam, const char *driver_path, 
    int width, int height, int format, int req_num)
{
    cam->fd         = Open(driver_path);
    cam->width      = width;
    cam->height     = height;
    cam->cap_format = format;
    cam->buf_num    = req_num;  
}

五、獲得數據
調用v4l2_uvc.c的get_one_frame_buf(cam),用int型的index接收返回值,即是目前獲得的底幾個緩衝區的索引值,cam->buffers[index].start即是指向那段數據內存,cam->buffers[index].length即是大小
.
.
.
.
.
.
.
.
.
.
.
(20160622補充)
當然,還有什麼設置伽馬值、曝光度這些套路跟上面差不多,可以百度一下,作爲函數補充進去

發佈了38 篇原創文章 · 獲贊 9 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章