您好,欢迎来到汇智旅游网。
搜索
您的当前位置:首页Android CCodec Codec2 (二二)C2BufferQueueBlockPool - Ⅰ

Android CCodec Codec2 (二二)C2BufferQueueBlockPool - Ⅰ

来源:汇智旅游网

1、outputAllocatorId

在CCodecBufferChannel的start方法中有这样一段代码,我们再回头看一遍:

status_t CCodecBufferChannel::start(
        const sp<AMessage> &inputFormat,
        const sp<AMessage> &outputFormat,
        bool buffersBoundToCodec) {
    // ...

    if (outputFormat != nullptr) {     
        // 1.
        pools->outputAllocatorId = (graphic) ? C2PlatformAllocatorStore::GRALLOC
                                                : preferredLinearId;

        // ...
                                            
        if (outputSurface) {
            params.clear();
            // 2.
            err = mComponent->query({ },
                                    { C2PortSurfaceAllocatorTuning::output::PARAM_TYPE },
                                    C2_DONT_BLOCK,
                                    &params);
            if ((err != C2_OK && err != C2_BAD_INDEX) || params.size() != 1) {

            } else if (err == C2_OK && params.size() == 1) {
                C2PortSurfaceAllocatorTuning::output *surfaceAllocator =
                    C2PortSurfaceAllocatorTuning::output::From(params[0].get());
                if (surfaceAllocator) {
                    std::shared_ptr<C2Allocator> allocator;
                    // 3.
                    allocatorStore->fetchAllocator(surfaceAllocator->value, &allocator);
                    if (allocator) {
                        pools->outputAllocatorId = allocator->getId();
                    } else {
                        err = C2_BAD_VALUE;
                    }
                }
            }
            // 4.
            if (pools->outputAllocatorId == C2PlatformAllocatorStore::GRALLOC
                    && err != C2_OK
                    && ((poolMask >> C2PlatformAllocatorStore::BUFFERQUEUE) & 1)) {
                pools->outputAllocatorId = C2PlatformAllocatorStore::BUFFERQUEUE;
            }
        }
    }
}

以上代码不难理解,稍微有点难理解的是代码标注第四段中的三个条件什么时候同时满足(或者说是什么时候outputAllocatorId为BUFFERQUEUE)?先来看单个条件成立的情形:

  1. outputAllocatorId是GRALLOC:参数请求失败,或者参数请求成功返回GRALLOC;
  2. err不是C2_OK:参数请求失败,或者allocator实例创建失败(默认创建成功);
  3. poolMask的BUFFERQUEUE标志位为1:默认满足此条件;

把各个条件进行拼接后得到,在video decoder且有surface的情况下:

  1. 如果组件没有定义C2PortSurfaceAllocatorTuning::output,使用BUFFERQUEUE;
  2. 组件定义有C2PortSurfaceAllocatorTuning::output,且值为BUFFERQUEUE,最终使用BUFFERQUEUE;
  3. 组件定义有C2PortSurfaceAllocatorTuning::output,且值为GRALLOC,最终使用GRALLOC;

简单来说,在video decoder且有surface的情况下,组件如果没有定义参数C2PortSurfaceAllocatorTuning::output,则使用BUFFERQUEUE;如果组件定义了参数则使用定义值。对于video decoder没有surface的情况,使用Gralloc。

接下来的文章只讨论outputAllocatorId为BUFFERQUEUE的情况!

2、C2BufferQueueBlockPool

C2BufferQueueBlockPool专门用于管理通过BufferQueue分配的内存块,这些内存块用于组件的输出端口,被填充的内存块会被送到NativeWindow做渲染。

在Codec2框架中,Input C2BlockPool是在上层(CCodecBufferChannel)创建的,而Output C2BlockPool是在HAL层(Component)创建的。如果outputAllocatorId为BUFFERQUEUE,创建过程除了实例化C2BlockPool外,还有一系列的配置和初始化工作。接下来我们将以C2BufferQueueBlockPool的创建流程作为切入点对它进行了解。

调用Codec2Client::Component的createBlockPool方法,传入outputAllocatorId,然后一路往下到达HIDL层的createBlockPool,在这里会调用C2Store.cpp中的CreateCodec2BlockPool方法。

// CCodecBufferChannel
if ((poolMask >> pools->outputAllocatorId) & 1) {
    err = mComponent->createBlockPool(
            pools->outputAllocatorId, &pools->outputPoolId, &pools->outputPoolIntf);
}
// Component HIDL
Return<void> Component::createBlockPool(
        uint32_t allocatorId,
        createBlockPool_cb _hidl_cb) {
    std::shared_ptr<C2BlockPool> blockPool;
    c2_status_t status = ComponentStore::GetFilterWrapper()->createBlockPool(
            static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
            mComponent,
            &blockPool);

    _hidl_cb(static_cast<Status>(status),
            blockPool ? blockPool->getLocalId() : 0,
            new CachedConfigurable(
            std::make_unique<BlockPoolIntf>(blockPool)));
    return Void();
}
// C2Store
switch(allocatorId) {
    case C2PlatformAllocatorStore::BUFFERQUEUE:
        res = allocatorStore->fetchAllocator(
                C2PlatformAllocatorStore::BUFFERQUEUE, &allocator);
        if (res == C2_OK) {
            std::shared_ptr<C2BlockPool> ptr(
                    new C2BufferQueueBlockPool(allocator, poolId), deleter);
            *pool = ptr;
            mBlockPools[poolId] = ptr;
            mComponents[poolId].insert(
                    mComponents[poolId].end(),
                    components.begin(), components.end());
        }
        break;
}
c2_status_t C2PlatformAllocatorStoreImpl::fetchAllocator(
        id_t id, std::shared_ptr<C2Allocator> *const allocator) {
    switch (id) {
    case C2PlatformAllocatorStore::BUFFERQUEUE:
        *allocator = fetchBufferQueueAllocator();
        break;
    }
}

最后先创建了一个C2AllocatorGralloc,然后将它作为参数创建了一个C2BufferQueueBlockPool。C2BlockPool创建完成后会回传一个outputPoolId给上层,后续的调用会用到此id。

3、setOutputSurface

接下来开始对C2BufferQueueBlockPool进行配置,所谓配置就是将它和Surface绑定:

4、OutputBufferQueue

5、C2SyncVariables

6、setOutputSurfaceWithSyncObj

7、configureProducer


原文阅读:

扫描下方二维码,关注公众号《青山渺渺》阅读音视频开发内容。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- hzar.cn 版权所有 赣ICP备2024042791号-5

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务