1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "C2Store" 18 #define LOG_NDEBUG 0 19 #include <utils/Log.h> 20 21 #include <C2AllocatorGralloc.h> 22 #include <C2AllocatorIon.h> 23 #include <C2BufferPriv.h> 24 #include <C2BqBufferPriv.h> 25 #include <C2Component.h> 26 #include <C2Config.h> 27 #include <C2PlatformStorePluginLoader.h> 28 #include <C2PlatformSupport.h> 29 #include <util/C2InterfaceHelper.h> 30 31 #include <dlfcn.h> 32 #include <unistd.h> // getpagesize 33 34 #include <map> 35 #include <memory> 36 #include <mutex> 37 38 namespace android { 39 40 /** 41 * Returns the preferred component store in this process to access its interface. 42 */ 43 std::shared_ptr<C2ComponentStore> GetPreferredCodec2ComponentStore(); 44 45 /** 46 * The platform allocator store provides basic allocator-types for the framework based on ion and 47 * gralloc. Allocators are not meant to be updatable. 48 * 49 * \todo Provide allocator based on ashmem 50 * \todo Move ion allocation into its HIDL or provide some mapping from memory usage to ion flags 51 * \todo Make this allocator store extendable 52 */ 53 class C2PlatformAllocatorStoreImpl : public C2PlatformAllocatorStore { 54 public: 55 C2PlatformAllocatorStoreImpl(); 56 57 virtual c2_status_t fetchAllocator( 58 id_t id, std::shared_ptr<C2Allocator> *const allocator) override; 59 60 virtual std::vector<std::shared_ptr<const C2Allocator::Traits>> listAllocators_nb() 61 const override { 62 return std::vector<std::shared_ptr<const C2Allocator::Traits>>(); /// \todo 63 } 64 65 virtual C2String getName() const override { 66 return "android.allocator-store"; 67 } 68 69 void setComponentStore(std::shared_ptr<C2ComponentStore> store); 70 71 ~C2PlatformAllocatorStoreImpl() override = default; 72 73 private: 74 /// returns a shared-singleton ion allocator 75 std::shared_ptr<C2Allocator> fetchIonAllocator(); 76 77 /// returns a shared-singleton gralloc allocator 78 std::shared_ptr<C2Allocator> fetchGrallocAllocator(); 79 80 /// returns a shared-singleton bufferqueue supporting gralloc allocator 81 std::shared_ptr<C2Allocator> fetchBufferQueueAllocator(); 82 83 /// component store to use 84 std::mutex _mComponentStoreSetLock; // protects the entire updating _mComponentStore and its 85 // dependencies 86 std::mutex _mComponentStoreReadLock; // must protect only read/write of _mComponentStore 87 std::shared_ptr<C2ComponentStore> _mComponentStore; 88 }; 89 90 C2PlatformAllocatorStoreImpl::C2PlatformAllocatorStoreImpl() { 91 } 92 93 c2_status_t C2PlatformAllocatorStoreImpl::fetchAllocator( 94 id_t id, std::shared_ptr<C2Allocator> *const allocator) { 95 allocator->reset(); 96 switch (id) { 97 // TODO: should we implement a generic registry for all, and use that? 98 case C2PlatformAllocatorStore::ION: 99 case C2AllocatorStore::DEFAULT_LINEAR: 100 *allocator = fetchIonAllocator(); 101 break; 102 103 case C2PlatformAllocatorStore::GRALLOC: 104 case C2AllocatorStore::DEFAULT_GRAPHIC: 105 *allocator = fetchGrallocAllocator(); 106 break; 107 108 case C2PlatformAllocatorStore::BUFFERQUEUE: 109 *allocator = fetchBufferQueueAllocator(); 110 break; 111 112 default: 113 return C2_NOT_FOUND; 114 } 115 if (*allocator == nullptr) { 116 return C2_NO_MEMORY; 117 } 118 return C2_OK; 119 } 120 121 namespace { 122 123 std::mutex gIonAllocatorMutex; 124 std::weak_ptr<C2AllocatorIon> gIonAllocator; 125 126 void UseComponentStoreForIonAllocator( 127 const std::shared_ptr<C2AllocatorIon> allocator, 128 std::shared_ptr<C2ComponentStore> store) { 129 C2AllocatorIon::UsageMapperFn mapper; 130 uint64_t minUsage = 0; 131 uint64_t maxUsage = C2MemoryUsage(C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE).expected; 132 size_t blockSize = getpagesize(); 133 134 // query min and max usage as well as block size via supported values 135 C2StoreIonUsageInfo usageInfo; 136 std::vector<C2FieldSupportedValuesQuery> query = { 137 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.usage)), 138 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.capacity)), 139 }; 140 c2_status_t res = store->querySupportedValues_sm(query); 141 if (res == C2_OK) { 142 if (query[0].status == C2_OK) { 143 const C2FieldSupportedValues &fsv = query[0].values; 144 if (fsv.type == C2FieldSupportedValues::FLAGS && !fsv.values.empty()) { 145 minUsage = fsv.values[0].u64; 146 maxUsage = 0; 147 for (C2Value::Primitive v : fsv.values) { 148 maxUsage |= v.u64; 149 } 150 } 151 } 152 if (query[1].status == C2_OK) { 153 const C2FieldSupportedValues &fsv = query[1].values; 154 if (fsv.type == C2FieldSupportedValues::RANGE && fsv.range.step.u32 > 0) { 155 blockSize = fsv.range.step.u32; 156 } 157 } 158 159 mapper = [store](C2MemoryUsage usage, size_t capacity, 160 size_t *align, unsigned *heapMask, unsigned *flags) -> c2_status_t { 161 if (capacity > UINT32_MAX) { 162 return C2_BAD_VALUE; 163 } 164 C2StoreIonUsageInfo usageInfo = { usage.expected, capacity }; 165 std::vector<std::unique_ptr<C2SettingResult>> failures; // TODO: remove 166 c2_status_t res = store->config_sm({&usageInfo}, &failures); 167 if (res == C2_OK) { 168 *align = usageInfo.minAlignment; 169 *heapMask = usageInfo.heapMask; 170 *flags = usageInfo.allocFlags; 171 } 172 return res; 173 }; 174 } 175 176 allocator->setUsageMapper(mapper, minUsage, maxUsage, blockSize); 177 } 178 179 } 180 181 void C2PlatformAllocatorStoreImpl::setComponentStore(std::shared_ptr<C2ComponentStore> store) { 182 // technically this set lock is not needed, but is here for safety in case we add more 183 // getter orders 184 std::lock_guard<std::mutex> lock(_mComponentStoreSetLock); 185 { 186 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock); 187 _mComponentStore = store; 188 } 189 std::shared_ptr<C2AllocatorIon> allocator; 190 { 191 std::lock_guard<std::mutex> lock(gIonAllocatorMutex); 192 allocator = gIonAllocator.lock(); 193 } 194 if (allocator) { 195 UseComponentStoreForIonAllocator(allocator, store); 196 } 197 } 198 199 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchIonAllocator() { 200 std::lock_guard<std::mutex> lock(gIonAllocatorMutex); 201 std::shared_ptr<C2AllocatorIon> allocator = gIonAllocator.lock(); 202 if (allocator == nullptr) { 203 std::shared_ptr<C2ComponentStore> componentStore; 204 { 205 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock); 206 componentStore = _mComponentStore; 207 } 208 allocator = std::make_shared<C2AllocatorIon>(C2PlatformAllocatorStore::ION); 209 UseComponentStoreForIonAllocator(allocator, componentStore); 210 gIonAllocator = allocator; 211 } 212 return allocator; 213 } 214 215 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchGrallocAllocator() { 216 static std::mutex mutex; 217 static std::weak_ptr<C2Allocator> grallocAllocator; 218 std::lock_guard<std::mutex> lock(mutex); 219 std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock(); 220 if (allocator == nullptr) { 221 allocator = std::make_shared<C2AllocatorGralloc>(C2PlatformAllocatorStore::GRALLOC); 222 grallocAllocator = allocator; 223 } 224 return allocator; 225 } 226 227 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBufferQueueAllocator() { 228 static std::mutex mutex; 229 static std::weak_ptr<C2Allocator> grallocAllocator; 230 std::lock_guard<std::mutex> lock(mutex); 231 std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock(); 232 if (allocator == nullptr) { 233 allocator = std::make_shared<C2AllocatorGralloc>( 234 C2PlatformAllocatorStore::BUFFERQUEUE, true); 235 grallocAllocator = allocator; 236 } 237 return allocator; 238 } 239 240 namespace { 241 std::mutex gPreferredComponentStoreMutex; 242 std::shared_ptr<C2ComponentStore> gPreferredComponentStore; 243 244 std::mutex gPlatformAllocatorStoreMutex; 245 std::weak_ptr<C2PlatformAllocatorStoreImpl> gPlatformAllocatorStore; 246 } 247 248 std::shared_ptr<C2AllocatorStore> GetCodec2PlatformAllocatorStore() { 249 std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex); 250 std::shared_ptr<C2PlatformAllocatorStoreImpl> store = gPlatformAllocatorStore.lock(); 251 if (store == nullptr) { 252 store = std::make_shared<C2PlatformAllocatorStoreImpl>(); 253 store->setComponentStore(GetPreferredCodec2ComponentStore()); 254 gPlatformAllocatorStore = store; 255 } 256 return store; 257 } 258 259 void SetPreferredCodec2ComponentStore(std::shared_ptr<C2ComponentStore> componentStore) { 260 static std::mutex mutex; 261 std::lock_guard<std::mutex> lock(mutex); // don't interleve set-s 262 263 // update preferred store 264 { 265 std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex); 266 gPreferredComponentStore = componentStore; 267 } 268 269 // update platform allocator's store as well if it is alive 270 std::shared_ptr<C2PlatformAllocatorStoreImpl> allocatorStore; 271 { 272 std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex); 273 allocatorStore = gPlatformAllocatorStore.lock(); 274 } 275 if (allocatorStore) { 276 allocatorStore->setComponentStore(componentStore); 277 } 278 } 279 280 std::shared_ptr<C2ComponentStore> GetPreferredCodec2ComponentStore() { 281 std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex); 282 return gPreferredComponentStore ? gPreferredComponentStore : GetCodec2PlatformComponentStore(); 283 } 284 285 namespace { 286 287 class _C2BlockPoolCache { 288 public: 289 _C2BlockPoolCache() : mBlockPoolSeqId(C2BlockPool::PLATFORM_START + 1) {} 290 291 c2_status_t _createBlockPool( 292 C2PlatformAllocatorStore::id_t allocatorId, 293 std::shared_ptr<const C2Component> component, 294 C2BlockPool::local_id_t poolId, 295 std::shared_ptr<C2BlockPool> *pool) { 296 std::shared_ptr<C2AllocatorStore> allocatorStore = 297 GetCodec2PlatformAllocatorStore(); 298 std::shared_ptr<C2Allocator> allocator; 299 c2_status_t res = C2_NOT_FOUND; 300 301 switch(allocatorId) { 302 case C2PlatformAllocatorStore::ION: 303 case C2AllocatorStore::DEFAULT_LINEAR: 304 res = allocatorStore->fetchAllocator( 305 C2AllocatorStore::DEFAULT_LINEAR, &allocator); 306 if (res == C2_OK) { 307 std::shared_ptr<C2BlockPool> ptr = 308 std::make_shared<C2PooledBlockPool>( 309 allocator, poolId); 310 *pool = ptr; 311 mBlockPools[poolId] = ptr; 312 mComponents[poolId] = component; 313 } 314 break; 315 case C2PlatformAllocatorStore::GRALLOC: 316 case C2AllocatorStore::DEFAULT_GRAPHIC: 317 res = allocatorStore->fetchAllocator( 318 C2AllocatorStore::DEFAULT_GRAPHIC, &allocator); 319 if (res == C2_OK) { 320 std::shared_ptr<C2BlockPool> ptr = 321 std::make_shared<C2PooledBlockPool>(allocator, poolId); 322 *pool = ptr; 323 mBlockPools[poolId] = ptr; 324 mComponents[poolId] = component; 325 } 326 break; 327 case C2PlatformAllocatorStore::BUFFERQUEUE: 328 res = allocatorStore->fetchAllocator( 329 C2PlatformAllocatorStore::BUFFERQUEUE, &allocator); 330 if (res == C2_OK) { 331 std::shared_ptr<C2BlockPool> ptr = 332 std::make_shared<C2BufferQueueBlockPool>( 333 allocator, poolId); 334 *pool = ptr; 335 mBlockPools[poolId] = ptr; 336 mComponents[poolId] = component; 337 } 338 break; 339 default: 340 // Try to create block pool from platform store plugins. 341 std::shared_ptr<C2BlockPool> ptr; 342 res = C2PlatformStorePluginLoader::GetInstance()->createBlockPool( 343 allocatorId, poolId, &ptr); 344 if (res == C2_OK) { 345 *pool = ptr; 346 mBlockPools[poolId] = ptr; 347 mComponents[poolId] = component; 348 } 349 break; 350 } 351 return res; 352 } 353 354 c2_status_t createBlockPool( 355 C2PlatformAllocatorStore::id_t allocatorId, 356 std::shared_ptr<const C2Component> component, 357 std::shared_ptr<C2BlockPool> *pool) { 358 return _createBlockPool(allocatorId, component, mBlockPoolSeqId++, pool); 359 } 360 361 bool getBlockPool( 362 C2BlockPool::local_id_t blockPoolId, 363 std::shared_ptr<const C2Component> component, 364 std::shared_ptr<C2BlockPool> *pool) { 365 // TODO: use one iterator for multiple blockpool type scalability. 366 std::shared_ptr<C2BlockPool> ptr; 367 auto it = mBlockPools.find(blockPoolId); 368 if (it != mBlockPools.end()) { 369 ptr = it->second.lock(); 370 if (!ptr) { 371 mBlockPools.erase(it); 372 mComponents.erase(blockPoolId); 373 } else { 374 auto found = mComponents.find(blockPoolId); 375 if (component == found->second.lock()) { 376 *pool = ptr; 377 return true; 378 } 379 } 380 } 381 return false; 382 } 383 384 private: 385 C2BlockPool::local_id_t mBlockPoolSeqId; 386 387 std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools; 388 std::map<C2BlockPool::local_id_t, std::weak_ptr<const C2Component>> mComponents; 389 }; 390 391 static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache = 392 std::make_unique<_C2BlockPoolCache>(); 393 static std::mutex sBlockPoolCacheMutex; 394 395 } // anynymous namespace 396 397 c2_status_t GetCodec2BlockPool( 398 C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component, 399 std::shared_ptr<C2BlockPool> *pool) { 400 pool->reset(); 401 std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex); 402 std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore(); 403 std::shared_ptr<C2Allocator> allocator; 404 c2_status_t res = C2_NOT_FOUND; 405 406 if (id >= C2BlockPool::PLATFORM_START) { 407 if (sBlockPoolCache->getBlockPool(id, component, pool)) { 408 return C2_OK; 409 } 410 } 411 412 switch (id) { 413 case C2BlockPool::BASIC_LINEAR: 414 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator); 415 if (res == C2_OK) { 416 *pool = std::make_shared<C2BasicLinearBlockPool>(allocator); 417 } 418 break; 419 case C2BlockPool::BASIC_GRAPHIC: 420 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator); 421 if (res == C2_OK) { 422 *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator); 423 } 424 break; 425 // TODO: remove this. this is temporary 426 case C2BlockPool::PLATFORM_START: 427 res = sBlockPoolCache->_createBlockPool( 428 C2PlatformAllocatorStore::BUFFERQUEUE, component, id, pool); 429 break; 430 default: 431 break; 432 } 433 return res; 434 } 435 436 c2_status_t CreateCodec2BlockPool( 437 C2PlatformAllocatorStore::id_t allocatorId, 438 std::shared_ptr<const C2Component> component, 439 std::shared_ptr<C2BlockPool> *pool) { 440 pool->reset(); 441 442 std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex); 443 return sBlockPoolCache->createBlockPool(allocatorId, component, pool); 444 } 445 446 class C2PlatformComponentStore : public C2ComponentStore { 447 public: 448 virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override; 449 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override; 450 virtual C2String getName() const override; 451 virtual c2_status_t querySupportedValues_sm( 452 std::vector<C2FieldSupportedValuesQuery> &fields) const override; 453 virtual c2_status_t querySupportedParams_nb( 454 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const override; 455 virtual c2_status_t query_sm( 456 const std::vector<C2Param*> &stackParams, 457 const std::vector<C2Param::Index> &heapParamIndices, 458 std::vector<std::unique_ptr<C2Param>> *const heapParams) const override; 459 virtual c2_status_t createInterface( 460 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) override; 461 virtual c2_status_t createComponent( 462 C2String name, std::shared_ptr<C2Component> *const component) override; 463 virtual c2_status_t copyBuffer( 464 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) override; 465 virtual c2_status_t config_sm( 466 const std::vector<C2Param*> ¶ms, 467 std::vector<std::unique_ptr<C2SettingResult>> *const failures) override; 468 C2PlatformComponentStore(); 469 470 virtual ~C2PlatformComponentStore() override = default; 471 472 private: 473 474 /** 475 * An object encapsulating a loaded component module. 476 * 477 * \todo provide a way to add traits to known components here to avoid loading the .so-s 478 * for listComponents 479 */ 480 struct ComponentModule : public C2ComponentFactory, 481 public std::enable_shared_from_this<ComponentModule> { 482 virtual c2_status_t createComponent( 483 c2_node_id_t id, std::shared_ptr<C2Component> *component, 484 ComponentDeleter deleter = std::default_delete<C2Component>()) override; 485 virtual c2_status_t createInterface( 486 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface, 487 InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) override; 488 489 /** 490 * \returns the traits of the component in this module. 491 */ 492 std::shared_ptr<const C2Component::Traits> getTraits(); 493 494 /** 495 * Creates an uninitialized component module. 496 * 497 * \param name[in] component name. 498 * 499 * \note Only used by ComponentLoader. 500 */ 501 ComponentModule() 502 : mInit(C2_NO_INIT), 503 mLibHandle(nullptr), 504 createFactory(nullptr), 505 destroyFactory(nullptr), 506 mComponentFactory(nullptr) { 507 } 508 509 /** 510 * Initializes a component module with a given library path. Must be called exactly once. 511 * 512 * \note Only used by ComponentLoader. 513 * 514 * \param libPath[in] library path (or name) 515 * 516 * \retval C2_OK the component module has been successfully loaded 517 * \retval C2_NO_MEMORY not enough memory to loading the component module 518 * \retval C2_NOT_FOUND could not locate the component module 519 * \retval C2_CORRUPTED the component module could not be loaded (unexpected) 520 * \retval C2_REFUSED permission denied to load the component module (unexpected) 521 * \retval C2_TIMED_OUT could not load the module within the time limit (unexpected) 522 */ 523 c2_status_t init(std::string libPath); 524 525 virtual ~ComponentModule() override; 526 527 protected: 528 std::recursive_mutex mLock; ///< lock protecting mTraits 529 std::shared_ptr<C2Component::Traits> mTraits; ///< cached component traits 530 531 c2_status_t mInit; ///< initialization result 532 533 void *mLibHandle; ///< loaded library handle 534 C2ComponentFactory::CreateCodec2FactoryFunc createFactory; ///< loaded create function 535 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory; ///< loaded destroy function 536 C2ComponentFactory *mComponentFactory; ///< loaded/created component factory 537 }; 538 539 /** 540 * An object encapsulating a loadable component module. 541 * 542 * \todo make this also work for enumerations 543 */ 544 struct ComponentLoader { 545 /** 546 * Load the component module. 547 * 548 * This method simply returns the component module if it is already currently loaded, or 549 * attempts to load it if it is not. 550 * 551 * \param module[out] pointer to the shared pointer where the loaded module shall be stored. 552 * This will be nullptr on error. 553 * 554 * \retval C2_OK the component module has been successfully loaded 555 * \retval C2_NO_MEMORY not enough memory to loading the component module 556 * \retval C2_NOT_FOUND could not locate the component module 557 * \retval C2_CORRUPTED the component module could not be loaded 558 * \retval C2_REFUSED permission denied to load the component module 559 */ 560 c2_status_t fetchModule(std::shared_ptr<ComponentModule> *module) { 561 c2_status_t res = C2_OK; 562 std::lock_guard<std::mutex> lock(mMutex); 563 std::shared_ptr<ComponentModule> localModule = mModule.lock(); 564 if (localModule == nullptr) { 565 localModule = std::make_shared<ComponentModule>(); 566 res = localModule->init(mLibPath); 567 if (res == C2_OK) { 568 mModule = localModule; 569 } 570 } 571 *module = localModule; 572 return res; 573 } 574 575 /** 576 * Creates a component loader for a specific library path (or name). 577 */ 578 ComponentLoader(std::string libPath) 579 : mLibPath(libPath) {} 580 581 private: 582 std::mutex mMutex; ///< mutex guarding the module 583 std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module 584 std::string mLibPath; ///< library path (or name) 585 }; 586 587 struct Interface : public C2InterfaceHelper { 588 std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo; 589 590 Interface(std::shared_ptr<C2ReflectorHelper> reflector) 591 : C2InterfaceHelper(reflector) { 592 setDerivedInstance(this); 593 594 struct Setter { 595 static C2R setIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) { 596 me.set().heapMask = ~0; 597 me.set().allocFlags = 0; 598 me.set().minAlignment = 0; 599 return C2R::Ok(); 600 } 601 }; 602 603 addParameter( 604 DefineParam(mIonUsageInfo, "ion-usage") 605 .withDefault(new C2StoreIonUsageInfo()) 606 .withFields({ 607 C2F(mIonUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}), 608 C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024), 609 C2F(mIonUsageInfo, heapMask).any(), 610 C2F(mIonUsageInfo, allocFlags).flags({}), 611 C2F(mIonUsageInfo, minAlignment).equalTo(0) 612 }) 613 .withSetter(Setter::setIonUsage) 614 .build()); 615 } 616 }; 617 618 /** 619 * Retrieves the component loader for a component. 620 * 621 * \return a non-ref-holding pointer to the component loader. 622 * 623 * \retval C2_OK the component loader has been successfully retrieved 624 * \retval C2_NO_MEMORY not enough memory to locate the component loader 625 * \retval C2_NOT_FOUND could not locate the component to be loaded 626 * \retval C2_CORRUPTED the component loader could not be identified due to some modules being 627 * corrupted (this can happen if the name does not refer to an already 628 * identified component but some components could not be loaded due to 629 * bad library) 630 * \retval C2_REFUSED permission denied to find the component loader for the named component 631 * (this can happen if the name does not refer to an already identified 632 * component but some components could not be loaded due to lack of 633 * permissions) 634 */ 635 c2_status_t findComponent(C2String name, ComponentLoader **loader); 636 637 std::map<C2String, ComponentLoader> mComponents; ///< list of components 638 std::shared_ptr<C2ReflectorHelper> mReflector; 639 Interface mInterface; 640 }; 641 642 c2_status_t C2PlatformComponentStore::ComponentModule::init(std::string libPath) { 643 ALOGV("in %s", __func__); 644 ALOGV("loading dll"); 645 mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE); 646 if (mLibHandle == nullptr) { 647 // could be access/symbol or simply not being there 648 ALOGD("could not dlopen %s: %s", libPath.c_str(), dlerror()); 649 mInit = C2_CORRUPTED; 650 } else { 651 createFactory = 652 (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory"); 653 destroyFactory = 654 (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory"); 655 656 mComponentFactory = createFactory(); 657 if (mComponentFactory == nullptr) { 658 ALOGD("could not create factory in %s", libPath.c_str()); 659 mInit = C2_NO_MEMORY; 660 } else { 661 mInit = C2_OK; 662 } 663 } 664 return mInit; 665 } 666 667 C2PlatformComponentStore::ComponentModule::~ComponentModule() { 668 ALOGV("in %s", __func__); 669 if (destroyFactory && mComponentFactory) { 670 destroyFactory(mComponentFactory); 671 } 672 if (mLibHandle) { 673 ALOGV("unloading dll"); 674 dlclose(mLibHandle); 675 } 676 } 677 678 c2_status_t C2PlatformComponentStore::ComponentModule::createInterface( 679 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface, 680 std::function<void(::C2ComponentInterface*)> deleter) { 681 interface->reset(); 682 if (mInit != C2_OK) { 683 return mInit; 684 } 685 std::shared_ptr<ComponentModule> module = shared_from_this(); 686 c2_status_t res = mComponentFactory->createInterface( 687 id, interface, [module, deleter](C2ComponentInterface *p) mutable { 688 // capture module so that we ensure we still have it while deleting interface 689 deleter(p); // delete interface first 690 module.reset(); // remove module ref (not technically needed) 691 }); 692 return res; 693 } 694 695 c2_status_t C2PlatformComponentStore::ComponentModule::createComponent( 696 c2_node_id_t id, std::shared_ptr<C2Component> *component, 697 std::function<void(::C2Component*)> deleter) { 698 component->reset(); 699 if (mInit != C2_OK) { 700 return mInit; 701 } 702 std::shared_ptr<ComponentModule> module = shared_from_this(); 703 c2_status_t res = mComponentFactory->createComponent( 704 id, component, [module, deleter](C2Component *p) mutable { 705 // capture module so that we ensure we still have it while deleting component 706 deleter(p); // delete component first 707 module.reset(); // remove module ref (not technically needed) 708 }); 709 return res; 710 } 711 712 std::shared_ptr<const C2Component::Traits> C2PlatformComponentStore::ComponentModule::getTraits() { 713 std::unique_lock<std::recursive_mutex> lock(mLock); 714 if (!mTraits) { 715 std::shared_ptr<C2ComponentInterface> intf; 716 c2_status_t res = createInterface(0, &intf); 717 if (res != C2_OK) { 718 ALOGD("failed to create interface: %d", res); 719 return nullptr; 720 } 721 722 std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits); 723 if (traits) { 724 traits->name = intf->getName(); 725 // TODO: get this from interface properly. 726 bool encoder = (traits->name.find("encoder") != std::string::npos); 727 uint32_t mediaTypeIndex = encoder ? C2PortMimeConfig::output::PARAM_TYPE 728 : C2PortMimeConfig::input::PARAM_TYPE; 729 std::vector<std::unique_ptr<C2Param>> params; 730 res = intf->query_vb({}, { mediaTypeIndex }, C2_MAY_BLOCK, ¶ms); 731 if (res != C2_OK) { 732 ALOGD("failed to query interface: %d", res); 733 return nullptr; 734 } 735 if (params.size() != 1u) { 736 ALOGD("failed to query interface: unexpected vector size: %zu", params.size()); 737 return nullptr; 738 } 739 C2PortMimeConfig *mediaTypeConfig = (C2PortMimeConfig *)(params[0].get()); 740 if (mediaTypeConfig == nullptr) { 741 ALOGD("failed to query media type"); 742 return nullptr; 743 } 744 traits->mediaType = mediaTypeConfig->m.value; 745 // TODO: get this properly. 746 traits->rank = 0x200; 747 748 // TODO: define these values properly 749 bool decoder = (traits->name.find("decoder") != std::string::npos); 750 traits->kind = 751 decoder ? C2Component::KIND_DECODER : 752 encoder ? C2Component::KIND_ENCODER : 753 C2Component::KIND_OTHER; 754 if (strncmp(traits->mediaType.c_str(), "audio/", 6) == 0) { 755 traits->domain = C2Component::DOMAIN_AUDIO; 756 } else if (strncmp(traits->mediaType.c_str(), "video/", 6) == 0) { 757 traits->domain = C2Component::DOMAIN_VIDEO; 758 } else if (strncmp(traits->mediaType.c_str(), "image/", 6) == 0) { 759 traits->domain = C2Component::DOMAIN_IMAGE; 760 } else { 761 traits->domain = C2Component::DOMAIN_OTHER; 762 } 763 } 764 765 mTraits = traits; 766 } 767 return mTraits; 768 } 769 770 C2PlatformComponentStore::C2PlatformComponentStore() 771 : mReflector(std::make_shared<C2ReflectorHelper>()), 772 mInterface(mReflector) { 773 // TODO: move this also into a .so so it can be updated 774 mComponents.emplace("c2.android.avc.decoder", "libstagefright_soft_c2avcdec.so"); 775 mComponents.emplace("c2.android.avc.encoder", "libstagefright_soft_c2avcenc.so"); 776 mComponents.emplace("c2.android.aac.decoder", "libstagefright_soft_c2aacdec.so"); 777 mComponents.emplace("c2.android.aac.encoder", "libstagefright_soft_c2aacenc.so"); 778 mComponents.emplace("c2.android.amrnb.decoder", "libstagefright_soft_c2amrnbdec.so"); 779 mComponents.emplace("c2.android.amrnb.encoder", "libstagefright_soft_c2amrnbenc.so"); 780 mComponents.emplace("c2.android.amrwb.decoder", "libstagefright_soft_c2amrwbdec.so"); 781 mComponents.emplace("c2.android.amrwb.encoder", "libstagefright_soft_c2amrwbenc.so"); 782 mComponents.emplace("c2.android.hevc.decoder", "libstagefright_soft_c2hevcdec.so"); 783 mComponents.emplace("c2.android.g711.alaw.decoder", "libstagefright_soft_c2g711alawdec.so"); 784 mComponents.emplace("c2.android.g711.mlaw.decoder", "libstagefright_soft_c2g711mlawdec.so"); 785 mComponents.emplace("c2.android.mpeg2.decoder", "libstagefright_soft_c2mpeg2dec.so"); 786 mComponents.emplace("c2.android.h263.decoder", "libstagefright_soft_c2h263dec.so"); 787 mComponents.emplace("c2.android.h263.encoder", "libstagefright_soft_c2h263enc.so"); 788 mComponents.emplace("c2.android.mpeg4.decoder", "libstagefright_soft_c2mpeg4dec.so"); 789 mComponents.emplace("c2.android.mpeg4.encoder", "libstagefright_soft_c2mpeg4enc.so"); 790 mComponents.emplace("c2.android.mp3.decoder", "libstagefright_soft_c2mp3dec.so"); 791 mComponents.emplace("c2.android.vorbis.decoder", "libstagefright_soft_c2vorbisdec.so"); 792 mComponents.emplace("c2.android.opus.decoder", "libstagefright_soft_c2opusdec.so"); 793 mComponents.emplace("c2.android.vp8.decoder", "libstagefright_soft_c2vp8dec.so"); 794 mComponents.emplace("c2.android.vp9.decoder", "libstagefright_soft_c2vp9dec.so"); 795 mComponents.emplace("c2.android.vp8.encoder", "libstagefright_soft_c2vp8enc.so"); 796 mComponents.emplace("c2.android.vp9.encoder", "libstagefright_soft_c2vp9enc.so"); 797 mComponents.emplace("c2.android.raw.decoder", "libstagefright_soft_c2rawdec.so"); 798 mComponents.emplace("c2.android.flac.decoder", "libstagefright_soft_c2flacdec.so"); 799 mComponents.emplace("c2.android.flac.encoder", "libstagefright_soft_c2flacenc.so"); 800 mComponents.emplace("c2.android.gsm.decoder", "libstagefright_soft_c2gsmdec.so"); 801 mComponents.emplace("c2.android.xaac.decoder", "libstagefright_soft_c2xaacdec.so"); 802 } 803 804 c2_status_t C2PlatformComponentStore::copyBuffer( 805 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) { 806 (void)src; 807 (void)dst; 808 return C2_OMITTED; 809 } 810 811 c2_status_t C2PlatformComponentStore::query_sm( 812 const std::vector<C2Param*> &stackParams, 813 const std::vector<C2Param::Index> &heapParamIndices, 814 std::vector<std::unique_ptr<C2Param>> *const heapParams) const { 815 return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams); 816 } 817 818 c2_status_t C2PlatformComponentStore::config_sm( 819 const std::vector<C2Param*> ¶ms, 820 std::vector<std::unique_ptr<C2SettingResult>> *const failures) { 821 return mInterface.config(params, C2_MAY_BLOCK, failures); 822 } 823 824 std::vector<std::shared_ptr<const C2Component::Traits>> C2PlatformComponentStore::listComponents() { 825 // This method SHALL return within 500ms. 826 std::vector<std::shared_ptr<const C2Component::Traits>> list; 827 for (auto &it : mComponents) { 828 ComponentLoader &loader = it.second; 829 std::shared_ptr<ComponentModule> module; 830 c2_status_t res = loader.fetchModule(&module); 831 if (res == C2_OK) { 832 std::shared_ptr<const C2Component::Traits> traits = module->getTraits(); 833 if (traits) { 834 list.push_back(traits); 835 } 836 } 837 } 838 return list; 839 } 840 841 c2_status_t C2PlatformComponentStore::findComponent(C2String name, ComponentLoader **loader) { 842 *loader = nullptr; 843 auto pos = mComponents.find(name); 844 // TODO: check aliases 845 if (pos == mComponents.end()) { 846 return C2_NOT_FOUND; 847 } 848 *loader = &pos->second; 849 return C2_OK; 850 } 851 852 c2_status_t C2PlatformComponentStore::createComponent( 853 C2String name, std::shared_ptr<C2Component> *const component) { 854 // This method SHALL return within 100ms. 855 component->reset(); 856 ComponentLoader *loader; 857 c2_status_t res = findComponent(name, &loader); 858 if (res == C2_OK) { 859 std::shared_ptr<ComponentModule> module; 860 res = loader->fetchModule(&module); 861 if (res == C2_OK) { 862 // TODO: get a unique node ID 863 res = module->createComponent(0, component); 864 } 865 } 866 return res; 867 } 868 869 c2_status_t C2PlatformComponentStore::createInterface( 870 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) { 871 // This method SHALL return within 100ms. 872 interface->reset(); 873 ComponentLoader *loader; 874 c2_status_t res = findComponent(name, &loader); 875 if (res == C2_OK) { 876 std::shared_ptr<ComponentModule> module; 877 res = loader->fetchModule(&module); 878 if (res == C2_OK) { 879 // TODO: get a unique node ID 880 res = module->createInterface(0, interface); 881 } 882 } 883 return res; 884 } 885 886 c2_status_t C2PlatformComponentStore::querySupportedParams_nb( 887 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const { 888 return mInterface.querySupportedParams(params); 889 } 890 891 c2_status_t C2PlatformComponentStore::querySupportedValues_sm( 892 std::vector<C2FieldSupportedValuesQuery> &fields) const { 893 return mInterface.querySupportedValues(fields, C2_MAY_BLOCK); 894 } 895 896 C2String C2PlatformComponentStore::getName() const { 897 return "android.componentStore.platform"; 898 } 899 900 std::shared_ptr<C2ParamReflector> C2PlatformComponentStore::getParamReflector() const { 901 return mReflector; 902 } 903 904 std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore() { 905 static std::mutex mutex; 906 static std::weak_ptr<C2ComponentStore> platformStore; 907 std::lock_guard<std::mutex> lock(mutex); 908 std::shared_ptr<C2ComponentStore> store = platformStore.lock(); 909 if (store == nullptr) { 910 store = std::make_shared<C2PlatformComponentStore>(); 911 platformStore = store; 912 } 913 return store; 914 } 915 916 } // namespace android 917