关于V4L2编程中获取视频流的误区

来源:互联网 发布:web数据挖掘第二版pdf 编辑:程序博客网 时间:2024/06/08 07:24

最近在做视频流的采集,然后保存成图片的形式,网上找的例程对映射缓存区的读取是这样的

struct v4l2_buffer buf;ioctl(fd, VIDIOC_DQBUF,&buf);process_image(usr_buf[buf.index].start, usr_buf[buf.index].length);//保存成图片的函数ioctl(fd, VIDIOC_QBUF,&buf);
但是看网上有的程序不是用的申请的缓存区的长度
usr_buf[buf.index].length
而是用的ioctl(fd, VIDIOC_DQBUF,&buf);读取回来的buf.bytesused
这两者的区别在哪呢?

1.先说一下

usr_buf[buf.index].length 是从哪里来的呢?在建立mmap的时候,用户层会向内核申请一部分的内存资源作为映射区,具体命令是
ioctl(fd,VIDIOC_QUERYBUF,&buf) ,具体内容如下
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;
};
其中标红的地方就是内核返回的消息,说明映射的这一片区域的大小。
2.那么在请求缓冲的视频帧的时候,
ioctl(fd, VIDIOC_DQBUF,&buf);
返回信息中的buf.bytesused 
就是实际占用的大小,如果你在保存的时候用的是
usr_buf[buf.index].length

那么得到的图片是一个固定大小的图片,并且很大,很多空间都是NULL填充的无效信息,因为length是指的是整个映射区域的大小,并不是实际用的大小,所以在存储的时候要采用buf.bytesused 存储实际用的字节数。
3.还有一个个人感觉很傻的问题,就是为什么每次保存的JPG图片的大小不一样。因为分辨率是一样的。为什么大小不一样呢?对图片格式小白的我理所当然的认为,应该一样大的。
其实jpg格式本身就是一种压缩格式化,每一张图片因为拍摄的图像不一样,压缩率肯定不一样。比如对一张白纸和对花花草草拍照,白纸要明显小得多,因为像素分布单一,压缩的比较厉害,所以就小的多。

原创粉丝点击