SurfaceView | GLSurfaceview | SurfaceTexture | TextureView学习记录

791 阅读5分钟

1 SurfaceView

1 Surface

Surface 是一块用于填充图像数据的内存空间,例如你可以使用 SurfaceView 的 Surface 接收每一帧预览数据用于显示预览画面,也可以使用 ImageReader 的 Surface 接收 JPEG 或 YUV 数据。每一个 Surface 都可以有自己的尺寸和数据格式,你可以从 CameraCharacteristics 获取某一个数据格式支持的尺寸列表。

英文直译:表面

由源码可以得知:

  1. Surface是用来处理屏幕显示内容合成器所管理的原始缓存区工具
  2. Surface通常由SurfaceTexture或者MediaRecord来创建(消费者
  3. Surface最后显示在MediaPlayer或者CameraDevice上(生产者
  4. 通过Surface可以获得管理原始缓存区的数据
  5. 原始缓存区(rawbuffer)是用来保存当前窗口的像素数据

2 SurfaceView

extends MockView/View

一个有自己独立Surface、Window的view,负责把surface显示在屏幕的合适位置。通过控制surface的格式、大小等,可以看到surface的部分或者全部内容。

由于相机预览对更新速度和帧率要求较高,通常使用SurfaceView更新画面,以免普通View阻塞UI线程,优点如下:

  1. 不与其他普通的view共享Surface,在独立的线程绘制
  2. SurfaceView底层实现了双缓冲机制,解决了反复局部刷新带来的闪烁问题。双缓冲机制会及时把要处理的图像在内存中处理后,先画到一个内存区域,然后再整体绘制处理,显示在屏幕上。

缺点~~~~:因为这个Surface不在View hierachy中,它的显示也不受View的属性控制,所以不能进行平移,缩放等变换,也不能放在其它ViewGroup中,一些View中的特性也无法使用。


SurfaceView 采用与其他 View 相同的布局参数,因此可以像对待其他任何 View 一样对其进行操作,但 SurfaceView 的内容是透明的。

SurfaceView和Activity生命周期

如需在创建或销毁 Surface 时收到回调,请使用 SurfaceHolder 接口。↓

3 SurfaceHolder

给持有Surface对象(通常是surfaceview这个类)来使用的抽象接口,通过这个接口控制surface的大小和格式,编辑surface中的像素和监听surface变化。

三者关系:

image.png

2 GLSurfaceView

extends SurfaceView

 /** 

 * SurfaceView 的一种实现,它使用专用Surface来显示 OpenGL 渲染。  

*

 * A GLSurfaceView provides the following features: 

 * <li>管理一个Surface(一块特殊的内存,可以合成到 Android 视图系统中)。 

 * <li>管理 EGL 显示,使 OpenGL 能够渲染到Surface。 

 * <li>接受用户提供的进行实际渲染的 Renderer 对象。 

 * <li>在专用线程上渲染以将渲染性能与 主线程 分离 。

 * <li>支持按需和连续渲染。 

 * <li>可选择包装、跟踪、和/或错误检查渲染器的 OpenGL 调用。 

 * 

*/

加入了EGL(OpenGL ES:EGL接口解析与理解)管理,并且自带渲染线程,定义了用户需要实现的Render接口负责实际渲染。

由如下类图可知,类似SurfaceView的SurfaceHolder提供了一些操作Surface的接口,GLSurfaceView中的EglHelper实现了管理EGL环境的工作,GLThread作为渲染线程。

3 SurfaceTexture

mp.weixin.qq.com/s/w6B38KLK1…

SurfaceTexture 是 Surface 和 OpenGL ES (GLES) 纹理的组合。SurfaceTexture 实例用于提供输出到 GLES 纹理的接口。

SurfaceTexture 是一个BufferQueue的消费者。

并不是一个View,有自己的BufferQueue,可以用来生成Surface,传入到SurfaceTexture中的Buffer会被转化成GL纹理(纹理是一些数据,需要附加到View上才能显示),这个纹理交给TextureView或者GLSurfaceview进行显示。

用来从图像流中捕获帧,作为 OpenGL ES 纹理,图像流可能来自相机预览或视频解码。

不同于 SurfaceView 会将图像显示在屏幕上,SurfaceTexture 对图像流的处理并不直接显示,而是转为 GL 外部纹理。

可用于图像流数据的二次处理(如Camera滤镜,桌面特效等)

输出目标是Camera或MediaPlayer时可以用SurfaceTexture代替SurfaceHolder

前面提到的,

  1. Surface通常由SurfaceTexture或者MediaRecord来创建(消费者)
  2. Surface最后显示在MediaPlayer或者CameraDevice上(生产者)

4 TextureView

TextureView 本质上是 SurfaceTexture 的 View 封装

TextureView 可用于显示内容流。例如,这样的内容流可以是视频或 OpenGL 场景。内容流可以来自应用程序的进程以及远程进程。

SurfaceView本身的输出不是通过Android的UI Renderer(HWUI),而是直接走系统的窗口合成器SurfaceFlinger,所以无法实现对普通view的完全兼容。

与SurfaceView不同,TextureView不会再WMS中单独创建窗口,而是作为一个普通的View,因此TextureView可以和普通View一样进行平移、旋转、缩放、动画等。

通过 SurfaceTextureListener监听 SurfaceTexture 的各种状态

缺点:

因为 TextureView 需要通过 UI Renderer 输出,也导致了新的问题的出现。除了性能比较 SurfaceView 会有明显下降外(低端机,高 GPU 负荷场景可能存在 15% 左右的帧率下降),另外因为需要在三个线程之间进行写读同步(包括 CPU 和 GPU 的同步),当同步失调的时候,比较容易出现掉帧或者吞帧导致的卡顿和抖动现象。

5 BufferQueue

BufferQueue 学习总结(内附动态图)

Gralloc

gralloc是Android中负责申请和释放GraphicBuffer的HAL层模块,由硬件驱动提供实现,为BufferQueue机制提供了基础。gralloc分配的图形Buffer是进程间共享的,且根据其Flag支持不同硬件设备的读写。

从系统层级来看,gralloc属于最底层的HAL层模块,为上层的libui库提供服务,整个层级结构: