一、BufferQueue&GraphicBuffer简介
GraphicBuffer是Android系统中用于图形缓冲区的类,它提供了一个用于存储图像数据的内存缓冲区。它是在底层图形驱动程序和应用程序之间传递图像数据的一种机制。GraphicBuffer可以用于在不同的图形组件之间共享图像数据,例如SurfaceFlinger和MediaCodec等。
BufferQueue是Android系统中用于管理图像缓冲区的类,它提供了一个先进先出(FIFO)队列,用于存储和管理GraphicBuffer对象。BufferQueue可以用于实现双缓冲机制,即应用程序可以在后台准备下一帧图像数据,而前台则可以显示当前帧的图像数据。通过BufferQueue,应用程序可以高效地处理图像数据的生产和消费。
在工作中,我们经常会和Surface,ImageReader,ImageWriter BufferQueue打交道,它们之间是什么关系呢。实际上Surface,ImageReader,ImageWriter是对BufferQueue的生产者消费者的封装,其核心实现还是BufferQueue。而BufferQueue是一个生产者消费者模型又是GraphicBuffer管理者,它和显示系统以及Camera流媒体紧密关系着。
所以要了解显示系统,绕不开BufferQueue,要了解BufferQueue 就要先了解生产者消费者模型。下面就从生产者消费者模型开始,深入浅出的讲解一下BufferQueue。
生产者消费者模型基本原理
在生产者消费者模型中,存在生产者和消费者两种角色,它们通过内存缓冲区进行通信,生产者生产消费者需要的数据,消费者获取生产者生产的数据进行消费。
如果没有生产者消费者模型,那么生产者和消费者是直接调用关系,生产速度的和消费速度相互拖累,必须在消费完成之后才能进行下一次生产,如下图:
有了生产者和消费者模型之后,生产者生产的数据存到缓冲队列,消费者从队列中取数据去消费,互不影响,互不拖累,耦合性低。如下图
生产者消费者模型的组成
总结起来生产者消费者模型由一个场所,和两个角色组成:
一个场所:数据缓冲区,实现内存共享和轮转。
两个角色: 生产者(生产线程)生产数据,消费者(消费线程)消费数据。也可以是进程间使用。
生产者和消费着之间又需要遵循三种关系和四个基本的原则:
三个关系:生产者和生产者互斥关系,消费者和消费者互斥关系,生产者和消费者互斥同步关系。
四个原则:生产者生产的时候消费者不能消费,消费者消费的时候生产者不能生产,缓冲区空时消费者不能消费,缓冲区满时生产者不能生产。
以上就可以很清晰,简单明了的解释了生产者消费者模型。那么BufferQueue是什么,怎么应用生产者-消费者模型思想的,下面详细说明。
二、BufferQueue&GraphicBuffer基本原理
BufferQueue的生产消费框架
BufferQueue的核心逻辑是生产者消费者逻辑,在BufferQueue这个生产者消费者框架中, BufferQueuecore可以理解为数据缓冲区的管理者,代码逻辑在BufferQueue.cpp和BufferQueuecore.cpp中。它的原始消费者是BufferQueueConsumer,它的原始生产者是BufferQueueProducer。
那么BufferQueue.cpp 和BufferQueuecore.cpp是什么样的关系呢,可以理解为BufferQueue 是创建者,BufferQueueCore是由BufferQueue调用createBufferQueue创建的。
总的来讲 BufferQueue.cpp 主要定义了createBufferQueue接口和ProxyConsumerListener的onFrameAvailable等通知接口。
使用的时候,封装的消费者调用createBufferQueue创建BufferQueueCore,然后根据创建好的BufferQueueCore,去创建原始生产者消费者BufferQueueConsumer和BufferQueueProducer。
而消费者BufferQueueConsumer在调用connect的时候把ConsumerListener相关的回调接口注册进BufferQueue供ProxyConsumerListener回调使用。
生产者BufferQueueProducer也有一个connect接口,生产者的connect接口会注册IProducerListener到BufferQueuecore中,在消费者使用完GraphicBuffer释放的时候通过这个Listener通知生产者。
同时这个IProducerListener会注册Binder死亡通知函数,在死亡的时候回调BufferQueueProducer的binderDied,取消链接。
至此由BufferQueue BufferQueuecore,BufferQueueConsumer, BufferQueueProducer,组成的核心的生产者消费者模型就建立起来了。
这里说的是封装的消费者去创建BufferQueuecore有两点需要解释一下:
一个是消费者的封装关系,这个后面会详细说明。
另外一个就是为什么是消费者创建BufferQueuecore 而不是生产者去创建呢。
其实也是可以放到生产者中创建的,但是主要由于两点原因,正常会放在消费者中去创建:
1.出于消费者准备好消费了在去生产的思想考虑。
2.以消费者端作为核心端去管理,在消费者端创建方便统一管理。
BufferQueueCore概述
从BufferQueue的生产消费框架建立过程看,BufferQueueCore是核心缓冲区管理者,是由BufferQueue创建的,那么BufferQueueCore具体管理哪些事呢。
代码上看主要包含了下面这些关键参数。
可以大概划分一下:
slots相关,用于关联数据核心GraphicBuffer。(包括mSlots mQueue mFreeSlots mfreeBuffers mUnusedSlots,mActiveBuffers ),
listener相关,用于通知和回调(包括mConsumerListener mLinkedToDeath mConnectedProducerListener),
Buffercount相关,用于定BufferQuue中的Buffer数量。(包括mMaxBufferCount mMaxAcquiredBufferCount mMaxDequeuedBufferCount),和一些设置项(包括 mConsumerName mDefaultWidth mDefaultHeight mDefaultBufferFormat mDefaultBufferDataSpace)设置相关主要是name 宽高信息,format信息,dataspace信息