v4l2 视频采集流程程序

v4l2 视频采集流程程序

/******************v4l2.c******************/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/videodev.h>
#ifdef ANDROID_ENV
#define LOG LOGV
#else
#define LOG //
#endif

#define CAMERA_DEVICE "/dev/video0"
#define VIDEO_WIDTH 640
#define VIDEO_HEIGHT 480
#define VIDEO_FORMAT V4L2_PIX_FMT_YUYV
#define BUFFER_COUNT 1

struct fimc_buffer {
int length;
void *start;
} framebuf[BUFFER_COUNT];

int main()
{
    int i, ret;
    int j,k,n,m;
    char name[10]={0};
    int flag=1;
    int fd;
    fd = open(CAMERA_DEVICE, O_RDWR, 0);//设备以非阻塞方式打开
    if (fd < 0)
    {
        LOG("Open %s failed/n", CAMERA_DEVICE);
        return -1;
    }

    struct v4l2_capability cap;
    ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);//摄像头主要功能获取
    if (ret < 0)
    {
        LOG("VIDIOC_QUERYCAP failed (%d)/n", ret);
        return ret;
    }

    struct v4l2_format fmt;      //设置视频制式和帧格式
    memset(&fmt, 0, sizeof(fmt));
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    fmt.fmt.pix.width = VIDEO_WIDTH;
    fmt.fmt.pix.height = VIDEO_HEIGHT;
    fmt.fmt.pix.pixelformat = VIDEO_FORMAT;
    fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
    ret = ioctl(fd, VIDIOC_S_FMT, &fmt);
    if (ret < 0)
    {
        LOG("VIDIOC_S_FMT failed (%d)/n", ret);
        return ret;
    }

    ret = ioctl(fd, VIDIOC_G_FMT, &fmt);//获取视频制式和帧格式的实际值,看是否设置正确
    if (ret < 0)
    {
        LOG("VIDIOC_G_FMT failed (%d)/n", ret);
        return ret;
    }

    struct v4l2_requestbuffers reqbuf;//向驱动申请帧缓冲
    reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    reqbuf.memory = V4L2_MEMORY_MMAP;
    reqbuf.count = BUFFER_COUNT;
    ret = ioctl(fd , VIDIOC_REQBUFS, &reqbuf);
    if(ret < 0)
    {
        LOG("VIDIOC_REQBUFS failed (%d)/n", ret);
        return ret;
    }

    struct v4l2_buffer buf;//获取帧缓冲地址
    for(i=0; i<BUFFER_COUNT; i++)
     {
        buf.index = i;
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        ret = ioctl(fd , VIDIOC_QUERYBUF, &buf);
        if(ret < 0)
        {
            LOG("VIDIOC_QUERYBUF (%d) failed (%d)/n", i, ret);
            return ret;
        }
        framebuf[i].length = buf.length;
        framebuf[i].start = (char *) mmap(0, buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, buf.m.offset);//将申请到的帧缓冲映射到用户空间,就能直接操作采集的帧
        if (framebuf[i].start == MAP_FAILED) 
        {
            LOG("mmap (%d) failed: %s/n", i, strerror(errno));
            return -1; 
        }

        ret = ioctl(fd , VIDIOC_QBUF, &buf);//将申请到的帧缓冲全部入队列,以便存放数据
        if (ret < 0) 
        {
            LOG("VIDIOC_QBUF (%d) failed (%d)/n", i, ret);
            return -1; 
        }

    }

    enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//开始视频采集
    ret = ioctl(fd, VIDIOC_STREAMON, &type);
    if (ret < 0) 
    {
        LOG("VIDIOC_STREAMON failed (%d)/n", ret);
        return ret;
    }

    while(1)
    {
        for(k=0;k<10;k++)
        {
            ret = ioctl(fd, VIDIOC_DQBUF, &buf);//出队列以取得已采集数据的帧缓冲,取得原始数据
            if (ret < 0)
            {
                LOG("VIDIOC_DQBUF failed (%d)/n", ret);
                return ret;
            }

            strcpy(name,"a.jpeg");
            name[0]='a'+k;
            FILE *fp = fopen(name, "wb");
            if (fp < 0) 
            {
                LOG("open frame data file failed/n");
                return -1;
            }
            fwrite(framebuf[buf.index].start, 1, buf.length, fp);
            fclose(fp);
            ret = ioctl(fd, VIDIOC_QBUF, &buf);//将缓冲重新入对尾,可以循环采集
            if (ret < 0) 
            {
                LOG("VIDIOC_QBUF failed (%d)/n", ret);
                return ret;
            }
        }
    }
    for (i=0; i<BUFFER_COUNT; i++) 
    {
       munmap(framebuf[i].start, framebuf[i].length);//取消映射,释放内存
    }
    close(fd);
    LOG("Camera test Done./n");
    return 0;
}

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值