Android camera preview and take picture with V4l2

这部分spec的内容没有全看懂,但是根据FSL的代码能知道这其中的sequence,下面就结合着FSL的代码来描述下video overlay过程的sequence。

首先介绍一下video overlay,vieo overlay不同于video capture,是指不需要对video信号的帧进行copy,直接将视频信号转化成显卡的VGA信号或者将捕获到的视频帧直接存放在显卡的内存中,具体过程就是将视频帧直接写入framebuffer中,不需要经过android 平台的处理。实际上看过FSL的camera preview过程之后就知道,它就是直接将视频数据 写入framebuffer,而没有经过android的surfaceflinger的处理。Video overlay需要硬件的支持,必须是支持video overlay的camera才能使用这套overlay interface。

因为video overlay直接使用linux 的framebuffer来显示捕获到的image,所以和capture相比它更具有效率,而不是将捕获到的image拷贝以后通过其他的方式(android surfaceflinger)来显示。Viedo overlay只用来preview,又被称为framebuffer overlay或previwing。

从spec上来看,实际上video capture interface也能实现preview,只是没有overlay有效率,因为video capture是将数据经过copy以后由android surfaceflinger来控制进行显示(实际上最后surfaceflinger还是通过framebuffer来显示的)。

Video overlay和Video capture使用同样的device,overlay的功能只有在调用VIDIOC_S_FMT后才会有效。下面就看看overlay流程的sequcence。

1、open device

这部分同video capture,首先是要打开设备。如果是同时进行overlay和capture,应该尽量不使用同一个文件 描述符,比如说如果此时在overlay,要拍照的话应该再打开设备,使用一个分开的文件描述符来进行capture。如果driver支持同时进行overlay和capture的话,必须支持使用分开的文件描述符来分别进行overlay和capture 。

camera_device = open(VIDEO_DEVICE, O_RDWR)) ;

2、set output

对于这个设置 输出不是太理解,但overlay换个角度来说是将捕获的image重新组合成能在屏幕上显示的视频信号,在这里的设置输出应该是如果device有多个输出的话,选择一个输出来将数据输入到屏幕,也就是framebuffer。

ioctl(camera_device, VIDIOC_S_OUTPUT, &g_display_lcd) ;

3、set control[可选]

设置用户控制参数,FSL在这里使用了他们驱动自定义的控制参数,不是很理解这个参数设置是想实现什么操作,我觉得这个应该是可选的。

ioctl(camera_device, VIDIOC_S_CTRL, &ctl) ;

4、set crop

这个同video capture是一样的,只是type由V4L2_BUF_TYPE_VIDEO_CAPTURE换成了V4L2_BUF_TYPE_VIDEO_OVERLAY,然后是取景参数的设置:left,top,width,height。

ioctl(camera_device, VIDIOC_S_CROP, &crop) ;

5、set format

这个format应该是最后preview我们在屏幕上看到的image的格式,如果在video capture中,这个就是我们拍照时image的格式。

ioctl(camera_device, VIDIOC_S_FMT, fmt) ;

6、 get video std

这个我觉得肯定是可选的,取得当前视频标准

ioctl(camera_device, VIDIOC_G_STD, &id) ;

7、set stream param

设置流参数,这个和video capture是相同的,这里的param.type是V4L2_BUF_TYPE_VIDEO_CAPTURE,其中timeperframe的分母是需要设定的帧率,而分子是1。

ioctl(camera_device, VIDIOC_S_PARM, &parm) ;

[PS]这里补充一点stream param方面的spec:

一般来说当前的帧率是由当前的视频标准来决定的,如果默认采用视频标准的帧率就不需要设置流参数,但是如果想获得或者设定自己的帧率就需要使用VIDIOC_G_PARM, VIDIOC_S_PARM:

int ioctl(int fd, int request, v4l2_streamparm *argp);

struct v4l2_stramparam包含以下主要成员:

enum v4l2_buf_type type

union param

struct v4l2_captureparm capture

struct v4l2_outputparam output

//要注意的是在这里,不管是overaly还是capture,这里的buffer type都是选择的V4L2_BUF_TYPE_VIDEO_CAPTURE。

Struct v4l2_captureparam包含以下主要成员:

__u32 capturemode

//是否支持高质量图像捕捉

struct v4l2_fract timeperframe

//设置帧率,通过分母分子实现

这里要注意的是,通过 VIDIOC_S_PARM设置帧率不一定成功,driver会根据硬件限制来设置这些参数,所以一般设置以后可以通过VIDIOC_G_PARM来看设定是否成功。

前面从1-8都是设置overlay的参数,然后需要设置framebuufer的参数,framebuffer参数部分的设置通过VIDIOC_G_FBUF,VIDIOC_S_FBUF来实现,这里的参数也是比较复杂,具体可以去参照这个spec:http://v4l2spec.bytesex.org/spec/r10595.htm

我看FSL的代码,它也是采用了默认的framebuffer的参数,唯一的就是改变了一下flag:

ioctl(camera_device, VIDIOC_G_FBUF, &fb_v4l2) ;

fb_v4l2.flags = V4L2_FBUF_FLAG_OVERLAY;

ioctl(camera_device, VIDIOC_S_FBUF, &fb_v4l2) ;

在设置framebubffer参数之前,FSL打开了framebuffer设备,并对屏幕进行了一系列的配置,因为overlay状态下是直接写屏,所以它这里加入了对framebuffer设备的配置工作。

完成这一系列的配置以后通过调用overlay即开始了overlay过程,在这里overlay的数为0时为关闭overlay,为1时为打开overlay。

ioctl(camera_device, VIDIOC_OVERLAY, &overlay) ;

实际上看FSL的preview代码,虽然也加入了线程的概念,但线程内没有作什么实际性的内容,在preview线程起来之前,overlay实际上已经开始了。个人觉得这个preview线程是一个多余的操作。而且它也没有用到android内部的memory,因此在overlay preview的启动过程中对initHeapLocked()的调用也完全是多余的,没有进行实质性的操作。由此可见FSL code完全就是通过linux和v4l2来实现了camera preview的功能,甚至连previewcallback都省去了。
FSL camera take picture with v4l2

首先说明一下可能是因为FSL 的camera 不支持autofocus ,所以它没有实现对autofocus 的支持,autofucus 线程直接调用了callback ,没有进行操作。

FSL 对拍照提供了一套它自己的jpeg 编码,获得的数据可以进行jpeg 编码,也可以直接将捕获的raw data 以call back 返回。Take picture 是建立在preview 的基础 上的,实际上就是将preview 中捕获的某个image 保存下来。在FSL code 中是在overlay 的基础上,重新打开设备,在新的文件描述符上设置take picture 相关的参数,从设备中读到数据以后,再将参数还原到overlay 的状态。下面我们看看take picture 的sequence :

1 、shutter callback

因为拍照是通过快门事件激发的,所以首先会调用mShutterCallback ;

2 、open device

打开一个新的文件描述符来进行take picture 的操作

3 、set format

设置capture 的image format ,可以看看它对参数的设置:

fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

fmt.fmt.pix.pixelformat = g_still_pixelformat;

fmt.fmt.pix.width = g_width;

fmt.fmt.pix.height = g_height;

fmt.fmt.pix.sizeimage = fmt.fmt.pix.width * fmt.fmt.pix.height * g_still_bpp / 8;

fmt.fmt.pix.bytesperline = g_width * g_still_bpp / 8;

其中bpp 是每个像素所占有的比特位

ioctl(fd_v4l, VIDIOC_S_FMT, &fmt) ;

4 、set crop

同样可以看看设置的crop parameter :

crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

crop.c.left = 0;

crop.c.top = 0;

crop.c.width = g_width;

crop.c.height = g_height;

ioctl(fd_v4l, VIDIOC_S_CROP, &crop) ;

5 、set stream paramter

parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

parm.parm.capture.timeperframe.numerator = 1;

parm.parm.capture.timeperframe.denominator = g_still_camera_framerate;

parm.parm.capture.capturemode = g_capture_mode;

ioctl(fd_v4l, VIDIOC_S_PARM, &parm) ;

6 、read image data

read(camera_device, buf1, fmt.fmt.pix.sizeimage) ;

这里存在一点疑问,这个camera_device 中的数据是从何而来的,根据v4l2 协议 就是当前overlay 到的数据么?

7 、将数据直接以rawcallback 返回或者压缩成jpeg 返回。

在Android平台通过V4L2接口获取video流 本文介绍了通过v4l2接口获取video数据的主要步骤。在android平台camera hal层调用v4l2接口实现video功能。根据android camera hal接口逻辑把v4l2接口的调用分为如下步骤。四大主要步骤:枚举码流格式,分辨率,帧率信息配置流参数和初始化buffer启动流并获取数据关闭流和反初始化buffer。 阅读详情

相关推荐

v4l2视频驱动使用步骤

1.      打开设备 1)用非阻塞模式打开摄像头设备 int cameraFd; cameraFd = open("/dev/video0", O_RDWR | O_NONBLOCK); 2)如果用阻塞模式打开摄像头设备,上述代码变为: cameraFd = open("/dev/video0", O_RDWR); 关于阻塞模式和非阻塞模式: 应用程序能够使用阻塞模式或非阻塞模式

qq785231745的专栏 1758

V4L2_CAP_VIDEO_CAPTURE

V4L2_CAP_VIDEO_CAPTURE

我的博客 1069

USB摄像头通过v4l2技术采集、储存视频

Linux下通过v4l2技术采集USB摄像头的视频,然后通过x264编码器编码成视频储存起来

v4l2接口解析和摄像头数据采集

V4L2接口解析 操作步骤 应用程序通过V4L2接口采集视频数据步骤 打开视频设备文件,通过视频采集的参数初始化,通过V4L2接口设置视频图像属性。 申请若干视频采集的帧缓存区,并将这些帧缓冲区从内核空间映射到用户空间,便于应用程序读取/处理视频数据。 将申请到的帧缓冲区在视频采集输入队列排队,并启动视频采集。 驱动开始视频数据的采集,应用程序从视频采集输出队列中取出帧缓冲区,处理后,将帧缓冲区重新放入视频采集输入队列,循环往复采集连续的视频数据。 停止视频采集。 具体实现如下图 图中文字 打开视.

转载和创作优秀的博客 7492

python爬虫自动下载网页链接

需求分析 今天遇到一个简单的需求,需要下载澳大利亚电力市场NEM日前市场的发电商报价数据(http://nemweb.com.au/Reports/Current/Next_Day_Offer_Energy/),页面观感是这样的: Ctrl + F 一下,看到一共有395个zip链接。于是就想着用python爬虫自动下载。这个网页很简单,没有验证码,甚至不需要登录,因此自动下载的pytho...

da_kao_la的博客 1万+

SpringBoot实战——仿b站项目(一)

热部署就是当应用程序这种运行的时候升级冉家或者修改某一部分代码、配置文件时,无需手动启动应用,即可修改的部分生效工具 + IDEA配置。

weixin_52880572的博客 3453

Android overlay 学习 二 Android camera preview and take picture with V4l2

这部分spec的内容没有全看懂,但是根据FSL的代码能知道这其中的sequence,下面就结合着FSL的代码来描述下video overlay过程的sequence。 首先介绍一下video overlay,vieo overlay不同于video capture,是指不需要对video信号的帧进行copy,直接将视频信号转化成显卡的VGA信号或者将捕获到的视频帧直接存放在显卡的内存中,具体过程...

java-admin 338

记录LeNet的硬件加速器设计(一)

LeNet的硬件加速器设计实现。

2301_81029398的博客 3543

Android overlay 学习二 Android camera preview and take picture with V4l2

这部分spec的内容没有全看懂,但是根据FSL的代码能知道这其中的sequence,下面就结合着FSL的代码来描述下video overlay过程的sequence。 首先介绍一下video overlay,vieo overlay不同于video capture,是指不

魔戒 2815

Axure原型模板与元件库APP交互设计素材(附资料)

在Axure中,手机模型是展示APP或小程序界面效果的重要工具。通过导入手机模型元件,设计师可以更加直观地模拟真实设备的显示效果,从而更准确地评估设计的可行性和用户体验。Axure官方及第三方资源库中提供了多种品牌和型号的手机模型,如iPhone、Android等,设计师可以根据项目需求选择合适的模型进行使用。Axure作为一款强大的原型设计工具,为APP和小程序的设计与开发提供了丰富的界面组件元件库和交互设计素材。

招风的黑耳优快云 1976

RocketMQ源码分析之消息轨迹

文章目录前言一、消息轨迹二、消息轨迹源码分析1、producer端2、consumer端三、消息轨迹中存储的信息1.TraceContext2.TraceBean3.TraceType四、总结 前言   本篇文章将会从以下方面介绍消息轨迹:什么是消息轨迹?如何启用消息轨迹?示例demo、消息轨迹的源码分析和消息轨迹中存储的信息。最后会用一张图来总结消息轨迹的工作原理。 一、消息轨迹 1.什么是消息轨迹? 消息轨迹是用来跟踪记录消息发送、消息消费的轨迹。 2.如何启用消息轨迹? broker端 需要在b

不爱学习的小妞博客 1075
上一篇: V4L2摄像头获取单幅图片测试程序(MMAP模式)
下一篇: 标准RTSP 消息的错误代码
ai_longyu
博客等级 码龄15年 9粉丝 209原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值