对于SurfaceView的理解

前言

一直从事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运转基于生产者消费者模型;所以Surface是生产者消费者模型的一个代理,代表的就是生产者。

二、Camera数据流转

Camera从上到下分为三层 :APP层、CameraServer、HAL+驱动。

1、SurfaceView由应用创建,获取到Surface之后传递给CameraServer;

2、CameraServer通过Surface的接口dequeue出一块GraphicBuffer,将buffer_handle传递给Hal;

3、Hal拿到buffer_handle之后会map出自己进程空间的地址,通过驱动往这块buffer上填数据;

4、数据填完之后会返回给CameraServer,CameraServer再queueBuffer,将buffer返回到队列;

5、生产者消费者模型消费者端继续acquire Buffer,通过Transaction传给SurfaceFlinger显示。

以下简单贴了CameraServer里dequeuBuffer和queueBuffer的代码位置

// Camera3OutputStream.cpp
status_t Camera3OutputStream::getBufferLockedCommon(ANativeWindowBuffer** anb, int* fenceFd) {
    
    ...............................
        if (batchSize == 1) {
            sp<ANativeWindow> anw = consumer;
            res = anw->dequeueBuffer(anw.get(), anb, fenceFd);
        }
}

status_t Camera3OutputStream::queueBufferToConsumer(sp<ANativeWindow>& consumer,
            ANativeWindowBuffer* buffer, int anwReleaseFence,
            const std::vector<size_t>&) {
    return consumer->queueBuffer(consumer.get(), buffer, anwReleaseFence);
}

ANativeWindow就是Surface。

三、总结

所以SurfaceView又是什么?作为app开发,SurfaceView当成View使用其实很简单,但其背后是基于生产者消费者模型的GraphicBuffer运转,BLASTBufferQueue作为GraphicBuffer的管理者统筹所有流程。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值