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