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实现的地方。

相关推荐
lxysbly16 分钟前
md模拟器安卓版带金手指2026
android
儿歌八万首1 小时前
硬核春节:用 Compose 打造“赛博鞭炮”
android·kotlin·compose·春节
消失的旧时光-19433 小时前
从 Kotlin 到 Dart:为什么 sealed 是处理「多种返回结果」的最佳方式?
android·开发语言·flutter·架构·kotlin·sealed
Jinkxs4 小时前
Gradle - 与Groovy/Kotlin DSL对比 构建脚本语言选择指南
android·开发语言·kotlin
&有梦想的咸鱼&4 小时前
Kotlin委托机制的底层实现深度解析(74)
android·开发语言·kotlin
LDORntKQH4 小时前
基于深度强化学习的混合动力汽车能量管理策略 1.利用DQN算法控制电池和发动机发电机组的功率分配 2
android
冬奇Lab4 小时前
Android 15 ServiceManager与Binder服务注册深度解析
android·源码·源码阅读
2501_916008896 小时前
深入解析iOS机审4.3原理与混淆实战方法
android·java·开发语言·ios·小程序·uni-app·iphone
独行soc7 小时前
2026年渗透测试面试题总结-20(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
常利兵7 小时前
2026年,Android开发已死?不,它正迎来黄金时代!
android