推广

Android 利用V4L2 调用camera

iseeyu2年前 (2024-02-22)推广125

image.png

这里我们只考虑应用程序如何调用V4L2接口。V4L2本身就是一个字符设备,跟其他字符设备驱动一样,其实使用V4L2只要3个接口:

  • open :打开设备文件
  • ioclt : 设置或获取camera相关参数,读写控制等
  • mmap: 内存映射, 用户空间通过内存映射获取到camera的数据
  • close:关闭设备文件描述符

详细的内容可以参考官网
http://v4l.videotechnology.com/dwg/
下面介绍的只是一个使用的demo,demo代码可参考
https://github.com/yizhongliu/AnV4L2Camera

V4L2 采集camera数据

下面是应用利用V4L2 采集camera数据的大体流程:

v4l2camera.png

  • 打开文件描述符
int open(constchar *device_name, int flags);

跟打开其他的设备文件是一样的,camera的设备节点是/dev/video*

int fd=open("/dev/video0",O_RDWR, 0);// 打开设备
  • 获取camera的参数
    先直观地了解下用v4l2获取camera的参数的格式
:~/software/squashfs-root$ v4l2-ctl -d0 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
    Index       : 0
    Type        : Video Capture
    Pixel Format: 'MJPG' (compressed)
    Name        : Motion-JPEG
        Size: Discrete 1280x720
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 848x480
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 960x540
            Interval: Discrete 0.033s (30.000 fps)

    Index       : 1
    Type        : Video Capture
    Pixel Format: 'YUYV'
    Name        : YUYV 4:2:2
        Size: Discrete 640x480
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 160x120
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 320x180
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 320x240
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 424x240
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 640x360
            Interval: Discrete 0.033s (30.000 fps)

这是在电脑上面用命令获取到的打印,可以看到组织的方式是 第一层是支持的图像格式, 第二层是支持的分辨率,第三层的帧率,所以我们写代码时是先去获取支持的图片格式,再用图片格式去获取该格式下支持的分辨率,再利用图片格式和
分辨率去获取该条件下支持的帧率

获取支持的格式:

struct v4l2_fmtdesc fmtd;
fmtd.index = i;
fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_ENUM_FMT, &fmtd) < 0)
    break;

获取支持的分辨率

struct v4l2_frmsizeenum  frmsize;
frmsize.index = j;
frmsize.pixel_format = fmtd.pixelformat;
if (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) < 0)
    break;

获取支持的帧率

struct v4l2_frmivalenum  framival;
framival.index = k;
framival.pixel_format = fmtd.pixelformat;
framival.width = frmsize.discrete.width;
framival.height = frmsize.discrete.height;
if (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &framival) < 0)
       break;
  • 设置camera参数
    这里主要设置视频的格式,宽高等
struct v4l2_format format;
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
format.fmt.pix.width = width;
format.fmt.pix.height = height;
format.fmt.pix.pixelformat = pixelformat;

// MUST set
format.fmt.pix.field = V4L2_FIELD_ANY;

ret = ioctl(fd, VIDIOC_S_FMT, &format);
if (ret < 0) {
    ALOGE("Unable to set format: %s", strerror(errno));
    return -1;
}
  • 申请帧缓冲区

V4L2支持内存映射方式(mmap)和直接读取方式(read)来采集数据,前者一般用于连续视频数据的采集,后者常用于静态图片数据的采集,这里只讨论内存映射方式的视频采集。

视频数据采集过程有两个队列,一个输入队列和一个输出队列。视频开始采集后,启动视频采集后,驱动程序开始采集一帧数据,把采集的数据放入视频采集输入队列的第一个帧缓冲区,一帧数据采集完成后,驱动程序将该帧缓冲区移至视频采集输出队列。应用程序从输出队列中获取数据,处理完后将缓冲区放到输入队列的队尾。

1353038230_2495.png

    /* V4L2: request buffers, only 1 frame */
    rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    rb.memory = V4L2_MEMORY_MMAP;
    rb.count = 1;

    ret = ioctl(fd, VIDIOC_REQBUFS, &rb);
    if (ret < 0) {
        ALOGE("Unable request buffers: %s", strerror(errno));
        return -1;
    }

    /* V4L2: map buffer  */
    memset(&buf, 0, sizeof(struct v4l2_buffer));

    buf.index = 0;
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;

    ret = ioctl(fd, VIDIOC_QUERYBUF, &buf);
    if (ret < 0) {
        ALOGE("Unable query buffer: %s", strerror(errno));
        return -1;
    }

    /* Only map one */
    mem = (unsigned char *)mmap(0, buf.length, PROT_READ | PROT_WRITE, 
                MAP_SHARED, fd, buf.m.offset);
    if (mem == MAP_FAILED) {
        ALOGE("Unable map buffer: %s", strerror(errno));
        return -1;
    }

    /* V4L2: queue buffer */
    ret = ioctl(fd, VIDIOC_QBUF, &buf);

这里是先申请了帧缓冲队列,只申请了一个,然后查询buff是否申请成功,最后做了内存映射,这里只用了一个buf,多个的话需要映射多个buf。最后一步ioctl(fd, VIDIOC_QBUF, &buf)是把缓冲区放到视频输入采集队列。

  • 开始数据采集
 enum v4l2_buf_type type;
 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 ret = ioctl(fd, VIDIOC_STREAMON, &type);
  • 循环数据采集处理
    一般会起一个线程对数据进行采集处理
int V4L2Camera::GrabRawFrame(void *raw_base)
{
    int ret;

    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;

    /* V4L2: dequeue buffer */
    ret = ioctl(fd, VIDIOC_DQBUF, &buf);
    if (ret < 0) {
        ALOGE("Unable query buffer: %s", strerror(errno));
        return ret;
    }
    ALOGD("copy size :%d", buf.bytesused);

    /* copy to userspace */
    memcpy(raw_base, mem,  buf.bytesused);

    /* V4l2: queue buffer again after that */
    ret = ioctl(fd, VIDIOC_QBUF, &buf);
    if (ret < 0) {
        ALOGE("Unable query buffer: %s", strerror(errno));
        return ret;
    }

    return 0;
}

这里的处理方法是先取出视频输出队列的一个缓冲区,将数据拷贝到raw_base, 最后将缓冲区放到视频输入队列

  • 结束数据采集
    enum v4l2_buf_type type;
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
  • 关闭文件描述符
close(fd)

关于demo中jni和视频显示部分,可以参考我的专题里面的介绍
Android FFmpeg专题结构

另外需要Video4Linux Programming.pdf可以在底下留言,留下邮箱

https://www.cnblogs.com/zhangsx/p/5803162.html
https://blog.csdn.net/li123128/article/details/89499935

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://0291.com.cn/post/56376.html

相关文章

重新申请淘宝账号要多久(邮箱注册淘宝号流程)

重新申请淘宝账号要多久(邮箱注册淘宝号流程)

  笔者因账号原因,需要重新注册淘宝账号,但是本人只有一个手机号,于是就想到了用邮箱注册,但是淘宝注册打开的时候却提示需要输入手机号,其实,输入手机号后还是可以用邮箱注册的,那么,如何用邮箱注册淘宝账号呢?今天就给大家分享一下!   进入淘宝网登录页面,点击“免费注册”      输入手机...

营销技巧:相比较讲产品的优点,更有效的是要向客户展示使用效果

营销技巧:相比较讲产品的优点,更有效的是要向客户展示使用效果

:相比较讲产品的优点,更有效的是要向客户展示使用效果 很多销售员都天然地认为,一定要向客户展示产品的优点,产品多好,功能多全,样式多新,价格多实惠,这样才能打动到客户。可事实上,结果远不是如此,相比较讲产品的优点,更有效的是要向客户展示使用效果。 乔布斯在推出第一款轻便苹果...

拼多多免单免的是什么?揭秘你不知道的购物秘籍!

拼多多免单免的是什么?揭秘你不知道的购物秘籍!

近年来,拼多多这个电商平台迅速崛起,其“免单”活动吸引了大量消费者。那么,拼多多免单免的到底是什么?让我们一起探讨这个话题,揭秘你不知道的购物秘籍! 一、拼多多免单是什么? 拼多多免单,顾名思义,就是在购物过程中,部分商品或者全额商品价格被免除,消费者无需支付费用即可获得商品。这种...

拼多多免单后什么时候退款?揭秘你不知道的秘密!

拼多多免单后什么时候退款?揭秘你不知道的秘密!

随着电商平台的发展,越来越多的消费者选择在拼多多购物,尤其是遇到免单活动时,抢购热情更是空前高涨。但是,免单后什么时候退款成了大家关心的问题。那么,拼多多免单后什么时候退款呢?本文将为你揭秘这一话题,带你了解你不知道的秘密! 一、拼多多免单活动概述 拼多多作为国内知名的电商平台,经...

美女、风景还是体验?——短视频时代的航司品牌营销策略思考

美女、风景还是体验?——短视频时代的航司品牌营销策略思考

从2020年起互联网已经从图文进化到了视频,其中短视频又成为了传播最快,流量最大的媒介。无一例外航旅届的各个行业也都开始在短视频平台发力,一方面塑造传播自身形象,一方面试图将这一新兴媒介变成新的销售,不论是酒店还是景区在抖音、小红书等都已经屡见不鲜。那么同为大领域的航司呢?...

ROG 魔霸新锐 2022怎么样,怎么选?实际使用感受如何 ...

ROG 魔霸新锐 2022怎么样,怎么选?实际使用感受如何 ...

ROG 魔霸新锐 2022怎么样,怎么选?实际使用感受如何 ......

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片