V4L2应用程序

        V4L2采集视频操作基本按照:打开视频设备、设置视频格式、启动视频采集、循环处理视频数据、停止视频采集、关闭视频设备,具体操作通过ioctl等函数实现

一般操作流程如下:

1、打开视频设备文件

int fd = open("/dev/video0", O_RDWR);


2、查询设备的能力,比如是否具有视频输入、或者音频输入输出等

struct v4l2_capability {
    __u8    driver[16];         /* i.e. "bttv" */                                                //驱动的名字
    __u8    card[32];           /* i.e. "Hauppauge WinTV" */                    //设备的名字
    __u8    bus_info[32];    /* "PCI:" + pci_name(pci_dev) */             //设备在系统中位置
    __u32   version;            /* should use KERNEL_VERSION() */  //驱动版本号
    __u32    capabilities;    /* Device capabilities */                            //设备支持的操作
    __u32    reserved[4];
};

struct v4l2_capability cap;

ioctl(fd, VIDIOC_QUERYCAP, &cap);


3、设置视频采集参数

1)设置视频的制式,制式包括PAL/NTSC,

typedef __u64 v4l2_std_id;

使用ioctl(fd, VIDIOC_S_STD, &std_id);

2)设置视频图像的采集窗口的类型和大小

struct v4l2_crop {
    enum v4l2_buf_type   type;//视频采集类型V4L2_BUF_TYPE_VIDEO_CAPTURE
    struct v4l2_rect            c;      //表示采集窗口的大小的结构体
};

struct v4l2_crop crop;

使用ioctl(fd, VIDIOC_S_CROP, &crop);

3)显示所有的视频帧格式

struct v4l2_fmtdesc {
    __u32                           index;                 //格式序号
    enum v4l2_buf_type  type;                   //帧类型
    __u32                           flags;                  //是否为压缩格式
    __u8                             description[32]; //格式名称
    __u32                           pixelformat;        /* Format fourcc      */
    __u32                           reserved[4];
};

struct v4l2_fmtdesc fmtdesc;

ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc);可以通过循环使用这个函数遍历输出所有格式

4)设置视频帧格式,包括帧的点阵格式、宽度和高度等

struct v4l2_format {
    enum v4l2_buf_type type;
    union {
        struct v4l2_pix_format        pix;     /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
        struct v4l2_window             win;    /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
        struct v4l2_vbi_format        vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
        struct v4l2_sliced_vbi_format    sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
        __u8    raw_data[200];                   /* user-defined */
    } fmt;
};

struct v4l2_pix_format {
    __u32                                  width;
    __u32                                  height;
    __u32                                  pixelformat;  //{V4L2_PIX_FMT_MJPEG, V4L2_PIX_FMT_YUYV ...}
    enum v4l2_field                 field;
    __u32                                  bytesperline; //表示每一行的字节数 /* for padding, zero if unused */
    __u32                                  sizeimage;    //表示图像所占的存储空间的大小
    enum v4l2_colorspace    colorspace;
    __u32                                  priv;                 /* private data, depends on pixelformat */
};

struct v4l2_format fmt;
使用ioctl(fd, VIDIOC_S_FMT, &fmt);

5)设置视频的帧率

struct v4l2_streamparm {
    enum v4l2_buf_type type;     //V4L2_BUF_TYPE_VIDEO_CAPTURE
    union {
        struct v4l2_captureparm    capture;
        struct v4l2_outputparm      output;
        __u8                                       raw_data[200];  /* user-defined */
    } parm;
};

struct v4l2_captureparm {
    __u32                  capability;      /*  Supported modes */
    __u32                  capturemode;      //采集模式,采集高质量图片值为1,一般设为0
    struct v4l2_fract  timeperframe;     /*  Time per frame in .1us units */
    __u32                   extendedmode;  /*  Driver-specific extensions */
    __u32                   readbuffers;        /*  # of buffers for read */
    __u32                   reserved[4];
};
struct v4l2_streamparm parm;

使用ioctl(fd, VIDIOC_S_PARM,&parm);

6)设置视频的旋转方式,使用ioctl(fd, VIDIOC_S_CTRL, &ctrl);


4、向驱动申请视频流数据的帧缓冲区

1)申请若干个帧缓冲区,每个帧缓冲区存放一帧视频数据,这些帧缓冲区在内核空间

struct v4l2_requestbuffers {
    __u32                              count;
    enum v4l2_buf_type      type;        //V4L2_BUF_TYPE_VIDEO_CAPTURE
    enum v4l2_memory      memory; //{V4L2_MEMORY_MMAP, V4L2_MEMORY_USERPTR, V4L2_MEMORY_OVERLAY}
    __u32                               reserved[2];
};

struct v4l2_requestbuffers req;

ioctl(fd, VIDIOC_REQBUFS, &req);

2)查询帧缓冲区在内核空间的长度和偏移量

struct v4l2_buffer {
    __u32                               index;
    enum v4l2_buf_type      type;
    __u32                               bytesused;
    __u32                               flags;
    enum v4l2_field              field;
    struct timeval                   timestamp;
    struct v4l2_timecode     timecode;
    __u32                               sequence;
    /* memory location */
    enum v4l2_memory       memory;
    union {
        __u32                  offset;
        unsigned long   userptr;
    } m;
    __u32                               length;
    __u32                               input;
    __u32                               reserved;
};

struct v4l2_buffer req;

ioctl(fd, VIDIOC_QUERY_BUF, &req);


5、应用程序通过内存映射,将帧缓冲区的地址映射到用户空间,这样就可以直接操作采集到的帧数据流,而不必去复制

buffer[i].start = mmap(NULL, buffers[i].length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buffers[i].offset);

6、将申请到的帧缓冲全部放入视频采集输入队列,以便存放采集的数据。ioctl(fd, VIDIOC_QBUF, &buf);

7、开始视频流数据的采集。ioctl(fd, VIDIOC_STREAMON, &type);

在驱动程序处理视频的过程中,定义了两个队列:视频采集输入队列和视频采集输出队列,前者是等待驱动存放视频数据的队列,后者是驱动程序已经放入了视频数据的队列

应用程序需要将上述帧缓冲在视频采集输入队列排队,然后可以启动视频采集。

8、驱动将采集到的一帧视频数据存入输入队列第一个帧缓冲区,一帧数据采集完后,驱动程序将该帧缓冲区移至视频采集输出队列,等待应用程序从输出队列中取出,驱动

程序接下来采集下一帧数据,放入第二个帧缓冲区,同样帧缓冲区存满下一帧数据后被放入视频采集输出队列

驱动程序做的事,从输入队列中取一块buffer往里面填数据,填满之后将整块buffer移至输出队列(输入队列链表减小,输出链表变大)

应用程序做的事,DQBUF则从输出队列取出一块buffer(输出队列变小);QBUF则将一块buffer放入输入队列中(输入队列变大)。

9、应用程序从视频采集输出队列中取出已含有采集数据的帧缓冲区。ioctl(fd, VIDIOC_DQBUF, &buf);应用程序处理该帧缓冲区的原始视频数据

10、处理完后,应用程序将该帧缓冲区重新排入输入队列,这样便可以循环采集数据。ioctl(fd, VIDIOC_QBUF, &buf);

重复上述步骤8到10,直到停止采集数据。

11、停止视频的采集。ioctl(fd, VIDIOC_STREAMOFF, &type);

12、释放申请的视频缓冲区unmap,关闭视频设备文件close(fd);



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luckywang1103

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值