Codec2Client::createComponent过程分析

Codec2Client类继承于Codec2ConfigurableClient父类,它可以创建component,创建与component相关联的interface,是Codec2 HIDL的client实现。

创建硬件codec2 Component

  • 先通过CreateFromService从ComponentStore service中获取store,然后初始化Codec2Client返回
  • 然后设置Codec2ClientInterfaceWrapper为preferred store,client用于初始化Codec2ClientInterfaceWrapper
  • 创建c2.qti.avc.decoder

参考CCdoec中的代码,Codec2Client创建一个component需要通过下面三行代码就可以实现:

// CreateFromService从ComponentStore service中获取store,然后初始化Codec2Client返回
std::shared_ptr<Codec2Client> client = Codec2Client::CreateFromService("default");

// 设置Codec2ClientInterfaceWrapper为preferred store,client用于初始化Codec2ClientInterfaceWrapper
SetPreferredCodec2ComponentStore(std::make_shared<Codec2ClientInterfaceWrapper>(client));

// 创建c2.qti.avc.decoder
mComponent = Codec2Client::CreateComponentByName("c2.qti.avc.decoder", mClientListener, &client);

Codec2Client::CreateFromService的细节

std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
        const char* name,
        bool setAsPreferredCodec2ComponentStore) {
    
    // 获取service idx,然后根据idx创建Codec2Client对象
    size_t index = getServiceIndex(name);
    if (index == GetServiceNames().size()) {
        if (setAsPreferredCodec2ComponentStore) {
            LOG(WARNING) << "CreateFromService(" << name
                         << ") -- preferred C2ComponentStore not set.";
        }
        return nullptr;
    }
    std::shared_ptr<Codec2Client> client = _CreateFromIndex(index);
    if (setAsPreferredCodec2ComponentStore) {
        SetPreferredCodec2ComponentStore(
                std::make_shared<Client2Store>(client));
        LOG(INFO) << "CreateFromService(" << name
                  << ") -- service set as preferred C2ComponentStore.";
    }
    return client;
}

service的创建可能像这样:

media/codec2/hidl/services/vendor.cpp

store = new utils::ComponentStore(
    std::make_shared<StoreImpl>());

if (store == nullptr) {
    LOG(ERROR) << "Cannot create Codec2's IComponentStore service.";
} else {
    constexpr char const* serviceName = "default";
    if (store->registerAsService(serviceName) != OK) {
        LOG(ERROR) << "Cannot register Codec2's IComponentStore service"
            " with instance name << \""
            << serviceName << "\".";
    } else {
        LOG(DEBUG) << "Codec2's IComponentStore service registered. "
            "Instance name: \"" << serviceName << "\".";
    }
}
Codec2Client::_CreateFromIndex

getService去获取ComponentStore server,比如android.hardware.media.c2@1.0::IComponentStore/default,然后将这个ComponentStore作为baseStore参数传给Codec2Client构造函数初始化Codec2Client,赋值给mBase1_0,所以在Codec2Client中的mBase1_0的mBase1_0就是这个service获得的ComponentStore对象,然后调用其对应的createComponent函数。

std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
    std::string const& name = GetServiceNames()[index];
    LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
   
    sp<Base> baseStore = Base::getService(name);
    CHECK(baseStore) << "Codec2 service \"" << name << "\""
                        " inaccessible for unknown reasons.";
    LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
    return std::make_shared<Codec2Client>(baseStore, index);
}

lshal | grep media可以查到ComponentStore server

android.hardware.media.c2@1.0::IComponentStore/default  
android.hardware.media.c2@1.0::IComponentStore/software 
android.hardware.media.c2@1.1::IComponentStore/software 
android.hardware.media.omx@1.0::IOmx/default            
android.hardware.media.omx@1.0::IOmxStore/default
IComponentStore::getService的代码
::android::sp<IComponentStore> IComponentStore::getService(const std::string &serviceName, const bool getStub) {
    return ::android::hardware::details::getServiceInternal<BpHwComponentStore>(serviceName, true, getStub);
}

Codec2Client::CreateComponentByName

调用ForAllServices创建component


std::shared_ptr<Codec2Client::Component>
        Codec2Client::CreateComponentByName(
        const char* componentName,
        const std::shared_ptr<Listener>& listener,
        std::shared_ptr<Codec2Client>* owner,
        size_t numberOfAttempts) {
    std::string key{"create:"};
    key.append(componentName);
    std::shared_ptr<Component> component;
    
	c2_status_t status = ForAllServices(
            key,
            numberOfAttempts,
        	// 细节需要看这个lambda表达式对应的函数在ForAllServices中被调用的地方,在ForAllServices函数中会有传入参数client
            [owner, &component, componentName, &listener](const std::shared_ptr<Codec2Client> &client)-> c2_status_t {
                c2_status_t status = client->createComponent(componentName, listener, &component);
                if (status == C2_OK) {
                    if (owner) {
                        *owner = client;
                    }
                } else if (status != C2_NOT_FOUND) {
                    // LOG ...
                }
                return status;
            });

    if (status != C2_OK) {
        // LOG ...
    }
    return component;
}
Codec2Client::ForAllServices

c2_status_t Codec2Client::ForAllServices(
        const std::string &key,
        size_t numberOfAttempts,
        std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>predicate) {
    c2_status_t status = C2_NO_INIT;  // no IComponentStores present

    // Cache the mapping key -> index of Codec2Client in Cache::List().
    static std::mutex key2IndexMutex;
    static std::map<std::string, size_t> key2Index;

    // By default try all stores. However, try the last known client first. If
    // the last known client fails, retry once. We do this by pushing the last
    // known client in front of the list of all clients.
    std::deque<size_t> indices;
    for (size_t index = Cache::List().size(); index > 0; ) {
        indices.push_front(--index);
    }

    bool wasMapped = false;
    {
        std::scoped_lock lock{key2IndexMutex};
        auto it = key2Index.find(key);
        if (it != key2Index.end()) {
            indices.push_front(it->second);
            wasMapped = true;
        }
    }

    for (size_t index : indices) {
        Cache& cache = Cache::List()[index];
        for (size_t tries = numberOfAttempts; tries > 0; --tries) {
            std::shared_ptr<Codec2Client> client{cache.getClient()};
            
            // 这个地方执行CreateComponentByName中的lambda表达式
            // 从cache中获取Codec2Client对象,然后调用createComponent函数,更新owner
            status = predicate(client);

            if (status == C2_OK) {
                std::scoped_lock lock{key2IndexMutex};
                key2Index[key] = index; // update last known client index
                return C2_OK;
            } else if (status == C2_TRANSACTION_FAILED) {
                cache.invalidate();
                continue;
            }
            if (wasMapped) {
                wasMapped = false;
            }
            break;
        }
    }
    return status; // return the last status from a valid client
}

其中std::function定义了一个参数表为(const std::shared_ptr<Codec2Client>&),返回类型为c2_status_t的函数,函数名为predicate,后面的花括号紧跟ForAllServices函数体:

std::function< c2_status_t(const std::shared_ptr<Codec2Client>&) >predicate
Codec2Client::createComponent

c2_status_t Codec2Client::createComponent(
        const C2String& name,
        const std::shared_ptr<Codec2Client::Listener>& listener,
        std::shared_ptr<Codec2Client::Component>* const component) {

    c2_status_t status;
    sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
    hidlListener->base = listener;

    // mBase1_1就是IComponentStore 
    Return<void> transStatus = mBase1_1 ?
        mBase1_1->createComponent_1_1(
            name,
            hidlListener,
            ClientManager::getInstance(),
            [&status, component, hidlListener](
                    Status s,
                    const sp<IComponent>& c) {
                status = static_cast<c2_status_t>(s);
                if (status != C2_OK) {
                    return;
                }
                *component = std::make_shared<Codec2Client::Component>(c);
                hidlListener->component = *component;
            }) :
    		// mBase1_0 就是IComponentStore,调用ComponentStore::createComponent
    		// service中获得的ComponentStore对象
            mBase1_0->createComponent(
            name,
            hidlListener,
            ClientManager::getInstance(),
            [&status, component, hidlListener](
                    Status s,
                    const sp<hardware::media::c2::V1_0::IComponent>& c) {
                status = static_cast<c2_status_t>(s);
                if (status != C2_OK) {
                    return;
                }
                *component = std::make_shared<Codec2Client::Component>(c);
                hidlListener->component = *component;
            });
}
ComponentStore::createComponent

frameworks/av/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
frameworks/av/media/codec2/hidl/1.0/utils/ComponentStore.cpp

ComponentStore::createComponent中的mStore是C2ComponentStore类型,所以:hardware component应该也有这么个类似C2PlatformComponentStore : public C2ComponentStore的类

// Methods from ::android::hardware::media::c2::V1_0::IComponentStore
Return<void> ComponentStore::createComponent(
        const hidl_string& name,
        const sp<IComponentListener>& listener,
        const sp<IClientManager>& pool,
        createComponent_cb _hidl_cb) {

    sp<Component> component;
    std::shared_ptr<C2Component> c2component;
    
    // 这地方又有一个mStore的调用,mStore是C2ComponentStore类型
    // 那么具体会是谁呢?只有可能是Client2Store
    
    // 疑问,这个怎么获得vendor的component列表的?
    // C2PlatformComponentStore只能获得软解,SetPreferredCodec2ComponentStore的时候,会设置这个store
    
    // 所以:hardware component应该也有这么个类似`C2PlatformComponentStore : public C2ComponentStore`的类
    // 然后在注册到HIDL service里面,Client2Client获得store,进而调用mStore->createComponent
    
    // C2ComponentStore::createComponent
    Status status = static_cast<Status>(
            mStore->createComponent(name, &c2component));

    if (status == Status::OK) {
#ifndef __ANDROID_APEX__
        c2component = GetFilterWrapper()->maybeWrapComponent(c2component);
#endif
        onInterfaceLoaded(c2component->intf());
        
        // 创建Component类型
        component = new Component(c2component, listener, this, pool);
        if (!component) {
            status = Status::CORRUPTED;
        } else {
            reportComponentBirth(component.get());
            if (component->status() != C2_OK) {
                status = static_cast<Status>(component->status());
            } else {
                component->initListener(component);
                if (component->status() != C2_OK) {
                    status = static_cast<Status>(component->status());
                }
            }
        }
    }
    _hidl_cb(status, component);
    return Void();
}

前面函数中createComponent_cb原型如下,comp是IComponent类型:

using createComponent_cb = std::function<void(::android::hardware::media::c2::V1_0::Status status, 
                                              const ::android::sp<::android::hardware::media::c2::V1_0::IComponent>& comp)>;

疑问,这个地方把IComponent类型通过make_shared转换为Codec2Client::Component类型?

在前面的Codec2Client::createComponent中有:

std::shared_ptr<Codec2Client::Component>* const component
*component = std::make_shared<Codec2Client::Component>(c);
  • make_shared会调用Codec2Client::Component的构造函数,Codec2Client::Component构造函数如下,Base就是IComponent,所以前面的c作为参数给Codec2Client::Component的构造函数没有问题,这个如果理解成类型转换就不对了,这两个类之间是没有共同基类的。

    Component(const sp<Base>& base);
    Component(const sp<Base1_1>& base);
    Component(const sp<Base1_2>& base);
    

IComponent继承自IBase

struct IComponent : public ::android::hidl::base::V1_0::IBase
ComponentStore::createComponent_1_1
Return<void> ComponentStore::createComponent_1_1(
        const hidl_string& name,
        const sp<IComponentListener>& listener,
        const sp<IClientManager>& pool,
        createComponent_1_1_cb _hidl_cb);

media/codec2/hidl/1.1/utils/ComponentStore.cpp

在ComponentStore中通过C2ComponentStore创建c2component,然后c2component作为参数,创建Component,创建的component又作为_hidl_cb的参数,所以关系是:

ComponentStore::createComponent_1_1
	C2ComponentStore::createComponent
		new Component(c2component, listener, this, pool)

_hidl_cb就是Codec2Client::createComponent中的拉姆达表达式:

// Methods from ::android::hardware::media::c2::V1_1::IComponentStore
Return<void> ComponentStore::createComponent_1_1(
        const hidl_string& name,
        const sp<IComponentListener>& listener,
        const sp<IClientManager>& pool,
        createComponent_1_1_cb _hidl_cb) {

    sp<Component> component;
    std::shared_ptr<C2Component> c2component;
    
    // C2ComponentStore::createComponent
    Status status = static_cast<Status>(
            mStore->createComponent(name, &c2component));

    if (status == Status::OK) {
        onInterfaceLoaded(c2component->intf());
        // new hidl Component
        component = new Component(c2component, listener, this, pool);
        if (!component) {
            status = Status::CORRUPTED;
        } else {
            reportComponentBirth(component.get());
            if (component->status() != C2_OK) {
                status = static_cast<Status>(component->status());
            } else {
                component->initListener(component);
                if (component->status() != C2_OK) {
                    status = static_cast<Status>(component->status());
                }
            }
        }
    }
    _hidl_cb(status, component);
    return Void();
}
C2ComponentStore::createComponent

因为C2ComponentStore是作为基类的一个抽象类,SimpleC2Component继承自C2ComponentStore,真正的codec component又继承自SimpleC2Component,所以这部分的实现参考C2PlatformComponentStore::createComponent就可以,后面的过程就比较清晰。

图中表示的是C2ComponentStore和C2SoftAvcDec以及Codec2Client之间的关系

在这里插入图片描述

C2PlatformComponentStore::createComponent
c2_status_t C2PlatformComponentStore::createComponent(
        C2String name, std::shared_ptr<C2Component> *const component) {
    // This method SHALL return within 100ms.
    component->reset();
    std::shared_ptr<ComponentModule> module;
    c2_status_t res = findComponent(name, &module);
    if (res == C2_OK) {
        // TODO: get a unique node ID
        res = module->createComponent(0, component);
    }
    return res;
}
C2PlatformComponentStore::findComponent
c2_status_t C2PlatformComponentStore::findComponent(
        C2String name, std::shared_ptr<ComponentModule> *module) {
    (*module).reset();
    
    // 调用visitComponents
    visitComponents();

    auto pos = mComponentNameToPath.find(name);
    if (pos != mComponentNameToPath.end()) {
        return mComponents.at(pos->second).fetchModule(module);
    }
    return C2_NOT_FOUND;
}
C2PlatformComponentStore::visitComponents

从mComponents的map中取的ComponentLoader,然后逐个去加载:

void C2PlatformComponentStore::visitComponents() {
    std::lock_guard<std::mutex> lock(mMutex);
    if (mVisited) {
        return;
    }

    // 从mComponents的map中取的ComponentLoader,然后逐个去加载
    for (auto &pathAndLoader : mComponents) {
        const C2String &path = pathAndLoader.first;
        ComponentLoader &loader = pathAndLoader.second;
        std::shared_ptr<ComponentModule> module;
        // fetchModule
        if (loader.fetchModule(&module) == C2_OK) {
            std::shared_ptr<const C2Component::Traits> traits = module->getTraits();
            if (traits) {
                mComponentList.push_back(traits);
                mComponentNameToPath.emplace(traits->name, path);
                for (const C2String &alias : traits->aliases) {
                    mComponentNameToPath.emplace(alias, path);
                }
            }
        }
    }
    mVisited = true;
}
C2PlatformComponentStore::fetchModule
c2_status_t fetchModule(std::shared_ptr<ComponentModule> *module) {
    c2_status_t res = C2_OK;
    std::lock_guard<std::mutex> lock(mMutex);
    std::shared_ptr<ComponentModule> localModule = mModule.lock();
    if (localModule == nullptr) {
        localModule = std::make_shared<ComponentModule>();
        res = localModule->init(mLibPath);
        if (res == C2_OK) {
            mModule = localModule;
        }
    }
    *module = localModule;
    return res;
}

C2PlatformComponentStore::createComponent
c2_status_t C2PlatformComponentStore::createComponent(
        C2String name, std::shared_ptr<C2Component> *const component) {
    // This method SHALL return within 100ms.
    component->reset();
    std::shared_ptr<ComponentModule> module;
    c2_status_t res = findComponent(name, &module);
    if (res == C2_OK) {
        // TODO: get a unique node ID
        res = module->createComponent(0, component);
    }
    return res;
}

调用栈如下,C2PlatformComponentStore::ComponentModule::init中会dlopen具体的动态库,然后获得符号CreateCodec2Factory,DestroyCodec2Factory,调用CreateCodec2Factory创建component factory,然后createComponent创建具体的component。

C2PlatformComponentStore::createComponent
	C2PlatformComponentStore::findComponent
	C2PlatformComponentStore::ComponentModule::createComponent
总结

所以有总结createComponent的过程,可以得出Codec2Client,codec2.0接口以及HIDL接口之间的关系:

 - Codec2Client               <==> C2ComponentStore         <==> IComponentStore
 - Codec2Client::Listener     <==> C2Component::Listener    <==> IComponentListener
 - Codec2Client::Configurable <==> [No equivalent]          <==> IConfigurable
 - Codec2Client::Interface    <==> C2ComponentInterface     <==> IComponentInterface
 - Codec2Client::Component    <==> C2Component              <==> IComponent

createComponent的时序图

在这里插入图片描述

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值