【v4l2】应用程序获取一帧并处理

来源:互联网 发布:nba变态数据 编辑:程序博客网 时间:2024/06/05 23:07


参考    http://blog.chinaunix.net/uid-23424741-id-3977591.html


2.3 分配内存
接下来可以为视频捕获分配内存:
struct v4l2_requestbuffers  req;
if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
  return -1;
}


v4l2_requestbuffers 结构如下:
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
    __u32               reserved[2];

};




2.4 获取并记录缓存的物理空间
使用VIDIOC_REQBUFS,我们获取了req.count个缓存,下一步通过调用VIDIOC_QUERYBUF命令来获取这些缓存的地址,然后使用mmap函数转换成应用程序中的绝对地址,最后把这段缓存放入缓存队列:



typedef struct VideoBuffer {
    void   *start;
    size_t  length;
} VideoBuffer;


VideoBuffer*          buffers = calloc( req.count, sizeof(*buffers) );

//作为一个与驱动程序交换数据的数据结构,用来辅助数据的导出,即v4l2_buf是作为中介,因为他可被驱动认识。在应用层,用一个指针数组来存储这许多帧。

//这里有个问题啊,我分配的内存,是给驱动设定缓冲的队列大小么?我每次都把数据全部出队?不是的,一次出队一个就好了。

struct v4l2_buffer    buf;


for (numBufs = 0; numBufs < req.count; numBufs++) {
    memset( &buf, 0, sizeof(buf) );
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;
    buf.index = numBufs;
    // 读取缓存

    if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {
        return -1;
    }


    //导出驱动层的数据到用户空间
    buffers[numBufs].length = buf.length;

    // 转换成相对地址
    buffers[numBufs].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE,
        MAP_SHARED,fd, buf.m.offset);


    if (buffers[numBufs].start == MAP_FAILED) {
        return -1;
    }


    // 放入缓存队列
    if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {
        return -1;
    }

}




这是官方的例子:

每次读取一帧,然后处理。

static intread_frame(void){        struct v4l2_buffer buf;unsigned int i;switch (io) {case IO_METHOD_READ:    if (-1 == read (fd, buffers[0].start, buffers[0].length)) {            switch (errno) {            case EAGAIN:                    return 0;case EIO:/* Could ignore EIO, see spec. *//* fall through */default:errno_exit ("read");}}    process_image (buffers[0].start);break;case IO_METHOD_MMAP://printf("###USE MMAP FOR CAPTURE ######\n"); //YESCLEAR (buf);            buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;            buf.memory = V4L2_MEMORY_MMAP;    if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {            switch (errno) {            case EAGAIN:                    return 0;case EIO:/* Could ignore EIO, see spec. *//* fall through */default:errno_exit ("VIDIOC_DQBUF");}}                assert (buf.index < n_buffers);        process_image (buffers[buf.index].start);if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))errno_exit ("VIDIOC_QBUF");break;case IO_METHOD_USERPTR:CLEAR (buf);    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    buf.memory = V4L2_MEMORY_USERPTR;if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {switch (errno) {case EAGAIN:return 0;case EIO:/* Could ignore EIO, see spec. *//* fall through */default:errno_exit ("VIDIOC_DQBUF");}}for (i = 0; i < n_buffers; ++i)if (buf.m.userptr == (unsigned long) buffers[i].start    && buf.length == buffers[i].length)break;assert (i < n_buffers);    process_image ((void *) buf.m.userptr);if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))errno_exit ("VIDIOC_QBUF");break;}return 1;}



0 0
原创粉丝点击