前言
一直从事Android相机相关的开发,我们知道相机预览离不开SurfaceView(当然使用GLSurfaceView + SurfaceTexture等方式也可以,本文先整理对SurfaceView的理解),通常用SurfaceView显示预览的步骤如下:
1、SurfaceView写入布局文件,加载的时候触发surfaceCreate
2、通过SurfaceView get SurfaceHolder,通过SurfaceHolder get Surface
3、将Surface传给Camera相关的API (Camera API1、API2使用方式不一样)
经过上面几步之后就可以显示预览画面了,虽然用法挺简单的,但是其背后的原理其实挺复杂的,许多从事相机app开发的都不一定能讲清楚。
首先我们先提出几个疑问?
1、Surface到底是什么?
2、Camera的数据流转经过哪些模块
一、Surface是什么
在Android系统中,Surface是一种用于图形和视频渲染的抽象概念,它可以用来将应用程序绘制的图形或视频显示在屏幕上。一个Surface代表一个屏幕表面,可以是整个屏幕或者应用程序UI的一个独立窗口。
这是随便网上搜索的一段描述,大部分人看了还是不理解,其实我也不知道怎么用言语描述。从阅读源码来看,Surface不仅仅可以用来显示图像的,例如ImageReader你也可以获取他的Surface,将该Surface作为渲染对象给Camera,回来的是各种格式的数据,所以在我看来Surface就是一块可渲染的buffer,准确说Surface是一系列API封装,这些API会关联到GraphicBuffer。
BufferQueue:
要理解Surface就必须理解关联的几个类(只关注C++的,java的其实都是封装):
Surface:抽象概念,里面大部分方法封装了IGraphicBufferProducer调用
BufferQueue:主要方法就是createBufferQueue
BufferQueueCore:主要维护一个slot数组
BLASTBufferQueue:创建BufferQueueCore; 实现onFrameAvailable
IGraphicBufferProducer:生产者,主要是binder接口调用
IGraphicBufferConsumer:消费者,主要是binder接口调用
BufferQueueProducer:生产者,实现逻辑(dequeue,queue)
BufferQueueConsumer:消费者,实现逻辑(acquire, release)
关于BufferQueue先来一张经典的图:
生产者:先dequeue一块空闲buffer,往buffer里面填充数据,填充完成之后再queue(归还)buffer
消费者:归还buffer之后消费者将收到onFrameAvailable回调,进而acquire buffer,消费者可以是拿去显示,可以是保存成图像文件,消费完成之后 release
应用到camera 预览来讲,生产者包括 camera hal,camera server,消费自然就是camera app,终极消费者是SurfaceFlinger, HWC 就不深入追究了
对BufferQueue的整体理解:
如下图是代码学习过程的总结,有许多理解不到位的地方希望大家指出。
从上图可以看到核心是围绕BufferQueueCore,但是通过代码阅读发现BufferQueueCore 主要就是维护slot数组,关键代码流程其实没什么。主要逻辑在BLASTBufferQueue、BufferQueueProducer、BufferQueueConsumer。
红虚线是queueBuffer 之后onFrameAvailabe的流向。
BufferQueueProducer最终向Gralloc申请GraphicBuffer。
BLASTBufferQueue最终通过Transaction调用到SurfacFlinger。
所以,最后我们通过上图看Surface,Surface的位置并不那么显眼,Surface的背后是GraphicBuffer,GraphicBuffer由BufferQueue管理,BufferQueue运转基于CS模型;所以Surface是CS模型的一个代理,代表的就是生产者。