/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "C2Store" #define LOG_NDEBUG 0 #include #include #include #include #include #include #include #include #include #include #include #include // getpagesize #include #include #include namespace android { /** * Returns the preferred component store in this process to access its interface. */ std::shared_ptr GetPreferredCodec2ComponentStore(); /** * The platform allocator store provides basic allocator-types for the framework based on ion and * gralloc. Allocators are not meant to be updatable. * * \todo Provide allocator based on ashmem * \todo Move ion allocation into its HIDL or provide some mapping from memory usage to ion flags * \todo Make this allocator store extendable */ class C2PlatformAllocatorStoreImpl : public C2PlatformAllocatorStore { public: C2PlatformAllocatorStoreImpl(); virtual c2_status_t fetchAllocator( id_t id, std::shared_ptr *const allocator) override; virtual std::vector> listAllocators_nb() const override { return std::vector>(); /// \todo } virtual C2String getName() const override { return "android.allocator-store"; } void setComponentStore(std::shared_ptr store); ~C2PlatformAllocatorStoreImpl() override = default; private: /// returns a shared-singleton ion allocator std::shared_ptr fetchIonAllocator(); /// returns a shared-singleton gralloc allocator std::shared_ptr fetchGrallocAllocator(); /// returns a shared-singleton bufferqueue supporting gralloc allocator std::shared_ptr fetchBufferQueueAllocator(); /// component store to use std::mutex _mComponentStoreSetLock; // protects the entire updating _mComponentStore and its // dependencies std::mutex _mComponentStoreReadLock; // must protect only read/write of _mComponentStore std::shared_ptr _mComponentStore; }; C2PlatformAllocatorStoreImpl::C2PlatformAllocatorStoreImpl() { } c2_status_t C2PlatformAllocatorStoreImpl::fetchAllocator( id_t id, std::shared_ptr *const allocator) { allocator->reset(); switch (id) { // TODO: should we implement a generic registry for all, and use that? case C2PlatformAllocatorStore::ION: case C2AllocatorStore::DEFAULT_LINEAR: *allocator = fetchIonAllocator(); break; case C2PlatformAllocatorStore::GRALLOC: case C2AllocatorStore::DEFAULT_GRAPHIC: *allocator = fetchGrallocAllocator(); break; case C2PlatformAllocatorStore::BUFFERQUEUE: *allocator = fetchBufferQueueAllocator(); break; default: // Try to create allocator from platform store plugins. c2_status_t res = C2PlatformStorePluginLoader::GetInstance()->createAllocator(id, allocator); if (res != C2_OK) { return res; } break; } if (*allocator == nullptr) { return C2_NO_MEMORY; } return C2_OK; } namespace { std::mutex gIonAllocatorMutex; std::weak_ptr gIonAllocator; void UseComponentStoreForIonAllocator( const std::shared_ptr allocator, std::shared_ptr store) { C2AllocatorIon::UsageMapperFn mapper; uint64_t minUsage = 0; uint64_t maxUsage = C2MemoryUsage(C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE).expected; size_t blockSize = getpagesize(); // query min and max usage as well as block size via supported values C2StoreIonUsageInfo usageInfo; std::vector query = { C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.usage)), C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.capacity)), }; c2_status_t res = store->querySupportedValues_sm(query); if (res == C2_OK) { if (query[0].status == C2_OK) { const C2FieldSupportedValues &fsv = query[0].values; if (fsv.type == C2FieldSupportedValues::FLAGS && !fsv.values.empty()) { minUsage = fsv.values[0].u64; maxUsage = 0; for (C2Value::Primitive v : fsv.values) { maxUsage |= v.u64; } } } if (query[1].status == C2_OK) { const C2FieldSupportedValues &fsv = query[1].values; if (fsv.type == C2FieldSupportedValues::RANGE && fsv.range.step.u32 > 0) { blockSize = fsv.range.step.u32; } } mapper = [store](C2MemoryUsage usage, size_t capacity, size_t *align, unsigned *heapMask, unsigned *flags) -> c2_status_t { if (capacity > UINT32_MAX) { return C2_BAD_VALUE; } C2StoreIonUsageInfo usageInfo = { usage.expected, capacity }; std::vector> failures; // TODO: remove c2_status_t res = store->config_sm({&usageInfo}, &failures); if (res == C2_OK) { *align = usageInfo.minAlignment; *heapMask = usageInfo.heapMask; *flags = usageInfo.allocFlags; } return res; }; } allocator->setUsageMapper(mapper, minUsage, maxUsage, blockSize); } } void C2PlatformAllocatorStoreImpl::setComponentStore(std::shared_ptr store) { // technically this set lock is not needed, but is here for safety in case we add more // getter orders std::lock_guard lock(_mComponentStoreSetLock); { std::lock_guard lock(_mComponentStoreReadLock); _mComponentStore = store; } std::shared_ptr allocator; { std::lock_guard lock(gIonAllocatorMutex); allocator = gIonAllocator.lock(); } if (allocator) { UseComponentStoreForIonAllocator(allocator, store); } } std::shared_ptr C2PlatformAllocatorStoreImpl::fetchIonAllocator() { std::lock_guard lock(gIonAllocatorMutex); std::shared_ptr allocator = gIonAllocator.lock(); if (allocator == nullptr) { std::shared_ptr componentStore; { std::lock_guard lock(_mComponentStoreReadLock); componentStore = _mComponentStore; } allocator = std::make_shared(C2PlatformAllocatorStore::ION); UseComponentStoreForIonAllocator(allocator, componentStore); gIonAllocator = allocator; } return allocator; } std::shared_ptr C2PlatformAllocatorStoreImpl::fetchGrallocAllocator() { static std::mutex mutex; static std::weak_ptr grallocAllocator; std::lock_guard lock(mutex); std::shared_ptr allocator = grallocAllocator.lock(); if (allocator == nullptr) { allocator = std::make_shared(C2PlatformAllocatorStore::GRALLOC); grallocAllocator = allocator; } return allocator; } std::shared_ptr C2PlatformAllocatorStoreImpl::fetchBufferQueueAllocator() { static std::mutex mutex; static std::weak_ptr grallocAllocator; std::lock_guard lock(mutex); std::shared_ptr allocator = grallocAllocator.lock(); if (allocator == nullptr) { allocator = std::make_shared( C2PlatformAllocatorStore::BUFFERQUEUE, true); grallocAllocator = allocator; } return allocator; } namespace { std::mutex gPreferredComponentStoreMutex; std::shared_ptr gPreferredComponentStore; std::mutex gPlatformAllocatorStoreMutex; std::weak_ptr gPlatformAllocatorStore; } std::shared_ptr GetCodec2PlatformAllocatorStore() { std::lock_guard lock(gPlatformAllocatorStoreMutex); std::shared_ptr store = gPlatformAllocatorStore.lock(); if (store == nullptr) { store = std::make_shared(); store->setComponentStore(GetPreferredCodec2ComponentStore()); gPlatformAllocatorStore = store; } return store; } void SetPreferredCodec2ComponentStore(std::shared_ptr componentStore) { static std::mutex mutex; std::lock_guard lock(mutex); // don't interleve set-s // update preferred store { std::lock_guard lock(gPreferredComponentStoreMutex); gPreferredComponentStore = componentStore; } // update platform allocator's store as well if it is alive std::shared_ptr allocatorStore; { std::lock_guard lock(gPlatformAllocatorStoreMutex); allocatorStore = gPlatformAllocatorStore.lock(); } if (allocatorStore) { allocatorStore->setComponentStore(componentStore); } } std::shared_ptr GetPreferredCodec2ComponentStore() { std::lock_guard lock(gPreferredComponentStoreMutex); return gPreferredComponentStore ? gPreferredComponentStore : GetCodec2PlatformComponentStore(); } namespace { class _C2BlockPoolCache { public: _C2BlockPoolCache() : mBlockPoolSeqId(C2BlockPool::PLATFORM_START + 1) {} c2_status_t _createBlockPool( C2PlatformAllocatorStore::id_t allocatorId, std::shared_ptr component, C2BlockPool::local_id_t poolId, std::shared_ptr *pool) { std::shared_ptr allocatorStore = GetCodec2PlatformAllocatorStore(); std::shared_ptr allocator; c2_status_t res = C2_NOT_FOUND; switch(allocatorId) { case C2PlatformAllocatorStore::ION: case C2AllocatorStore::DEFAULT_LINEAR: res = allocatorStore->fetchAllocator( C2AllocatorStore::DEFAULT_LINEAR, &allocator); if (res == C2_OK) { std::shared_ptr ptr = std::make_shared( allocator, poolId); *pool = ptr; mBlockPools[poolId] = ptr; mComponents[poolId] = component; } break; case C2PlatformAllocatorStore::GRALLOC: case C2AllocatorStore::DEFAULT_GRAPHIC: res = allocatorStore->fetchAllocator( C2AllocatorStore::DEFAULT_GRAPHIC, &allocator); if (res == C2_OK) { std::shared_ptr ptr = std::make_shared(allocator, poolId); *pool = ptr; mBlockPools[poolId] = ptr; mComponents[poolId] = component; } break; case C2PlatformAllocatorStore::BUFFERQUEUE: res = allocatorStore->fetchAllocator( C2PlatformAllocatorStore::BUFFERQUEUE, &allocator); if (res == C2_OK) { std::shared_ptr ptr = std::make_shared( allocator, poolId); *pool = ptr; mBlockPools[poolId] = ptr; mComponents[poolId] = component; } break; default: // Try to create block pool from platform store plugins. std::shared_ptr ptr; res = C2PlatformStorePluginLoader::GetInstance()->createBlockPool( allocatorId, poolId, &ptr); if (res == C2_OK) { *pool = ptr; mBlockPools[poolId] = ptr; mComponents[poolId] = component; } break; } return res; } c2_status_t createBlockPool( C2PlatformAllocatorStore::id_t allocatorId, std::shared_ptr component, std::shared_ptr *pool) { return _createBlockPool(allocatorId, component, mBlockPoolSeqId++, pool); } bool getBlockPool( C2BlockPool::local_id_t blockPoolId, std::shared_ptr component, std::shared_ptr *pool) { // TODO: use one iterator for multiple blockpool type scalability. std::shared_ptr ptr; auto it = mBlockPools.find(blockPoolId); if (it != mBlockPools.end()) { ptr = it->second.lock(); if (!ptr) { mBlockPools.erase(it); mComponents.erase(blockPoolId); } else { auto found = mComponents.find(blockPoolId); if (component == found->second.lock()) { *pool = ptr; return true; } } } return false; } private: C2BlockPool::local_id_t mBlockPoolSeqId; std::map> mBlockPools; std::map> mComponents; }; static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache = std::make_unique<_C2BlockPoolCache>(); static std::mutex sBlockPoolCacheMutex; } // anynymous namespace c2_status_t GetCodec2BlockPool( C2BlockPool::local_id_t id, std::shared_ptr component, std::shared_ptr *pool) { pool->reset(); std::lock_guard lock(sBlockPoolCacheMutex); std::shared_ptr allocatorStore = GetCodec2PlatformAllocatorStore(); std::shared_ptr allocator; c2_status_t res = C2_NOT_FOUND; if (id >= C2BlockPool::PLATFORM_START) { if (sBlockPoolCache->getBlockPool(id, component, pool)) { return C2_OK; } } switch (id) { case C2BlockPool::BASIC_LINEAR: res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator); if (res == C2_OK) { *pool = std::make_shared(allocator); } break; case C2BlockPool::BASIC_GRAPHIC: res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator); if (res == C2_OK) { *pool = std::make_shared(allocator); } break; // TODO: remove this. this is temporary case C2BlockPool::PLATFORM_START: res = sBlockPoolCache->_createBlockPool( C2PlatformAllocatorStore::BUFFERQUEUE, component, id, pool); break; default: break; } return res; } c2_status_t CreateCodec2BlockPool( C2PlatformAllocatorStore::id_t allocatorId, std::shared_ptr component, std::shared_ptr *pool) { pool->reset(); std::lock_guard lock(sBlockPoolCacheMutex); return sBlockPoolCache->createBlockPool(allocatorId, component, pool); } class C2PlatformComponentStore : public C2ComponentStore { public: virtual std::vector> listComponents() override; virtual std::shared_ptr getParamReflector() const override; virtual C2String getName() const override; virtual c2_status_t querySupportedValues_sm( std::vector &fields) const override; virtual c2_status_t querySupportedParams_nb( std::vector> *const params) const override; virtual c2_status_t query_sm( const std::vector &stackParams, const std::vector &heapParamIndices, std::vector> *const heapParams) const override; virtual c2_status_t createInterface( C2String name, std::shared_ptr *const interface) override; virtual c2_status_t createComponent( C2String name, std::shared_ptr *const component) override; virtual c2_status_t copyBuffer( std::shared_ptr src, std::shared_ptr dst) override; virtual c2_status_t config_sm( const std::vector ¶ms, std::vector> *const failures) override; C2PlatformComponentStore(); virtual ~C2PlatformComponentStore() override = default; private: /** * An object encapsulating a loaded component module. * * \todo provide a way to add traits to known components here to avoid loading the .so-s * for listComponents */ struct ComponentModule : public C2ComponentFactory, public std::enable_shared_from_this { virtual c2_status_t createComponent( c2_node_id_t id, std::shared_ptr *component, ComponentDeleter deleter = std::default_delete()) override; virtual c2_status_t createInterface( c2_node_id_t id, std::shared_ptr *interface, InterfaceDeleter deleter = std::default_delete()) override; /** * \returns the traits of the component in this module. */ std::shared_ptr getTraits(); /** * Creates an uninitialized component module. * * \param name[in] component name. * * \note Only used by ComponentLoader. */ ComponentModule() : mInit(C2_NO_INIT), mLibHandle(nullptr), createFactory(nullptr), destroyFactory(nullptr), mComponentFactory(nullptr) { } /** * Initializes a component module with a given library path. Must be called exactly once. * * \note Only used by ComponentLoader. * * \param alias[in] module alias * \param libPath[in] library path * * \retval C2_OK the component module has been successfully loaded * \retval C2_NO_MEMORY not enough memory to loading the component module * \retval C2_NOT_FOUND could not locate the component module * \retval C2_CORRUPTED the component module could not be loaded (unexpected) * \retval C2_REFUSED permission denied to load the component module (unexpected) * \retval C2_TIMED_OUT could not load the module within the time limit (unexpected) */ c2_status_t init(std::string alias, std::string libPath); virtual ~ComponentModule() override; protected: std::recursive_mutex mLock; ///< lock protecting mTraits std::shared_ptr mTraits; ///< cached component traits c2_status_t mInit; ///< initialization result void *mLibHandle; ///< loaded library handle C2ComponentFactory::CreateCodec2FactoryFunc createFactory; ///< loaded create function C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory; ///< loaded destroy function C2ComponentFactory *mComponentFactory; ///< loaded/created component factory }; /** * An object encapsulating a loadable component module. * * \todo make this also work for enumerations */ struct ComponentLoader { /** * Load the component module. * * This method simply returns the component module if it is already currently loaded, or * attempts to load it if it is not. * * \param module[out] pointer to the shared pointer where the loaded module shall be stored. * This will be nullptr on error. * * \retval C2_OK the component module has been successfully loaded * \retval C2_NO_MEMORY not enough memory to loading the component module * \retval C2_NOT_FOUND could not locate the component module * \retval C2_CORRUPTED the component module could not be loaded * \retval C2_REFUSED permission denied to load the component module */ c2_status_t fetchModule(std::shared_ptr *module) { c2_status_t res = C2_OK; std::lock_guard lock(mMutex); std::shared_ptr localModule = mModule.lock(); if (localModule == nullptr) { localModule = std::make_shared(); res = localModule->init(mAlias, mLibPath); if (res == C2_OK) { mModule = localModule; } } *module = localModule; return res; } /** * Creates a component loader for a specific library path (or name). */ ComponentLoader(std::string alias, std::string libPath) : mAlias(alias), mLibPath(libPath) {} private: std::mutex mMutex; ///< mutex guarding the module std::weak_ptr mModule; ///< weak reference to the loaded module std::string mAlias; ///< component alias std::string mLibPath; ///< library path }; struct Interface : public C2InterfaceHelper { std::shared_ptr mIonUsageInfo; Interface(std::shared_ptr reflector) : C2InterfaceHelper(reflector) { setDerivedInstance(this); struct Setter { static C2R setIonUsage(bool /* mayBlock */, C2P &me) { me.set().heapMask = ~0; me.set().allocFlags = 0; me.set().minAlignment = 0; return C2R::Ok(); } }; addParameter( DefineParam(mIonUsageInfo, "ion-usage") .withDefault(new C2StoreIonUsageInfo()) .withFields({ C2F(mIonUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}), C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024), C2F(mIonUsageInfo, heapMask).any(), C2F(mIonUsageInfo, allocFlags).flags({}), C2F(mIonUsageInfo, minAlignment).equalTo(0) }) .withSetter(Setter::setIonUsage) .build()); } }; /** * Retrieves the component loader for a component. * * \return a non-ref-holding pointer to the component loader. * * \retval C2_OK the component loader has been successfully retrieved * \retval C2_NO_MEMORY not enough memory to locate the component loader * \retval C2_NOT_FOUND could not locate the component to be loaded * \retval C2_CORRUPTED the component loader could not be identified due to some modules being * corrupted (this can happen if the name does not refer to an already * identified component but some components could not be loaded due to * bad library) * \retval C2_REFUSED permission denied to find the component loader for the named component * (this can happen if the name does not refer to an already identified * component but some components could not be loaded due to lack of * permissions) */ c2_status_t findComponent(C2String name, ComponentLoader **loader); std::map mComponents; ///< map of name -> components std::vector mComponentsList; ///< list of components std::shared_ptr mReflector; Interface mInterface; }; c2_status_t C2PlatformComponentStore::ComponentModule::init( std::string alias, std::string libPath) { ALOGV("in %s", __func__); ALOGV("loading dll"); mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE); if (mLibHandle == nullptr) { // could be access/symbol or simply not being there ALOGD("could not dlopen %s: %s", libPath.c_str(), dlerror()); mInit = C2_CORRUPTED; } else { createFactory = (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory"); destroyFactory = (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory"); mComponentFactory = createFactory(); if (mComponentFactory == nullptr) { ALOGD("could not create factory in %s", libPath.c_str()); mInit = C2_NO_MEMORY; } else { mInit = C2_OK; } } if (mInit != C2_OK) { return mInit; } std::shared_ptr intf; c2_status_t res = createInterface(0, &intf); if (res != C2_OK) { ALOGD("failed to create interface: %d", res); return mInit; } std::shared_ptr traits(new (std::nothrow) C2Component::Traits); if (traits) { if (alias != intf->getName()) { ALOGV("%s is alias to %s", alias.c_str(), intf->getName().c_str()); } traits->name = alias; // TODO: get this from interface properly. bool encoder = (traits->name.find("encoder") != std::string::npos); uint32_t mediaTypeIndex = encoder ? C2PortMimeConfig::output::PARAM_TYPE : C2PortMimeConfig::input::PARAM_TYPE; std::vector> params; res = intf->query_vb({}, { mediaTypeIndex }, C2_MAY_BLOCK, ¶ms); if (res != C2_OK) { ALOGD("failed to query interface: %d", res); return mInit; } if (params.size() != 1u) { ALOGD("failed to query interface: unexpected vector size: %zu", params.size()); return mInit; } C2PortMimeConfig *mediaTypeConfig = (C2PortMimeConfig *)(params[0].get()); if (mediaTypeConfig == nullptr) { ALOGD("failed to query media type"); return mInit; } traits->mediaType = mediaTypeConfig->m.value; // TODO: get this properly. traits->rank = 0x200; // TODO: define these values properly bool decoder = (traits->name.find("decoder") != std::string::npos); traits->kind = decoder ? C2Component::KIND_DECODER : encoder ? C2Component::KIND_ENCODER : C2Component::KIND_OTHER; if (strncmp(traits->mediaType.c_str(), "audio/", 6) == 0) { traits->domain = C2Component::DOMAIN_AUDIO; } else if (strncmp(traits->mediaType.c_str(), "video/", 6) == 0) { traits->domain = C2Component::DOMAIN_VIDEO; } else if (strncmp(traits->mediaType.c_str(), "image/", 6) == 0) { traits->domain = C2Component::DOMAIN_IMAGE; } else { traits->domain = C2Component::DOMAIN_OTHER; } } mTraits = traits; return mInit; } C2PlatformComponentStore::ComponentModule::~ComponentModule() { ALOGV("in %s", __func__); if (destroyFactory && mComponentFactory) { destroyFactory(mComponentFactory); } if (mLibHandle) { ALOGV("unloading dll"); dlclose(mLibHandle); } } c2_status_t C2PlatformComponentStore::ComponentModule::createInterface( c2_node_id_t id, std::shared_ptr *interface, std::function deleter) { interface->reset(); if (mInit != C2_OK) { return mInit; } std::shared_ptr module = shared_from_this(); c2_status_t res = mComponentFactory->createInterface( id, interface, [module, deleter](C2ComponentInterface *p) mutable { // capture module so that we ensure we still have it while deleting interface deleter(p); // delete interface first module.reset(); // remove module ref (not technically needed) }); return res; } c2_status_t C2PlatformComponentStore::ComponentModule::createComponent( c2_node_id_t id, std::shared_ptr *component, std::function deleter) { component->reset(); if (mInit != C2_OK) { return mInit; } std::shared_ptr module = shared_from_this(); c2_status_t res = mComponentFactory->createComponent( id, component, [module, deleter](C2Component *p) mutable { // capture module so that we ensure we still have it while deleting component deleter(p); // delete component first module.reset(); // remove module ref (not technically needed) }); return res; } std::shared_ptr C2PlatformComponentStore::ComponentModule::getTraits() { std::unique_lock lock(mLock); return mTraits; } C2PlatformComponentStore::C2PlatformComponentStore() : mReflector(std::make_shared()), mInterface(mReflector) { auto emplace = [this](const char *alias, const char *libPath) { // ComponentLoader is neither copiable nor movable, so it must be // constructed in-place. Now ComponentLoader takes two arguments in // constructor, so we need to use piecewise_construct to achieve this // behavior. mComponents.emplace( std::piecewise_construct, std::forward_as_tuple(alias), std::forward_as_tuple(alias, libPath)); mComponentsList.emplace_back(alias); }; // TODO: move this also into a .so so it can be updated emplace("c2.android.avc.decoder", "libstagefright_soft_c2avcdec.so"); emplace("c2.android.avc.encoder", "libstagefright_soft_c2avcenc.so"); emplace("c2.android.aac.decoder", "libstagefright_soft_c2aacdec.so"); emplace("c2.android.aac.encoder", "libstagefright_soft_c2aacenc.so"); emplace("c2.android.amrnb.decoder", "libstagefright_soft_c2amrnbdec.so"); emplace("c2.android.amrnb.encoder", "libstagefright_soft_c2amrnbenc.so"); emplace("c2.android.amrwb.decoder", "libstagefright_soft_c2amrwbdec.so"); emplace("c2.android.amrwb.encoder", "libstagefright_soft_c2amrwbenc.so"); emplace("c2.android.hevc.decoder", "libstagefright_soft_c2hevcdec.so"); emplace("c2.android.g711.alaw.decoder", "libstagefright_soft_c2g711alawdec.so"); emplace("c2.android.g711.mlaw.decoder", "libstagefright_soft_c2g711mlawdec.so"); emplace("c2.android.mpeg2.decoder", "libstagefright_soft_c2mpeg2dec.so"); emplace("c2.android.h263.decoder", "libstagefright_soft_c2h263dec.so"); emplace("c2.android.h263.encoder", "libstagefright_soft_c2h263enc.so"); emplace("c2.android.mpeg4.decoder", "libstagefright_soft_c2mpeg4dec.so"); emplace("c2.android.mpeg4.encoder", "libstagefright_soft_c2mpeg4enc.so"); emplace("c2.android.mp3.decoder", "libstagefright_soft_c2mp3dec.so"); emplace("c2.android.vorbis.decoder", "libstagefright_soft_c2vorbisdec.so"); emplace("c2.android.opus.decoder", "libstagefright_soft_c2opusdec.so"); emplace("c2.android.vp8.decoder", "libstagefright_soft_c2vp8dec.so"); emplace("c2.android.vp9.decoder", "libstagefright_soft_c2vp9dec.so"); emplace("c2.android.vp8.encoder", "libstagefright_soft_c2vp8enc.so"); emplace("c2.android.vp9.encoder", "libstagefright_soft_c2vp9enc.so"); emplace("c2.android.raw.decoder", "libstagefright_soft_c2rawdec.so"); emplace("c2.android.flac.decoder", "libstagefright_soft_c2flacdec.so"); emplace("c2.android.flac.encoder", "libstagefright_soft_c2flacenc.so"); emplace("c2.android.gsm.decoder", "libstagefright_soft_c2gsmdec.so"); emplace("c2.android.xaac.decoder", "libstagefright_soft_c2xaacdec.so"); // "Aliases" // TODO: use aliases proper from C2Component::Traits emplace("OMX.google.h264.decoder", "libstagefright_soft_c2avcdec.so"); emplace("OMX.google.h264.encoder", "libstagefright_soft_c2avcenc.so"); emplace("OMX.google.aac.decoder", "libstagefright_soft_c2aacdec.so"); emplace("OMX.google.aac.encoder", "libstagefright_soft_c2aacenc.so"); emplace("OMX.google.amrnb.decoder", "libstagefright_soft_c2amrnbdec.so"); emplace("OMX.google.amrnb.encoder", "libstagefright_soft_c2amrnbenc.so"); emplace("OMX.google.amrwb.decoder", "libstagefright_soft_c2amrwbdec.so"); emplace("OMX.google.amrwb.encoder", "libstagefright_soft_c2amrwbenc.so"); emplace("OMX.google.hevc.decoder", "libstagefright_soft_c2hevcdec.so"); emplace("OMX.google.g711.alaw.decoder", "libstagefright_soft_c2g711alawdec.so"); emplace("OMX.google.g711.mlaw.decoder", "libstagefright_soft_c2g711mlawdec.so"); emplace("OMX.google.mpeg2.decoder", "libstagefright_soft_c2mpeg2dec.so"); emplace("OMX.google.h263.decoder", "libstagefright_soft_c2h263dec.so"); emplace("OMX.google.h263.encoder", "libstagefright_soft_c2h263enc.so"); emplace("OMX.google.mpeg4.decoder", "libstagefright_soft_c2mpeg4dec.so"); emplace("OMX.google.mpeg4.encoder", "libstagefright_soft_c2mpeg4enc.so"); emplace("OMX.google.mp3.decoder", "libstagefright_soft_c2mp3dec.so"); emplace("OMX.google.vorbis.decoder", "libstagefright_soft_c2vorbisdec.so"); emplace("OMX.google.opus.decoder", "libstagefright_soft_c2opusdec.so"); emplace("OMX.google.vp8.decoder", "libstagefright_soft_c2vp8dec.so"); emplace("OMX.google.vp9.decoder", "libstagefright_soft_c2vp9dec.so"); emplace("OMX.google.vp8.encoder", "libstagefright_soft_c2vp8enc.so"); emplace("OMX.google.vp9.encoder", "libstagefright_soft_c2vp9enc.so"); emplace("OMX.google.raw.decoder", "libstagefright_soft_c2rawdec.so"); emplace("OMX.google.flac.decoder", "libstagefright_soft_c2flacdec.so"); emplace("OMX.google.flac.encoder", "libstagefright_soft_c2flacenc.so"); emplace("OMX.google.gsm.decoder", "libstagefright_soft_c2gsmdec.so"); emplace("OMX.google.xaac.decoder", "libstagefright_soft_c2xaacdec.so"); } c2_status_t C2PlatformComponentStore::copyBuffer( std::shared_ptr src, std::shared_ptr dst) { (void)src; (void)dst; return C2_OMITTED; } c2_status_t C2PlatformComponentStore::query_sm( const std::vector &stackParams, const std::vector &heapParamIndices, std::vector> *const heapParams) const { return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams); } c2_status_t C2PlatformComponentStore::config_sm( const std::vector ¶ms, std::vector> *const failures) { return mInterface.config(params, C2_MAY_BLOCK, failures); } std::vector> C2PlatformComponentStore::listComponents() { // This method SHALL return within 500ms. std::vector> list; for (const C2String &alias : mComponentsList) { ComponentLoader &loader = mComponents.at(alias); std::shared_ptr module; c2_status_t res = loader.fetchModule(&module); if (res == C2_OK) { std::shared_ptr traits = module->getTraits(); if (traits) { list.push_back(traits); } } } return list; } c2_status_t C2PlatformComponentStore::findComponent(C2String name, ComponentLoader **loader) { *loader = nullptr; auto pos = mComponents.find(name); // TODO: check aliases if (pos == mComponents.end()) { return C2_NOT_FOUND; } *loader = &pos->second; return C2_OK; } c2_status_t C2PlatformComponentStore::createComponent( C2String name, std::shared_ptr *const component) { // This method SHALL return within 100ms. component->reset(); ComponentLoader *loader; c2_status_t res = findComponent(name, &loader); if (res == C2_OK) { std::shared_ptr module; res = loader->fetchModule(&module); if (res == C2_OK) { // TODO: get a unique node ID res = module->createComponent(0, component); } } return res; } c2_status_t C2PlatformComponentStore::createInterface( C2String name, std::shared_ptr *const interface) { // This method SHALL return within 100ms. interface->reset(); ComponentLoader *loader; c2_status_t res = findComponent(name, &loader); if (res == C2_OK) { std::shared_ptr module; res = loader->fetchModule(&module); if (res == C2_OK) { // TODO: get a unique node ID res = module->createInterface(0, interface); } } return res; } c2_status_t C2PlatformComponentStore::querySupportedParams_nb( std::vector> *const params) const { return mInterface.querySupportedParams(params); } c2_status_t C2PlatformComponentStore::querySupportedValues_sm( std::vector &fields) const { return mInterface.querySupportedValues(fields, C2_MAY_BLOCK); } C2String C2PlatformComponentStore::getName() const { return "android.componentStore.platform"; } std::shared_ptr C2PlatformComponentStore::getParamReflector() const { return mReflector; } std::shared_ptr GetCodec2PlatformComponentStore() { static std::mutex mutex; static std::weak_ptr platformStore; std::lock_guard lock(mutex); std::shared_ptr store = platformStore.lock(); if (store == nullptr) { store = std::make_shared(); platformStore = store; } return store; } } // namespace android