Buffer轮转
这篇文章收录在相机系列文章:相机基础知识大纲
下面是对Android 相机框架Buffer轮转相关知识的解读。
GraphicBuffer
GraphicBuffer是共享缓冲区,用来承载图片数据,在系统中,图像数据通过buffer形式在显示,相机应用,相机框架,Hal等多个模块间流转交互。
buffer的轮转状态
一个buffer在创建后,一般会经历Free->Dequeueed->Queued->Acquired->Free几个状态循环。
如下图所示
BufferQueue
BufferQueue创建时候会创建BufferQueueCore对象,它是核心缓冲区的管理者,用其作为构造入参创建出生产者BufferQueueProducer对象和消费者BufferQueueConsumer对象。也就是说BufferQueue创建过程其实是建立了一个producer>core<consumer的绑定关系。一般是在消费者进程调用createBufferQueue创建BufferQueueCore,并建立起绑定关系。
BufferQueue机制是安卓系统的核心内容,是生产者-消费者设计模式的极好实践。生产者和消费者通常在不同的进程,共享同一块buffer内存,减少数据拷贝。
生产者和消费者
生产者和消费者通常在不同的进程,BufferQueue采用了binder和共享内存机制,可以高效地在进程间传递图形数据。 BufferQueueProducer和BufferQueueConsumer分别实现了IGraphicBufferProducer和IGraphicBufferConsumer binder接口。
生产者BufferQueueProducer
IGraphicBufferProducer接口定义了dequeue Buffer,queueBuffer,requestBuffer等纯虚函数,生产者一般分为BpGraphicBufferProducer和BnIGraphicBufferProducer两个部分,这两部分都实现了IGraphicBufferProducer接口。Bp端通过binder接口调用到Bn端接口,Bn端和BufferQueueCore属于同一个进程。
BpGraphicBufferProducer可以通过connect向BufferQueueCore注册IProducerListener回调,这样当消费者归还消费后的GraphicBuffer可以通知生产者。
生产者通过调用dequeueBuffer获取可用的GraphicBuffer,生产填充数据后,再调用queueBuffer归还数据到BufferQueueCore。
消费者BufferQueueConsumer
IGraphicBufferConsumer接口定义了connect,acquireBuffer,releaseBuffer等纯虚函数,消费者分为BpGraphicBufferConsumer和BnIGraphicBufferConsumer两个部分,这两部分都实现了IGraphicBufferConsumer接口。
消费者调用connect向BufferQueueCore注册IConsumerListener,这样有新数据的时候就可以通过IConsumerListener的onFrameAvailable通知消费者。也就是说,当生产者queueBuffer到BufferQueue队列时,会通过onFrameAvailable回调来通知消费者,收到通知后,消费者通过调用acquireBuffer获取GraphicBuffer,使用完后再调用releaseBuffer归回数据到BufferQueueCore。
相机框架轮转
相机BufferQueue构建
SurfaceTexture在初始化函数SurfaceTexture_init中构建BufferQueue。
ImageReader在初始化函数ImageReader_init中构建BufferQueue。
SurfaceView 在BufferLayer初始化函数onFirstRef中构建BufferQueue。
相机框架buffer轮转
在java侧创建的Surface在native层有对应的一个Surface对象,相机应用将Surface作为入参创建会话,框架层会对应创建Stream数据流,一个Surface一般对应一路数据流,这个Surface对象作为生产者Bp端对象存储在Stream配置数据中。
下面是相机框架与BufferQueue的一个交互简图。