Graphic 学习笔记

发现一个比较好的介绍graphic帖子, 后面会跟着帖子来梳理下graphic相关知识点
http://blog.csdn.net/u014409795/article/details/51276468

  • BufferQueue

  •        class BufferQueue {
                  class ProxyConsumerListener : public BnConsumerListener;
                  static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
                            sp<IGraphicBufferConsumer>* outConsumer,
                            const sp<IGraphicBufferAlloc>& allocator = NULL);
            private:
                 BufferQueue(); // Create through createBufferQueue

         }

         //看起来只有consumer一个角色?


        void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
            sp<IGraphicBufferConsumer>* outConsumer,
            const sp<IGraphicBufferAlloc>& allocator) {

            sp<BufferQueueCore> core(new BufferQueueCore(allocator));
            sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core));

            sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));

      BufferQueue核心是BufferQueueCore,

      看BufferQueueCore里面是管理什么的 

      class BufferQueueCore : public virtual RefBase {

              friend class BufferQueueProducer;
              friend class BufferQueueConsumer;

               typedef Vector<BufferItem> Fifo;  //一个BufferItem Vector

             private:

             // mAllocator is the connection to SurfaceFlinger that is used to allocate
             // new GraphicBuffer objects.
            sp<IGraphicBufferAlloc> mAllocator;
             // mSlots is an array of buffer slots that must be mirrored on the producer
            // side. This allows buffer ownership to be transferred between the producer
            // and consumer without sending a GraphicBuffer over Binder. The entire
           // array is initialized to NULL at construction time, and buffers are
           // allocated for a slot when requestBuffer is called with that slot's index.
            BufferQueueDefs::SlotsType mSlots;   //


            BufferSlot()
        : mEglDisplay(EGL_NO_DISPLAY),
          mBufferState(BufferSlot::FREE),   //state
          mRequestBufferCalled(false),
          mFrameNumber(0),
          mEglFence(EGL_NO_SYNC_KHR),
          mAcquireCalled(false),
          mNeedsCleanupOnRelease(false),
          mAttachedByConsumer(false) {
        }

        // mGraphicBuffer points to the buffer allocated for this slot or is NULL
        // if no buffer has been allocated.
        sp<GraphicBuffer> mGraphicBuffer;   //bufferslot中指向GraphicBuffer

        enum BufferState { // state 表示buffer state

         FREE = 0,  //FREE indicates that the buffer is available to be dequeued by the producer.
         // 允许produce获取该buffer,填充数据,状态变为dequeue    free 时表示该buffer还被bufferqueue 所有

       DEQUEUED = 1,// DEQUEUED indicates that the buffer has been dequeued by the  producer, but has not yet been queued or canceled. The slot is "owned" by the producer.  处于待填充数据状态,被producer所有

      QUEUED = 2,//QUEUED indicates that the buffer has been filled by the producer and queued for use by the consumer; producer填充完数据,准备提供给consumer消费,被bufferqueue所有

       ACQUIRED = 3//ACQUIRED indicates that the buffer has been acquired by the  consumer.

       buffer被consumer获取到,消费完后转为free

       在bufferqueuecore中bufferItem又是什么
       class BufferItem : public Flattenable<BufferItem> {

       // mGraphicBuffer points to the buffer allocated for this slot, or is NULL
        // if the buffer in this slot has been acquired in the past (see
        // BufferSlot.mAcquireCalled).
        sp<GraphicBuffer> mGraphicBuffer; //也有GraphicBuffer指针 

         union {
            // mSlot is the slot index of this buffer (default INVALID_BUFFER_SLOT).
            int mSlot; // slot数组中索引

            // mBuf is the former name for mSlot
            int mBuf;  // 旧名字
        };

       BufferSlot 与 BufferItem 都指向GraphicBuffer,然后又 通过mSlot下标关联起来,至于两者使用场景再看,至于GraphicBuffer是如何再通过GraphicBufferAlloc分配的,待进一步trace,目前继续聚焦于BufferQueue使用

    在SurfaceMediaSource::read()就是一个consumer acquire场景
    SurfaceMediaSource::signalBufferReturned()是consumer release场景,但什么时候调用的呢?是通过mediaBuffer自身的observer来通知consumer release该buffer

    void MediaBuffer::release() {

    mObserver->signalBufferReturned(this);


    struct VideoNativeMetadata {
        MetadataBufferType eType;               // must be kMetadataBufferTypeANWBuffer
    #ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
        OMX_PTR pBuffer;
    #else
        struct ANativeWindowBuffer* pBuffer;
    #endif
        int nFenceFd;                           // -1 if unused
    };

    下面聚焦BufferQueue使用过程

     BufferQueue::createBufferQueue(&mProducer, &mConsumer);

    可以跳转到文章开头看CreateBufferQueue, Producer与Consumer 实际是共用bufferslot,然后通过不同的BufferState 来判断实际空间上数据是归属于谁,正被谁使用

    mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight); //这个宽和高是codec要编解码的宽和高

    至于producer是如何跟surfaceview关联起来的?
    base/core/jni/android_view_Surface.cpp:jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env

     sp<Surface> surface(new Surface(bufferProducer, true));这样关联起来了

    生产者

    status_t BufferQueueProducer::dequeueBuffer(){

    while (found == BufferItem::INVALID_BUFFER_SLOT) {
                status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
                        &found, &returnFlags);} //得到一个空闲的slot 号 found

     const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
            if ((buffer == NULL) || buffer->needsReallocation(width, height, format, usage)){}else{}

    判断graphic buffer是否需要重新分配

    if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
    sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
                    width, height, format, usage, &error)); }

    return returnFlags;}

    填充数据完成

    status_t BufferQueueProducer::queueBuffer(){

    input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop, &scalingMode,
                &transform, &async, &fence, &stickyTransform);

    mSlots[slot].mBufferState = BufferSlot::QUEUED;

    BufferItem item;

     mCore->mQueue.push_back(item);// 将buffer 放入bufferqueuecore队列,供consumer到时acquire

     mCore->mDequeueCondition.broadcast();  }

    BufferQueueProducer::cancelBuffer(){

        mCore->mFreeBuffers.push_front(slot);
        mSlots[slot].mBufferState = BufferSlot::FREE; }


    BufferQueueProducer::connect(){}

    BufferQueueProducer::disconnect(int api){}  //BufferQueue跟app的生死绑定到了一起,当app莫名其妙的死掉以后,flinger服务中的BufferQueue就知道,会做一些清理工作

    void BufferQueueProducer::allocateBuffers(){

    newBufferCount =
                        static_cast<size_t>(maxBufferCount - currentBufferCount);

    for (size_t i = 0; i <  newBufferCount; ++i) {

    sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
                        allocWidth, allocHeight, allocFormat, allocUsage, &result)); }  }//这个buffer分配被void Surface::allocateBuffers()调用

    消费者
    status_t BufferQueueConsumer::acquireBuffer(){

     BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
      int slot = front->mSlot;
      *outBuffer = *front;
       mSlots[slot].mBufferState = BufferSlot::ACQUIRED;
       mCore->mQueue.erase(front);    }

    status_t BufferQueueConsumer::releaseBuffer(int slot..){
            if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) {
                mSlots[slot].mBufferState = BufferSlot::FREE;
                mCore->mFreeBuffers.push_back(slot); }  //acquire, release 只是简单的状态改变和插入对应队列 }

    最后编辑于
    ©著作权归作者所有,转载或内容合作请联系作者
    • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
      沈念sama阅读 203,772评论 6 477
    • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
      沈念sama阅读 85,458评论 2 381
    • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
      开封第一讲书人阅读 150,610评论 0 337
    • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
      开封第一讲书人阅读 54,640评论 1 276
    • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
      茶点故事阅读 63,657评论 5 365
    • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
      开封第一讲书人阅读 48,590评论 1 281
    • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
      沈念sama阅读 37,962评论 3 395
    • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
      开封第一讲书人阅读 36,631评论 0 258
    • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
      沈念sama阅读 40,870评论 1 297
    • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
      茶点故事阅读 35,611评论 2 321
    • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
      茶点故事阅读 37,704评论 1 329
    • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
      沈念sama阅读 33,386评论 4 319
    • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
      茶点故事阅读 38,969评论 3 307
    • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
      开封第一讲书人阅读 29,944评论 0 19
    • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
      开封第一讲书人阅读 31,179评论 1 260
    • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
      沈念sama阅读 44,742评论 2 349
    • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
      茶点故事阅读 42,440评论 2 342

    推荐阅读更多精彩内容

    • 本篇文章是基于谷歌有关Graphic的一篇概览文章的翻译:http://source.android.com/de...
      lee_3do阅读 7,088评论 2 21
    • **2014真题Directions:Read the following text. Choose the be...
      又是夜半惊坐起阅读 9,355评论 0 23
    • 财富的定义:‘当你完全不工作’(或者你家里的所有人都完全不工作)时,在你现有的生活水平之下你所能生存的天数。财富是...
      王洁敏阅读 206评论 0 0
    • 毕业4年,同学见面的时候聊得最多的莫过于谁谁谁结婚了,谁谁谁生小孩了。可能是因为我们都是女同胞,都比较关...
      未雨_绸缪阅读 268评论 0 0