Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright (C) 2018 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_NDEBUG 0
     18 #define LOG_TAG "Codec2-ComponentStore"
     19 #include <log/log.h>
     20 
     21 #include <codec2/hidl/1.0/ComponentStore.h>
     22 #include <codec2/hidl/1.0/InputSurface.h>
     23 #include <codec2/hidl/1.0/Component.h>
     24 #include <codec2/hidl/1.0/ConfigurableC2Intf.h>
     25 #include <codec2/hidl/1.0/types.h>
     26 
     27 #include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
     28 #include <media/stagefright/bqhelper/GraphicBufferSource.h>
     29 
     30 #include <C2PlatformSupport.h>
     31 
     32 #include <utils/Errors.h>
     33 
     34 #include <android-base/file.h>
     35 
     36 #ifdef LOG
     37 #undef LOG
     38 #endif
     39 
     40 #ifdef PLOG
     41 #undef PLOG
     42 #endif
     43 
     44 #include <android-base/logging.h>
     45 
     46 #include <ostream>
     47 #include <sstream>
     48 #include <iomanip>
     49 
     50 namespace hardware {
     51 namespace google {
     52 namespace media {
     53 namespace c2 {
     54 namespace V1_0 {
     55 namespace utils {
     56 
     57 using namespace ::android;
     58 using ::android::GraphicBufferSource;
     59 using namespace ::android::hardware::media::bufferpool::V1_0::implementation;
     60 
     61 namespace /* unnamed */ {
     62 
     63 struct StoreIntf : public ConfigurableC2Intf {
     64     StoreIntf(const std::shared_ptr<C2ComponentStore>& store) :
     65         ConfigurableC2Intf(store ? store->getName() : ""),
     66         mStore(store) {
     67     }
     68 
     69     c2_status_t config(
     70             const std::vector<C2Param*> &params,
     71             c2_blocking_t mayBlock,
     72             std::vector<std::unique_ptr<C2SettingResult>> *const failures
     73             ) override {
     74         // Assume all params are blocking
     75         // TODO: Filter for supported params
     76         if (mayBlock == C2_DONT_BLOCK && params.size() != 0) {
     77             return C2_BLOCKING;
     78         }
     79         return mStore->config_sm(params, failures);
     80     }
     81 
     82     c2_status_t query(
     83             const std::vector<C2Param::Index> &indices,
     84             c2_blocking_t mayBlock,
     85             std::vector<std::unique_ptr<C2Param>> *const params) const override {
     86         // Assume all params are blocking
     87         // TODO: Filter for supported params
     88         if (mayBlock == C2_DONT_BLOCK && indices.size() != 0) {
     89             return C2_BLOCKING;
     90         }
     91         return mStore->query_sm({}, indices, params);
     92     }
     93 
     94     c2_status_t querySupportedParams(
     95             std::vector<std::shared_ptr<C2ParamDescriptor>> *const params
     96             ) const override {
     97         return mStore->querySupportedParams_nb(params);
     98     }
     99 
    100     c2_status_t querySupportedValues(
    101             std::vector<C2FieldSupportedValuesQuery> &fields,
    102             c2_blocking_t mayBlock) const override {
    103         // Assume all params are blocking
    104         // TODO: Filter for supported params
    105         if (mayBlock == C2_DONT_BLOCK && fields.size() != 0) {
    106             return C2_BLOCKING;
    107         }
    108         return mStore->querySupportedValues_sm(fields);
    109     }
    110 
    111 protected:
    112     std::shared_ptr<C2ComponentStore> mStore;
    113 };
    114 
    115 } // unnamed namespace
    116 
    117 ComponentStore::ComponentStore(const std::shared_ptr<C2ComponentStore>& store) :
    118     Configurable(new CachedConfigurable(std::make_unique<StoreIntf>(store))),
    119     mStore(store) {
    120 
    121     std::shared_ptr<C2ComponentStore> platformStore = android::GetCodec2PlatformComponentStore();
    122     SetPreferredCodec2ComponentStore(store);
    123 
    124     // Retrieve struct descriptors
    125     mParamReflector = mStore->getParamReflector();
    126 
    127     // Retrieve supported parameters from store
    128     mInit = init(this);
    129 }
    130 
    131 c2_status_t ComponentStore::validateSupportedParams(
    132         const std::vector<std::shared_ptr<C2ParamDescriptor>>& params) {
    133     c2_status_t res = C2_OK;
    134 
    135     for (const std::shared_ptr<C2ParamDescriptor> &desc : params) {
    136         if (!desc) {
    137             // All descriptors should be valid
    138             res = res ? res : C2_BAD_VALUE;
    139             continue;
    140         }
    141         C2Param::CoreIndex coreIndex = desc->index().coreIndex();
    142         std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
    143         auto it = mStructDescriptors.find(coreIndex);
    144         if (it == mStructDescriptors.end()) {
    145             std::shared_ptr<C2StructDescriptor> structDesc =
    146                     mParamReflector->describe(coreIndex);
    147             if (!structDesc) {
    148                 // All supported params must be described
    149                 res = C2_BAD_INDEX;
    150             }
    151             mStructDescriptors.insert({ coreIndex, structDesc });
    152         }
    153     }
    154     return res;
    155 }
    156 
    157 // Methods from ::android::hardware::media::c2::V1_0::IComponentStore
    158 Return<void> ComponentStore::createComponent(
    159         const hidl_string& name,
    160         const sp<IComponentListener>& listener,
    161         const sp<IClientManager>& pool,
    162         createComponent_cb _hidl_cb) {
    163 
    164     sp<Component> component;
    165     std::shared_ptr<C2Component> c2component;
    166     Status status = static_cast<Status>(
    167             mStore->createComponent(name, &c2component));
    168 
    169     if (status == Status::OK) {
    170         onInterfaceLoaded(c2component->intf());
    171         component = new Component(c2component, listener, this, pool);
    172         if (!component) {
    173             status = Status::CORRUPTED;
    174         } else if (component->status() != C2_OK) {
    175             status = static_cast<Status>(component->status());
    176         } else {
    177             component->initListener(component);
    178             if (component->status() != C2_OK) {
    179                 status = static_cast<Status>(component->status());
    180             } else {
    181                 std::lock_guard<std::mutex> lock(mComponentRosterMutex);
    182                 component->setLocalId(
    183                         mComponentRoster.emplace(
    184                             Component::InterfaceKey(component),
    185                             c2component)
    186                         .first);
    187             }
    188         }
    189     }
    190     _hidl_cb(status, component);
    191     return Void();
    192 }
    193 
    194 Return<void> ComponentStore::createInterface(
    195         const hidl_string& name,
    196         createInterface_cb _hidl_cb) {
    197     std::shared_ptr<C2ComponentInterface> c2interface;
    198     c2_status_t res = mStore->createInterface(name, &c2interface);
    199     sp<IComponentInterface> interface;
    200     if (res == C2_OK) {
    201         onInterfaceLoaded(c2interface);
    202         interface = new ComponentInterface(c2interface, this);
    203     }
    204     _hidl_cb((Status)res, interface);
    205     return Void();
    206 }
    207 
    208 Return<void> ComponentStore::listComponents(listComponents_cb _hidl_cb) {
    209     std::vector<std::shared_ptr<const C2Component::Traits>> c2traits =
    210             mStore->listComponents();
    211     hidl_vec<IComponentStore::ComponentTraits> traits(c2traits.size());
    212     size_t ix = 0;
    213     for (const std::shared_ptr<const C2Component::Traits> &c2trait : c2traits) {
    214         if (c2trait) {
    215             objcpy(&traits[ix++], *c2trait);
    216         }
    217     }
    218     traits.resize(ix);
    219     _hidl_cb(traits);
    220     return Void();
    221 }
    222 
    223 Return<sp<IInputSurface>> ComponentStore::createInputSurface() {
    224     sp<GraphicBufferSource> source = new GraphicBufferSource();
    225     if (source->initCheck() != OK) {
    226         return nullptr;
    227     }
    228     typedef ::android::hardware::graphics::bufferqueue::V1_0::
    229             IGraphicBufferProducer HGBP;
    230     typedef ::android::TWGraphicBufferProducer<HGBP> B2HGBP;
    231     return new InputSurface(
    232             this,
    233             new B2HGBP(source->getIGraphicBufferProducer()),
    234             source);
    235 }
    236 
    237 void ComponentStore::onInterfaceLoaded(const std::shared_ptr<C2ComponentInterface> &intf) {
    238     // invalidate unsupported struct descriptors if a new interface is loaded as it may have
    239     // exposed new descriptors
    240     std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
    241     if (!mLoadedInterfaces.count(intf->getName())) {
    242         mUnsupportedStructDescriptors.clear();
    243         mLoadedInterfaces.emplace(intf->getName());
    244     }
    245 }
    246 
    247 Return<void> ComponentStore::getStructDescriptors(
    248         const hidl_vec<uint32_t>& indices,
    249         getStructDescriptors_cb _hidl_cb) {
    250     hidl_vec<StructDescriptor> descriptors(indices.size());
    251     size_t dstIx = 0;
    252     Status res = Status::OK;
    253     for (size_t srcIx = 0; srcIx < indices.size(); ++srcIx) {
    254         std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
    255         const C2Param::CoreIndex coreIndex = C2Param::CoreIndex(indices[srcIx]).coreIndex();
    256         const auto item = mStructDescriptors.find(coreIndex);
    257         if (item == mStructDescriptors.end()) {
    258             // not in the cache, and not known to be unsupported, query local reflector
    259             if (!mUnsupportedStructDescriptors.count(coreIndex)) {
    260                 std::shared_ptr<C2StructDescriptor> structDesc =
    261                     mParamReflector->describe(coreIndex);
    262                 if (!structDesc) {
    263                     mUnsupportedStructDescriptors.emplace(coreIndex);
    264                 } else {
    265                     mStructDescriptors.insert({ coreIndex, structDesc });
    266                     objcpy(&descriptors[dstIx++], *structDesc);
    267                     continue;
    268                 }
    269             }
    270             res = Status::NOT_FOUND;
    271         } else if (item->second) {
    272             objcpy(&descriptors[dstIx++], *item->second);
    273         } else {
    274             res = Status::NO_MEMORY;
    275         }
    276     }
    277     descriptors.resize(dstIx);
    278     _hidl_cb(res, descriptors);
    279     return Void();
    280 }
    281 
    282 Return<sp<IClientManager>> ComponentStore::getPoolClientManager() {
    283     return ClientManager::getInstance();
    284 }
    285 
    286 Return<Status> ComponentStore::copyBuffer(const Buffer& src, const Buffer& dst) {
    287     // TODO implement
    288     (void)src;
    289     (void)dst;
    290     return Status::OMITTED;
    291 }
    292 
    293 void ComponentStore::reportComponentDeath(
    294         const Component::LocalId& componentLocalId) {
    295     std::lock_guard<std::mutex> lock(mComponentRosterMutex);
    296     mComponentRoster.erase(componentLocalId);
    297 }
    298 
    299 std::shared_ptr<C2Component> ComponentStore::findC2Component(
    300         const sp<IComponent>& component) const {
    301     std::lock_guard<std::mutex> lock(mComponentRosterMutex);
    302     Component::LocalId it = mComponentRoster.find(
    303             Component::InterfaceKey(component));
    304     if (it == mComponentRoster.end()) {
    305         return std::shared_ptr<C2Component>();
    306     }
    307     return it->second.lock();
    308 }
    309 
    310 // Debug dump
    311 
    312 namespace /* unnamed */ {
    313 
    314 // Dump component traits
    315 std::ostream& dump(
    316         std::ostream& out,
    317         const std::shared_ptr<const C2Component::Traits>& comp) {
    318 
    319     constexpr const char indent[] = "    ";
    320 
    321     out << indent << "name: " << comp->name << std::endl;
    322     out << indent << "domain: " << comp->domain << std::endl;
    323     out << indent << "kind: " << comp->kind << std::endl;
    324     out << indent << "rank: " << comp->rank << std::endl;
    325     out << indent << "mediaType: " << comp->mediaType << std::endl;
    326     out << indent << "aliases:";
    327     for (const auto& alias : comp->aliases) {
    328         out << ' ' << alias;
    329     }
    330     out << std::endl;
    331 
    332     return out;
    333 }
    334 
    335 // Dump component
    336 std::ostream& dump(
    337         std::ostream& out,
    338         const std::shared_ptr<C2Component>& comp) {
    339 
    340     constexpr const char indent[] = "    ";
    341 
    342     std::shared_ptr<C2ComponentInterface> intf = comp->intf();
    343     if (!intf) {
    344         out << indent << "Unknown -- null interface" << std::endl;
    345         return out;
    346     }
    347     out << indent << "name: " << intf->getName() << std::endl;
    348     out << indent << "id: " << intf->getId() << std::endl;
    349     return out;
    350 }
    351 
    352 } // unnamed namespace
    353 
    354 Return<void> ComponentStore::debug(
    355         const hidl_handle& handle,
    356         const hidl_vec<hidl_string>& /* args */) {
    357    LOG(INFO) << "debug -- dumping...";
    358    const native_handle_t *h = handle.getNativeHandle();
    359    if (!h || h->numFds != 1) {
    360       LOG(ERROR) << "debug -- dumping failed -- "
    361               "invalid file descriptor to dump to";
    362       return Void();
    363    }
    364    std::ostringstream out;
    365 
    366    { // Populate "out".
    367 
    368         constexpr const char indent[] = "  ";
    369 
    370         // Show name.
    371         out << "Beginning of dump -- C2ComponentStore: "
    372                 << mStore->getName() << std::endl << std::endl;
    373 
    374         // Retrieve the list of supported components.
    375         std::vector<std::shared_ptr<const C2Component::Traits>> traitsList =
    376                 mStore->listComponents();
    377 
    378         // Dump the traits of supported components.
    379         out << indent << "Supported components:" << std::endl << std::endl;
    380         if (traitsList.size() == 0) {
    381             out << indent << indent << "NONE" << std::endl << std::endl;
    382         } else {
    383             for (const auto& traits : traitsList) {
    384                 dump(out, traits) << std::endl;
    385             }
    386         }
    387 
    388         // Retrieve the list of active components.
    389         std::list<std::shared_ptr<C2Component>> activeComps;
    390         {
    391             std::lock_guard<std::mutex> lock(mComponentRosterMutex);
    392             auto i = mComponentRoster.begin();
    393             while (i != mComponentRoster.end()) {
    394                 std::shared_ptr<C2Component> c2comp = i->second.lock();
    395                 if (!c2comp) {
    396                     auto j = i;
    397                     ++i;
    398                     mComponentRoster.erase(j);
    399                 } else {
    400                     ++i;
    401                     activeComps.emplace_back(c2comp);
    402                 }
    403             }
    404         }
    405 
    406         // Dump active components.
    407         out << indent << "Active components:" << std::endl << std::endl;
    408         if (activeComps.size() == 0) {
    409             out << indent << indent << "NONE" << std::endl << std::endl;
    410         } else {
    411             for (const std::shared_ptr<C2Component>& c2comp : activeComps) {
    412                 dump(out, c2comp) << std::endl;
    413             }
    414         }
    415 
    416         out << "End of dump -- C2ComponentStore: "
    417                 << mStore->getName() << std::endl;
    418    }
    419 
    420    if (!android::base::WriteStringToFd(out.str(), h->data[0])) {
    421        PLOG(WARNING) << "debug -- dumping failed -- write()";
    422    } else {
    423        LOG(INFO) << "debug -- dumping succeeded";
    424    }
    425    return Void();
    426 }
    427 
    428 
    429 }  // namespace utils
    430 }  // namespace V1_0
    431 }  // namespace c2
    432 }  // namespace media
    433 }  // namespace google
    434 }  // namespace hardware
    435