当前位置: 首页 > news >正文

Android Camera预览实现方案总结

前言:

开发过camera apk的人可能都听过SurfaceView、SurfaceTexture、GLSurfaceView、TextureView等等这些东西,刚接触的时候可能很懵,到底为啥会有这么些View?到底有什么区别?哪些场景用哪些好一点?

博主也做了很长时间的Camera开发,惭愧!知道的也不多,不深入,仅仅记录下最新的理解,方便日后更新总结,也给初探者一点点帮助。

进入正题:

无论哪种预览方案,都离不开Surface这个对象,App将Surface传递给CameraServer,CameraServer拿到GraphicBuffer对应的buffer_handle,继续传给HAL,HAL再对buffer_handle进行映射,拿到buffer地址,往该地址上填充数据。数据填充完返回上层,要么是回到SurfaceTexture(onFrameAvailable),要么就是回到BLASTBufferQueue(onFrameAvailable)...

SurfaceView、SurfaceTexture、GLSurfaceView、TextureView、ImageReader这些东西的背后都是BufferQueue,BufferQueue就是一个生产者--消费者模型。生产者就是surface(对相机而言,本质的生产者就是camera),消费者就是所有onFrameAvailable实现的地方(以上各个组件有的不一样,有的实质上一样的)。

SurfaceView:

surfaceview是很常用的相机预览方案,我们直接通过getHolder.getSurface就可以获取surface,阅读SurfaceView源码可以看到,SurfaceView有个成员就是BLASTBufferQueue,BLASTBufferQueue就是背后的生产者消费者模型,底层填充完buffer数据之后也是直接回到BLASTBufferQueue里面的onFrameAvailable,继续调用到SurfaceFlinger。

所以SurfaceView这种预览方式而言,预览数据对app来说完全是个黑盒,完全无感,app开发者完全摸不到预览数据在哪,这也是为啥surfaceview很好用,但是理解不深的原因。

SurfaceView非常适合的场景就是扫码之类的应用,这些应用不需要对预览数据进行二次处理,仅仅显示源数据。

SurfaceTexture+GLSurfaceView:

这两个是需要放在一起的,单独讲并不好讲。

GLSurfaceView是SurfaceView的子类,比SurfaceView多的是内部创建了EGL环境,开发者不需要自己创建EGL环境了。

SurfaceTexture背后也是一个生产者消费者模型,但是更多的时候一些纹理和Image的操作,创建KHRImage,绑定Image这些。

SurfaceTexture、GLSurfaceView背后都有一个生产者消费者模型,他们是怎么分工的呢?

对于相机预览,我们先创建纹理,再用纹理创建SurfaceTexture,再用SurfaceTexture创建Surface,将Surface下发给Camera就行了,相机数据生产完成之后通过onFrameAvailable回到应用,应用收到每一帧的预览回调(注意不是预览数据)。所以可以看到SurfaceTexture能拿到预览回调了,比SurfaceView貌似高级一点了。到这里我们总结一下,SurfaceTexture就是预览数据的载体,SurfaceTexture就是这个阶段的消费者。

SurfaceTexture预览数据的载体了,但是预览怎么显示呢?那就是GLSurfaceView的事情了,GLSurfaceView背后也是生产者消费者模型,这时候生产者可以理解成SurfaceTexture了,因为数据从它这来;消费者就是BLASTBufferQueue里面的onFrameAvailable(最终是SurfaceFlinger)

具体opengl的绘制这些就不细讲了。

SurfaceTexture+GLSurfaceView适合那种对预览进行二次处理的场景,单也仅仅是opengl方式的处理,因为上面提到SurfaceTexture收到每一帧的预览回调(注意不是预览数据),我们起初绑定的也仅仅是个纹理id

TextureView:

再来看看TextureView,相对前面的两种,TextureView用的比较少了。通过名字也能看出它是含有纹理的,阅读源码看到TextureView里面有个成员就是SurfaceTexture,所以和SurfaceTexture+GLSurfaceView的预览方式有相同之处,就是都是通过SurfaceTexture从相机获取数据;不同的是TextureView继承自普通View,绘制流程是通过draw函数一路下去的,具体也没怎么看懂,先记着。

ImageReader+GLSurfaceView:

再来看看ImageReader,这是Camera Api2里面常用的一个类了,Camera Api2里面拍照的话是一定要用到这玩意的(其他方式可能也有,但是没见过),那么预览可不可以用ImageReader呢?当然是可以的。

ImageReader的背后同样也是生产者--消费者模型。

ImageReader非常灵活的是可以自己定义需要的数据格式(yuv,jpg,raw),那么预览的时候我就定义一个yuv格式的,然后将ImageReader.getSurface 获取surface传给相机。

ImageReader的onFrameAvailable回掉拿到的是实实在在的yuv数据,那好了,app想做什么算法都可以,可以先做CPU的算法在做GPU的算法。

yuv数据可以通过khr的一些接口绑定到纹理上,再用GLSurfaceView绘制显示。

总结:

以上就是一点简单的总结,当然预览方案不仅仅就这些。比如GLSurfaceView和SurfaceView相比就是多了EGL环境创建,那我们完全可以自己创建环境。那么SurfaceTexture+SurfaceView、ImageReader+SurfaceView的方案也是可行的。

总的来说,知道他们背后都是生产者--消费者模型这条主线就行了,生产者就是各种方式获取的surface,消费者就是onFrameAvailable实现的地方。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • P3423 [POI2005] BAN-Bank Notes
  • MySQL之事务
  • 数据库管理-第229期 Oracle全球分布式数据库-深入1(20240814)
  • C# NX二次开发-曲线投影到面上
  • 《密码编码学与网络安全原理与实践》第八章伪随机数与流密码
  • Linux第六章---thrift
  • centos7安装Oracle 11g数据库
  • 代码随想录算法训练营day41|动态规划part08
  • 【Unity打包Android】Gradle报错,Deprecated Gradle features were used in this build ···
  • Windows的cmd命令行使用Linux类命令
  • C语言memcmp函数
  • c++中加不加const的值传递和引用传递的区别
  • How to import openai package using jupyter notebook?
  • Dav_笔记13:SQL Access Advisor 之 2 使用SQL Access Advisor-3
  • Linux-Shell三剑客grep,awk,sed-08
  • $translatePartialLoader加载失败及解决方式
  • Angular6错误 Service: No provider for Renderer2
  • java 多线程基础, 我觉得还是有必要看看的
  • Java多态
  • leetcode98. Validate Binary Search Tree
  • Phpstorm怎样批量删除空行?
  • Python进阶细节
  • Rancher-k8s加速安装文档
  • 大数据与云计算学习:数据分析(二)
  • 如何优雅地使用 Sublime Text
  • 使用SAX解析XML
  • 系统认识JavaScript正则表达式
  • 继 XDL 之后,阿里妈妈开源大规模分布式图表征学习框架 Euler ...
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ‌U盘闪一下就没了?‌如何有效恢复数据
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • #android不同版本废弃api,新api。
  • #进阶:轻量级ORM框架Dapper的使用教程与原理详解
  • $L^p$ 调和函数恒为零
  • (C语言)strcpy与strcpy详解,与模拟实现
  • (二十九)STL map容器(映射)与STL pair容器(值对)
  • (黑马点评)二、短信登录功能实现
  • (简单) HDU 2612 Find a way,BFS。
  • (剑指Offer)面试题34:丑数
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (南京观海微电子)——COF介绍
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • *_zh_CN.properties 国际化资源文件 struts 防乱码等
  • .form文件_一篇文章学会文件上传
  • .net 8 发布了,试下微软最近强推的MAUI
  • .Net CF下精确的计时器
  • .NET Reactor简单使用教程
  • .net 受管制代码
  • .NETCORE 开发登录接口MFA谷歌多因子身份验证
  • @PreAuthorize注解
  • @RequestMapping 和 @GetMapping等子注解的区别及其用法
  • [\u4e00-\u9fa5] //匹配中文字符
  • [Android 数据通信] android cmwap接入点
  • [BJDCTF2020]The mystery of ip1
  • [Django开源学习 1]django-vue-admin