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-Component"
     19 #include <log/log.h>
     20 
     21 #include <C2PlatformSupport.h>
     22 #include <codec2/hidl/1.0/Component.h>
     23 #include <codec2/hidl/1.0/ComponentStore.h>
     24 #include <codec2/hidl/1.0/types.h>
     25 
     26 #include <hidl/HidlBinderSupport.h>
     27 
     28 #include <C2BqBufferPriv.h>
     29 #include <C2PlatformSupport.h>
     30 
     31 namespace hardware {
     32 namespace google {
     33 namespace media {
     34 namespace c2 {
     35 namespace V1_0 {
     36 namespace utils {
     37 
     38 using namespace ::android;
     39 
     40 namespace /* unnamed */ {
     41 
     42 // Implementation of ConfigurableC2Intf based on C2ComponentInterface
     43 struct CompIntf : public ConfigurableC2Intf {
     44     CompIntf(const std::shared_ptr<C2ComponentInterface>& intf) :
     45         ConfigurableC2Intf(intf->getName()),
     46         mIntf(intf) {
     47     }
     48 
     49     virtual c2_status_t config(
     50             const std::vector<C2Param*>& params,
     51             c2_blocking_t mayBlock,
     52             std::vector<std::unique_ptr<C2SettingResult>>* const failures
     53             ) override {
     54         ALOGV("config");
     55         return mIntf->config_vb(params, mayBlock, failures);
     56     }
     57 
     58     virtual c2_status_t query(
     59             const std::vector<C2Param::Index>& indices,
     60             c2_blocking_t mayBlock,
     61             std::vector<std::unique_ptr<C2Param>>* const params
     62             ) const override {
     63         ALOGV("query");
     64         return mIntf->query_vb({}, indices, mayBlock, params);
     65     }
     66 
     67     virtual c2_status_t querySupportedParams(
     68             std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
     69             ) const override {
     70         ALOGV("querySupportedParams");
     71         return mIntf->querySupportedParams_nb(params);
     72     }
     73 
     74     virtual c2_status_t querySupportedValues(
     75             std::vector<C2FieldSupportedValuesQuery>& fields,
     76             c2_blocking_t mayBlock) const override {
     77         ALOGV("querySupportedValues");
     78         return mIntf->querySupportedValues_vb(fields, mayBlock);
     79     }
     80 
     81 protected:
     82     std::shared_ptr<C2ComponentInterface> mIntf;
     83 };
     84 
     85 } // unnamed namespace
     86 
     87 // ComponentInterface
     88 ComponentInterface::ComponentInterface(
     89         const std::shared_ptr<C2ComponentInterface>& intf,
     90         const sp<ComponentStore>& store) :
     91     Configurable(new CachedConfigurable(std::make_unique<CompIntf>(intf))),
     92     mInterface(intf) {
     93     mInit = init(store.get());
     94 }
     95 
     96 c2_status_t ComponentInterface::status() const {
     97     return mInit;
     98 }
     99 
    100 // ComponentListener wrapper
    101 struct Component::Listener : public C2Component::Listener {
    102 
    103     Listener(const sp<Component>& component) :
    104         mComponent(component),
    105         mListener(component->mListener) {
    106     }
    107 
    108     virtual void onError_nb(
    109             std::weak_ptr<C2Component> /* c2component */,
    110             uint32_t errorCode) override {
    111         ALOGV("onError");
    112         sp<IComponentListener> listener = mListener.promote();
    113         if (listener) {
    114             Return<void> transStatus = listener->onError(Status::OK, errorCode);
    115             if (!transStatus.isOk()) {
    116                 ALOGE("onError -- transaction failed.");
    117             }
    118         }
    119     }
    120 
    121     virtual void onTripped_nb(
    122             std::weak_ptr<C2Component> /* c2component */,
    123             std::vector<std::shared_ptr<C2SettingResult>> c2settingResult
    124             ) override {
    125         ALOGV("onTripped");
    126         sp<IComponentListener> listener = mListener.promote();
    127         if (listener) {
    128             hidl_vec<SettingResult> settingResults(c2settingResult.size());
    129             size_t ix = 0;
    130             for (const std::shared_ptr<C2SettingResult> &c2result :
    131                     c2settingResult) {
    132                 if (c2result) {
    133                     if (objcpy(&settingResults[ix++], *c2result) !=
    134                             Status::OK) {
    135                         break;
    136                     }
    137                 }
    138             }
    139             settingResults.resize(ix);
    140             Return<void> transStatus = listener->onTripped(settingResults);
    141             if (!transStatus.isOk()) {
    142                 ALOGE("onTripped -- transaction failed.");
    143             }
    144         }
    145     }
    146 
    147     virtual void onWorkDone_nb(
    148             std::weak_ptr<C2Component> /* c2component */,
    149             std::list<std::unique_ptr<C2Work>> c2workItems) override {
    150         ALOGV("onWorkDone");
    151         sp<IComponentListener> listener = mListener.promote();
    152         if (listener) {
    153             WorkBundle workBundle;
    154 
    155             sp<Component> strongComponent = mComponent.promote();
    156             if (objcpy(&workBundle, c2workItems, strongComponent ?
    157                     &strongComponent->mBufferPoolSender : nullptr)
    158                     != Status::OK) {
    159                 ALOGE("onWorkDone() received corrupted work items.");
    160                 return;
    161             }
    162             Return<void> transStatus = listener->onWorkDone(workBundle);
    163             if (!transStatus.isOk()) {
    164                 ALOGE("onWorkDone -- transaction failed.");
    165                 return;
    166             }
    167             yieldBufferQueueBlocks(c2workItems, true);
    168         }
    169     }
    170 
    171 protected:
    172     wp<Component> mComponent;
    173     wp<IComponentListener> mListener;
    174 };
    175 
    176 // Component
    177 Component::Component(
    178         const std::shared_ptr<C2Component>& component,
    179         const sp<IComponentListener>& listener,
    180         const sp<ComponentStore>& store,
    181         const sp<::android::hardware::media::bufferpool::V1_0::
    182         IClientManager>& clientPoolManager) :
    183     Configurable(new CachedConfigurable(
    184             std::make_unique<CompIntf>(component->intf()))),
    185     mComponent(component),
    186     mInterface(component->intf()),
    187     mListener(listener),
    188     mStore(store),
    189     mBufferPoolSender(clientPoolManager) {
    190     // Retrieve supported parameters from store
    191     // TODO: We could cache this per component/interface type
    192     mInit = init(store.get());
    193 }
    194 
    195 c2_status_t Component::status() const {
    196     return mInit;
    197 }
    198 
    199 // Methods from ::android::hardware::media::c2::V1_0::IComponent
    200 Return<Status> Component::queue(const WorkBundle& workBundle) {
    201     ALOGV("queue -- converting input");
    202     std::list<std::unique_ptr<C2Work>> c2works;
    203 
    204     // TODO: Connect with bufferpool API for buffer transfers
    205     if (objcpy(&c2works, workBundle) != C2_OK) {
    206         ALOGV("queue -- corrupted");
    207         return Status::CORRUPTED;
    208     }
    209     ALOGV("queue -- calling");
    210     return static_cast<Status>(mComponent->queue_nb(&c2works));
    211 }
    212 
    213 Return<void> Component::flush(flush_cb _hidl_cb) {
    214     std::list<std::unique_ptr<C2Work>> c2flushedWorks;
    215     ALOGV("flush -- calling");
    216     c2_status_t c2res = mComponent->flush_sm(
    217             C2Component::FLUSH_COMPONENT,
    218             &c2flushedWorks);
    219     WorkBundle flushedWorkBundle;
    220 
    221     Status res = static_cast<Status>(c2res);
    222     if (c2res == C2_OK) {
    223         ALOGV("flush -- converting output");
    224         res = objcpy(&flushedWorkBundle, c2flushedWorks, &mBufferPoolSender);
    225     }
    226     _hidl_cb(res, flushedWorkBundle);
    227     yieldBufferQueueBlocks(c2flushedWorks, true);
    228     return Void();
    229 }
    230 
    231 Return<Status> Component::drain(bool withEos) {
    232     ALOGV("drain");
    233     return static_cast<Status>(mComponent->drain_nb(withEos ?
    234             C2Component::DRAIN_COMPONENT_WITH_EOS :
    235             C2Component::DRAIN_COMPONENT_NO_EOS));
    236 }
    237 
    238 Return<Status> Component::setOutputSurface(
    239         uint64_t blockPoolId,
    240         const sp<HGraphicBufferProducer>& surface) {
    241     std::shared_ptr<C2BlockPool> pool;
    242     GetCodec2BlockPool(blockPoolId, mComponent, &pool);
    243     if (pool && pool->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
    244         std::shared_ptr<C2BufferQueueBlockPool> bqPool =
    245                 std::static_pointer_cast<C2BufferQueueBlockPool>(pool);
    246         C2BufferQueueBlockPool::OnRenderCallback cb =
    247             [this](uint64_t producer, int32_t slot, int64_t nsecs) {
    248                 // TODO: batch this
    249                 hidl_vec<IComponentListener::RenderedFrame> rendered;
    250                 rendered.resize(1);
    251                 rendered[0] = { producer, slot, nsecs };
    252                 mListener->onFramesRendered(rendered);
    253         };
    254         if (bqPool) {
    255             bqPool->setRenderCallback(cb);
    256             bqPool->configureProducer(surface);
    257         }
    258     }
    259     return Status::OK;
    260 }
    261 
    262 Return<Status> Component::connectToOmxInputSurface(
    263         const sp<HGraphicBufferProducer>& producer,
    264         const sp<::android::hardware::media::omx::V1_0::
    265         IGraphicBufferSource>& source) {
    266     // TODO implement
    267     (void)producer;
    268     (void)source;
    269     return Status::OMITTED;
    270 }
    271 
    272 Return<Status> Component::disconnectFromInputSurface() {
    273     // TODO implement
    274     return Status::OK;
    275 }
    276 
    277 namespace /* unnamed */ {
    278 
    279 struct BlockPoolIntf : public ConfigurableC2Intf {
    280     BlockPoolIntf(const std::shared_ptr<C2BlockPool>& pool) :
    281         ConfigurableC2Intf("C2BlockPool:" + std::to_string(pool->getLocalId())),
    282         mPool(pool) {
    283     }
    284 
    285     virtual c2_status_t config(
    286             const std::vector<C2Param*>& params,
    287             c2_blocking_t mayBlock,
    288             std::vector<std::unique_ptr<C2SettingResult>>* const failures
    289             ) override {
    290         (void)params;
    291         (void)mayBlock;
    292         (void)failures;
    293         return C2_OK;
    294     }
    295 
    296     virtual c2_status_t query(
    297             const std::vector<C2Param::Index>& indices,
    298             c2_blocking_t mayBlock,
    299             std::vector<std::unique_ptr<C2Param>>* const params
    300             ) const override {
    301         (void)indices;
    302         (void)mayBlock;
    303         (void)params;
    304         return C2_OK;
    305     }
    306 
    307     virtual c2_status_t querySupportedParams(
    308             std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
    309             ) const override {
    310         (void)params;
    311         return C2_OK;
    312     }
    313 
    314     virtual c2_status_t querySupportedValues(
    315             std::vector<C2FieldSupportedValuesQuery>& fields,
    316             c2_blocking_t mayBlock) const override {
    317         (void)fields;
    318         (void)mayBlock;
    319         return C2_OK;
    320     }
    321 
    322 protected:
    323     std::shared_ptr<C2BlockPool> mPool;
    324 };
    325 
    326 } // unnamed namespace
    327 
    328 Return<void> Component::createBlockPool(
    329         uint32_t allocatorId,
    330         createBlockPool_cb _hidl_cb) {
    331     std::shared_ptr<C2BlockPool> blockPool;
    332     c2_status_t status = CreateCodec2BlockPool(
    333             static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
    334             mComponent,
    335             &blockPool);
    336     if (status != C2_OK) {
    337         blockPool = nullptr;
    338     }
    339     if (blockPool) {
    340         mBlockPoolsMutex.lock();
    341         mBlockPools.emplace(blockPool->getLocalId(), blockPool);
    342         mBlockPoolsMutex.unlock();
    343     } else if (status == C2_OK) {
    344         status = C2_CORRUPTED;
    345     }
    346 
    347     _hidl_cb(static_cast<Status>(status),
    348             blockPool ? blockPool->getLocalId() : 0,
    349             new CachedConfigurable(
    350             std::make_unique<BlockPoolIntf>(blockPool)));
    351     return Void();
    352 }
    353 
    354 Return<Status> Component::destroyBlockPool(uint64_t blockPoolId) {
    355     std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
    356     return mBlockPools.erase(blockPoolId) == 1 ?
    357             Status::OK : Status::CORRUPTED;
    358 }
    359 
    360 Return<Status> Component::start() {
    361     ALOGV("start");
    362     return static_cast<Status>(mComponent->start());
    363 }
    364 
    365 Return<Status> Component::stop() {
    366     ALOGV("stop");
    367     return static_cast<Status>(mComponent->stop());
    368 }
    369 
    370 Return<Status> Component::reset() {
    371     ALOGV("reset");
    372     Status status = static_cast<Status>(mComponent->reset());
    373     {
    374         std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
    375         mBlockPools.clear();
    376     }
    377     return status;
    378 }
    379 
    380 Return<Status> Component::release() {
    381     ALOGV("release");
    382     Status status = static_cast<Status>(mComponent->release());
    383     {
    384         std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
    385         mBlockPools.clear();
    386     }
    387     return status;
    388 }
    389 
    390 void Component::setLocalId(const Component::LocalId& localId) {
    391     mLocalId = localId;
    392 }
    393 
    394 void Component::initListener(const sp<Component>& self) {
    395     std::shared_ptr<C2Component::Listener> c2listener =
    396             std::make_shared<Listener>(self);
    397     c2_status_t res = mComponent->setListener_vb(c2listener, C2_DONT_BLOCK);
    398     if (res != C2_OK) {
    399         mInit = res;
    400     }
    401 }
    402 
    403 Component::~Component() {
    404     mStore->reportComponentDeath(mLocalId);
    405 }
    406 
    407 Component::InterfaceKey::InterfaceKey(const sp<IComponent>& component) {
    408     isRemote = component->isRemote();
    409     if (isRemote) {
    410         remote = ::android::hardware::toBinder(component);
    411     } else {
    412         local = component;
    413     }
    414 }
    415 
    416 }  // namespace utils
    417 }  // namespace V1_0
    418 }  // namespace c2
    419 }  // namespace media
    420 }  // namespace google
    421 }  // namespace hardware
    422