当前位置: 代码迷 >> Android >> Android5.1中surface跟CpuConsumer下生产者和消费者间的处理框架简述
  详细解决方案

Android5.1中surface跟CpuConsumer下生产者和消费者间的处理框架简述

热度:258   发布时间:2016-04-27 22:42:12.0
Android5.1中surface和CpuConsumer下生产者和消费者间的处理框架简述

本文均属自己阅读源码的点滴总结,转账请注明出处谢谢。

欢迎和大家交流。qq:1037701636 email:[email protected]

Software:系统源码Android5.1


前沿:

如果对SurfaceFlinger架构的工作原理较为熟悉的话,本文阅读起来会相对容易些。之所以撰写本文是因为在阅读Camera HAL3的实现过程中大量的出现了类似与SurfaceFlinger的工作模式。本文将以CallbackProcessor模块的为入口,和大家进行分享。



1 Preview模块Surface与SurfaceFlinger的基础知识

    开发过Android Camera模块的人,基本都应该熟悉实时采集的视频如果要显示到手机屏上,对应的Framework层就应该构建一个Surface对象,这对所有Android版本都是通用的。该Surface本质是一个在APP端的ANativeWindow,是需要从SurfaceFlinger端的Gralloc模块获取Buffer的,然后填充帧图像数据并送显示的过程。详细内容可以参考之前的专栏我心所向之Android4.2关于SurfaceFlinger相关的内容。

    由于目前Android系统版本升级过快,在5.0以上的版本中SurfaceFlinger部分框架发生了变化(目前还没有深入去研读过),了解到的是:

  一方面他去掉了SurfaceTexture/SurfaceTextureClient等内容,增强了Surface的功能。

  另一方面BufferQueue的使用也更加简单与明了,Producer与Consumer的关系也更加明确,BufferQueue不再是以前的消费者角色,转而成为ProducerBufferQueue和Consumer相互关联的桥梁。

 此外,如果你在深入的话,会了解到Gralloc模块中非framebuff的缓存管理与共享不在是那个Ashmem匿名共享内存,而是出现了一种新的内存管理机制/dev/ION/,后面会和大家分享他部分的工作机制。

对于SurfaceFlinger与Camera Preview Surface而言,ANativeWindow作为两者的共性负责管理和维护Buffer的创建与共享,在SurfaceFlinger端ANativeWindow创建buffer,在Surface侧通过dequeuebuffer获取buffer handle到本地进行共享,在填充完数据后通过queuebuffer告诉SurfaceFlinger当前buffer可用,这样就形成了一个buffer生产与消费的关系,基于这种原理我们在Camera3Device中除了看到正常的Preview Surface之外还看到了其他模块中出现了Surface的创建。


2 CallbackProcessor::updateStream() 创建Surface

    sp<IGraphicBufferProducer> producer;        sp<IGraphicBufferConsumer> consumer;        BufferQueue::createBufferQueue(&producer, &consumer);//BufferQueueProducer与BufferQueueConsumer        mCallbackConsumer = new CpuConsumer(consumer, kCallbackHeapCount);        mCallbackConsumer->setFrameAvailableListener(this);//当前CallbackProcessor继承于CpuConsumer::FrameAvailableListener        mCallbackConsumer->setName(String8("Camera2Client::CallbackConsumer"));        mCallbackWindow = new Surface(producer);//用于queue操作,这里直接进行本地的buffer操作
上述代码看上去很简单,但就是他最终形成了一个bufferstream Product和Consumer的处理,这种方式也为Camera2Client下出现多路stream,多路数据流存在奠定了基础,下面我们来简单的描述他的工作机制。


2.1 BufferQueue::createBufferQueue

void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,        sp<IGraphicBufferConsumer>* outConsumer,        const sp<IGraphicBufferAlloc>& allocator) {    LOG_ALWAYS_FATAL_IF(outProducer == NULL,            "BufferQueue: outProducer must not be NULL");    LOG_ALWAYS_FATAL_IF(outConsumer == NULL,            "BufferQueue: outConsumer must not be NULL");    sp<BufferQueueCore> core(new BufferQueueCore(allocator));    LOG_ALWAYS_FATAL_IF(core == NULL,            "BufferQueue: failed to create BufferQueueCore");    sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core));//本地Bn的BufferQueueProducer    LOG_ALWAYS_FATAL_IF(producer == NULL,            "BufferQueue: failed to create BufferQueueProducer");    sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));//本地Bn的BufferQueueConsumer    LOG_ALWAYS_FATAL_IF(consumer == NULL,            "BufferQueue: failed to create BufferQueueConsumer");    *outProducer = producer;    *outConsumer = consumer;}
当前Android5.1版本中可以看到BufferQueue已经改变了原先的角色,成为了一个用于创建一组操作BufferQueue的接口,实现了BufferQueueProducer与BufferQueueConsumer的创建。更本质说现在BufferQueue的工作量已经很小,基本由Surface来全盘操作。这里通过BufferQueueCore会将BufferQueueProducer与BufferQueueConsumer绑定在一起,BufferQueueProducer可以说是替代了旧版本Android4.2中的SurfaceTextureClient,而BufferQueueConsumer则直接是SurfaceTexture以及BufferQueue的替代者。下图是在Android4.2.2中Surface和SurfaceFlinger间基于Bn/BpSurfaceTexture的多进程间buffer的queue操作机制。


2.2 CpuConsumer

    在2.1中本质上是创建了BufferQueueProducer和BufferQueueConsumer,一般是成对出现。

这个CpuConsumer的地位本质是和SurfaceFlinger是一样的,主要角色就是来处理已经带有帧数据的buffer块,所以整个的处理机制都是类型的,其中两者均为继承一个ConsumerBase类,用于实现对buffer块的处理。

CpuConsumer::CpuConsumer(const sp<IGraphicBufferConsumer>& bq,        uint32_t maxLockedBuffers, bool controlledByApp) :    ConsumerBase(bq, controlledByApp),    mMaxLockedBuffers(maxLockedBuffers),    mCurrentLockedBuffers(0){    // Create tracking entries for locked buffers    mAcquiredBuffers.insertAt(0, maxLockedBuffers);    mConsumer->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN);    mConsumer->setMaxAcquiredBufferCount(maxLockedBuffers);}


2.3 mCallbackConsumer->setFrameAvailableListener(this)

    这里所完成的过程是需要Consumer去将一个listener加入到Productor端去,便于在帧数据可用时,可以监听到并告知Consumer去做数据的处理,Product需要在数据可用时触发这个listener的onFrameAvailable,从而让数据从Productor转到Consumer则,数据处理应该是在同一进程的而不是跨进程。

    如果作为Consumer如CPUConsumer没有使用setFrameAvailableListener将自己加入到listener中去,会由ConsumerBase的接口onFrameAvailable来替代完成。

2.4 mCallbackWindow = new Surface(producer)
    这里是建立一个Surface,也就是类型于Preview模式下创建的Surface,两者的本质是一样的。在Android5.1中,Surface已经拥有了绝对的控制权,Preview模式下的Surface是跨进程的和SF进行交互,故构造函数传入的sp<IGraphicBufferProducer>& bufferProducer参数一般是一个BufferQueue中BufferQueueProducer侧匿名的binder BpGraphicBufferProducer。对于CPUConsumer而言,两者是处于同一进程之中的,Surface主要行驶如下的操作,而在旧版本中这些主要由SurfaceTextureClient来管理的:

   ANativeWindow::setSwapInterval  = hook_setSwapInterval;    ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;    ANativeWindow::cancelBuffer     = hook_cancelBuffer;    ANativeWindow::queueBuffer      = hook_queueBuffer;    ANativeWindow::query            = hook_query;    ANativeWindow::perform          = hook_perform;    ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;    ANativeWindow::cancelBuffer_DEPRECATED  = hook_cancelBuffer_DEPRECATED;    ANativeWindow::lockBuffer_DEPRECATED    = hook_lockBuffer_DEPRECATED;    ANativeWindow::queueBuffer_DEPRECATED   = hook_queueBuffer_DEPRECATED;
    一般对Buffer的操作都先是基于Struct ANativeWindow这个本地的窗口类来处理,再是通过hook到实际的surface再交由GraphicBufferProducer来完成的。


3 Android5.1下Surface的queuebuffer操作逻辑


对比上一图可知,当前CPUConsumer模式下,从queuebuffer的处理过程来看更加体现出Productor和Consumer这种设计模式,整个架构代码看起来也更明了,这也是谷歌不断升级系统去冗存精的道理吧。整个用户在调用这种逻辑是,只需几句代码就可以获得对一个buffer块的读与写的操作接口,具体后续在分析Camera HAL3的数据流时可以很深刻的看到。

    总的来说Surface在Camera3Device的架构下,与HAL3相组合是充当了消费者,与CPUCOnsumer或者Surfaceflinger来说就是生产者。或者说surface充当了buffer信息的传输与过渡。







版权声明:本文为博主原创文章,未经博主允许不得转载。

  相关解决方案