client.cpp revision ec232287b40b0fca541d57420f5d84472cdde5b0
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 "Codec2Client" 19#include <log/log.h> 20 21#include <codec2/hidl/client.h> 22 23#include <codec2/hidl/1.0/types.h> 24 25#include <hardware/google/media/c2/1.0/IComponentListener.h> 26#include <hardware/google/media/c2/1.0/IConfigurable.h> 27#include <hardware/google/media/c2/1.0/IComponentInterface.h> 28#include <hardware/google/media/c2/1.0/IComponent.h> 29#include <hardware/google/media/c2/1.0/IComponentStore.h> 30 31#include <C2PlatformSupport.h> 32#include <C2BufferPriv.h> 33#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h> 34#include <hidl/HidlSupport.h> 35#include <cutils/properties.h> 36 37#include <limits> 38#include <type_traits> 39#include <vector> 40#include <map> 41 42namespace android { 43 44using ::android::hardware::hidl_vec; 45using ::android::hardware::hidl_string; 46using ::android::hardware::Return; 47using ::android::hardware::Void; 48 49using namespace ::hardware::google::media::c2::V1_0; 50using namespace ::hardware::google::media::c2::V1_0::utils; 51 52namespace /* unnamed */ { 53 54// c2_status_t value that corresponds to hwbinder transaction failure. 55constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED; 56 57// List of known IComponentStore services. 58constexpr const char* kClientNames[] = { 59 "default", 60 "software", 61 }; 62 63std::vector<std::shared_ptr<Codec2Client>> gClients; 64 65void prepareClients() { 66 static std::mutex clientsMutex; 67 static bool clientsInitialized = false; 68 69 std::lock_guard<std::mutex> lock(clientsMutex); 70 if (clientsInitialized) { 71 return; 72 } 73 gClients.reserve(std::extent<decltype(kClientNames)>::value); 74 for (const char* clientName : kClientNames) { 75 gClients.emplace_back(Codec2Client::CreateFromService(clientName)); 76 } 77 clientsInitialized = true; 78} 79 80} // unnamed namespace 81 82// Codec2ConfigurableClient 83 84const C2String& Codec2ConfigurableClient::getName() const { 85 return mName; 86} 87 88Codec2ConfigurableClient::Base* Codec2ConfigurableClient::base() const { 89 return static_cast<Base*>(mBase.get()); 90} 91 92Codec2ConfigurableClient::Codec2ConfigurableClient( 93 const sp<Codec2ConfigurableClient::Base>& base) : mBase(base) { 94 Return<void> transStatus = base->getName( 95 [this](const hidl_string& name) { 96 mName = name.c_str(); 97 }); 98 if (!transStatus.isOk()) { 99 ALOGE("Cannot obtain name from IConfigurable."); 100 } 101} 102 103c2_status_t Codec2ConfigurableClient::query( 104 const std::vector<C2Param*> &stackParams, 105 const std::vector<C2Param::Index> &heapParamIndices, 106 c2_blocking_t mayBlock, 107 std::vector<std::unique_ptr<C2Param>>* const heapParams) const { 108 hidl_vec<ParamIndex> indices( 109 stackParams.size() + heapParamIndices.size()); 110 size_t numIndices = 0; 111 for (C2Param* const& stackParam : stackParams) { 112 if (!stackParam) { 113 ALOGW("query -- null stack param encountered."); 114 continue; 115 } 116 indices[numIndices++] = static_cast<ParamIndex>(stackParam->index()); 117 } 118 size_t numStackIndices = numIndices; 119 for (const C2Param::Index& index : heapParamIndices) { 120 indices[numIndices++] = 121 static_cast<ParamIndex>(static_cast<uint32_t>(index)); 122 } 123 indices.resize(numIndices); 124 if (heapParams) { 125 heapParams->reserve(numIndices); 126 heapParams->clear(); 127 } 128 c2_status_t status; 129 Return<void> transStatus = base()->query( 130 indices, 131 mayBlock == C2_MAY_BLOCK, 132 [&status, &numStackIndices, &stackParams, heapParams]( 133 Status s, const Params& p) { 134 status = static_cast<c2_status_t>(s); 135 if (status != C2_OK) { 136 ALOGE("query -- call failed. " 137 "Error code = %d", static_cast<int>(status)); 138 return; 139 } 140 std::vector<C2Param*> paramPointers; 141 status = parseParamsBlob(¶mPointers, p); 142 if (status != C2_OK) { 143 ALOGE("query -- error while parsing params. " 144 "Error code = %d", static_cast<int>(status)); 145 return; 146 } 147 size_t i = 0; 148 for (C2Param* const& paramPointer : paramPointers) { 149 if (numStackIndices > 0) { 150 --numStackIndices; 151 if (!paramPointer) { 152 ALOGW("query -- null stack param."); 153 if (numStackIndices > 0) { 154 ++i; 155 } 156 continue; 157 } 158 for (; !stackParams[i]; ++i) { 159 if (i >= stackParams.size()) { 160 ALOGE("query -- unexpected error."); 161 status = C2_CORRUPTED; 162 return; 163 } 164 } 165 if (!stackParams[i++]->updateFrom(*paramPointer)) { 166 ALOGW("query -- param update failed. index = %d", 167 static_cast<int>(paramPointer->index())); 168 } 169 } else { 170 if (!paramPointer) { 171 ALOGW("query -- null heap param."); 172 continue; 173 } 174 if (!heapParams) { 175 ALOGW("query -- extra stack param."); 176 } 177 heapParams->emplace_back(C2Param::Copy(*paramPointer)); 178 } 179 } 180 }); 181 if (!transStatus.isOk()) { 182 ALOGE("query -- transaction failed."); 183 return C2_TRANSACTION_FAILED; 184 } 185 return status; 186} 187 188c2_status_t Codec2ConfigurableClient::config( 189 const std::vector<C2Param*> ¶ms, 190 c2_blocking_t mayBlock, 191 std::vector<std::unique_ptr<C2SettingResult>>* const failures) { 192 Params hidlParams; 193 Status hidlStatus = createParamsBlob(&hidlParams, params); 194 if (hidlStatus != Status::OK) { 195 ALOGE("config -- bad input."); 196 return C2_TRANSACTION_FAILED; 197 } 198 c2_status_t status; 199 Return<void> transStatus = base()->config( 200 hidlParams, 201 mayBlock == C2_MAY_BLOCK, 202 [&status, ¶ms, failures]( 203 Status s, 204 const hidl_vec<SettingResult> f, 205 const Params& o) { 206 status = static_cast<c2_status_t>(s); 207 if (status != C2_OK) { 208 ALOGE("config -- call failed. " 209 "Error code = %d", static_cast<int>(status)); 210 return; 211 } 212 failures->clear(); 213 failures->resize(f.size()); 214 size_t i = 0; 215 for (const SettingResult& sf : f) { 216 status = objcpy(&(*failures)[i++], sf); 217 if (status != C2_OK) { 218 ALOGE("config -- invalid returned SettingResult. " 219 "Error code = %d", static_cast<int>(status)); 220 return; 221 } 222 } 223 status = updateParamsFromBlob(params, o); 224 }); 225 if (!transStatus.isOk()) { 226 ALOGE("config -- transaction failed."); 227 return C2_TRANSACTION_FAILED; 228 } 229 return status; 230} 231 232c2_status_t Codec2ConfigurableClient::querySupportedParams( 233 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const { 234 // TODO: Cache and query properly! 235 c2_status_t status; 236 Return<void> transStatus = base()->querySupportedParams( 237 std::numeric_limits<uint32_t>::min(), 238 std::numeric_limits<uint32_t>::max(), 239 [&status, params]( 240 Status s, 241 const hidl_vec<ParamDescriptor>& p) { 242 status = static_cast<c2_status_t>(s); 243 if (status != C2_OK) { 244 ALOGE("querySupportedParams -- call failed. " 245 "Error code = %d", static_cast<int>(status)); 246 return; 247 } 248 params->resize(p.size()); 249 size_t i = 0; 250 for (const ParamDescriptor& sp : p) { 251 status = objcpy(&(*params)[i++], sp); 252 if (status != C2_OK) { 253 ALOGE("querySupportedParams -- " 254 "invalid returned ParamDescriptor. " 255 "Error code = %d", static_cast<int>(status)); 256 return; 257 } 258 } 259 }); 260 if (!transStatus.isOk()) { 261 ALOGE("querySupportedParams -- transaction failed."); 262 return C2_TRANSACTION_FAILED; 263 } 264 return status; 265} 266 267c2_status_t Codec2ConfigurableClient::querySupportedValues( 268 std::vector<C2FieldSupportedValuesQuery>& fields, 269 c2_blocking_t mayBlock) const { 270 hidl_vec<FieldSupportedValuesQuery> inFields(fields.size()); 271 for (size_t i = 0; i < fields.size(); ++i) { 272 Status hidlStatus = objcpy(&inFields[i], fields[i]); 273 if (hidlStatus != Status::OK) { 274 ALOGE("querySupportedValues -- bad input"); 275 return C2_TRANSACTION_FAILED; 276 } 277 } 278 279 c2_status_t status; 280 Return<void> transStatus = base()->querySupportedValues( 281 inFields, 282 mayBlock == C2_MAY_BLOCK, 283 [&status, &inFields, &fields]( 284 Status s, 285 const hidl_vec<FieldSupportedValuesQueryResult>& r) { 286 status = static_cast<c2_status_t>(s); 287 if (status != C2_OK) { 288 ALOGE("querySupportedValues -- call failed. " 289 "Error code = %d", static_cast<int>(status)); 290 return; 291 } 292 if (r.size() != fields.size()) { 293 ALOGE("querySupportedValues -- input and output lists " 294 "have different sizes."); 295 status = C2_CORRUPTED; 296 return; 297 } 298 for (size_t i = 0; i < fields.size(); ++i) { 299 status = objcpy(&fields[i], inFields[i], r[i]); 300 if (status != C2_OK) { 301 ALOGE("querySupportedValues -- invalid returned value. " 302 "Error code = %d", static_cast<int>(status)); 303 return; 304 } 305 } 306 }); 307 if (!transStatus.isOk()) { 308 ALOGE("querySupportedValues -- transaction failed."); 309 return C2_TRANSACTION_FAILED; 310 } 311 return status; 312} 313 314// Codec2Client 315 316Codec2Client::Base* Codec2Client::base() const { 317 return static_cast<Base*>(mBase.get()); 318} 319 320Codec2Client::Codec2Client(const sp<Codec2Client::Base>& base) : 321 Codec2ConfigurableClient(base), mListed(false) { 322} 323 324c2_status_t Codec2Client::createComponent( 325 const C2String& name, 326 const std::shared_ptr<Codec2Client::Listener>& listener, 327 std::shared_ptr<Codec2Client::Component>* const component) { 328 329 // TODO: Add support for Bufferpool 330 331 struct HidlListener : public IComponentListener { 332 std::shared_ptr<Codec2Client::Listener> base; 333 std::weak_ptr<Codec2Client::Component> component; 334 335 virtual Return<void> onWorkDone(const WorkBundle& workBundle) override { 336 std::list<std::unique_ptr<C2Work>> workItems; 337 c2_status_t status = objcpy(&workItems, workBundle); 338 if (status != C2_OK) { 339 ALOGE("onWorkDone -- received corrupted WorkBundle. " 340 "Error code: %d", static_cast<int>(status)); 341 return Void(); 342 } 343 base->onWorkDone(component, workItems); 344 return Void(); 345 } 346 347 virtual Return<void> onTripped( 348 const hidl_vec<SettingResult>& settingResults) override { 349 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults( 350 settingResults.size()); 351 c2_status_t status; 352 for (size_t i = 0; i < settingResults.size(); ++i) { 353 std::unique_ptr<C2SettingResult> c2SettingResult; 354 status = objcpy(&c2SettingResult, settingResults[i]); 355 if (status != C2_OK) { 356 ALOGE("onTripped -- received corrupted SettingResult. " 357 "Error code: %d", static_cast<int>(status)); 358 return Void(); 359 } 360 c2SettingResults[i] = std::move(c2SettingResult); 361 } 362 base->onTripped(component, c2SettingResults); 363 return Void(); 364 } 365 366 virtual Return<void> onError(Status s, uint32_t errorCode) override { 367 ALOGE("onError -- status = %d, errorCode = %u. ", 368 static_cast<int>(s), 369 static_cast<unsigned>(errorCode)); 370 base->onError(component, s == Status::OK ? 371 errorCode : static_cast<c2_status_t>(s)); 372 return Void(); 373 } 374 }; 375 376 c2_status_t status; 377 sp<HidlListener> hidlListener = new HidlListener(); 378 hidlListener->base = listener; 379 Return<void> transStatus = base()->createComponent( 380 name, 381 hidlListener, 382 nullptr, 383 [&status, component, hidlListener]( 384 Status s, 385 const sp<IComponent>& c) { 386 status = static_cast<c2_status_t>(s); 387 if (status != C2_OK) { 388 ALOGE("createComponent -- call failed. " 389 "Error code = %d", static_cast<int>(status)); 390 return; 391 } 392 *component = std::make_shared<Codec2Client::Component>(c); 393 hidlListener->component = *component; 394 }); 395 if (!transStatus.isOk()) { 396 ALOGE("createComponent -- failed transaction."); 397 return C2_TRANSACTION_FAILED; 398 } 399 return status; 400} 401 402c2_status_t Codec2Client::createInterface( 403 const C2String& name, 404 std::shared_ptr<Codec2Client::Interface>* const interface) { 405 c2_status_t status; 406 Return<void> transStatus = base()->createInterface( 407 name, 408 [&status, interface]( 409 Status s, 410 const sp<IComponentInterface>& i) { 411 status = static_cast<c2_status_t>(s); 412 if (status != C2_OK) { 413 ALOGE("createInterface -- call failed. " 414 "Error code = %d", static_cast<int>(status)); 415 return; 416 } 417 *interface = std::make_shared<Codec2Client::Interface>(i); 418 }); 419 if (!transStatus.isOk()) { 420 ALOGE("createInterface -- failed transaction."); 421 return C2_TRANSACTION_FAILED; 422 } 423 return status; 424} 425 426c2_status_t Codec2Client::createInputSurface( 427 std::shared_ptr<Codec2Client::InputSurface>* const inputSurface) { 428 Return<sp<IInputSurface>> transResult = base()->createInputSurface(); 429 if (!transResult.isOk()) { 430 ALOGE("createInputSurface -- failed transaction."); 431 return C2_TRANSACTION_FAILED; 432 } 433 *inputSurface = std::make_shared<InputSurface>( 434 static_cast<sp<IInputSurface>>(transResult)); 435 if (!*inputSurface) { 436 ALOGE("createInputSurface -- failed to create client."); 437 return C2_CORRUPTED; 438 } 439 return C2_OK; 440} 441 442const std::vector<C2Component::Traits>& Codec2Client::listComponents() const { 443 std::lock_guard<std::mutex> lock(mMutex); 444 if (mListed) { 445 return mTraitsList; 446 } 447 Return<void> transStatus = base()->listComponents( 448 [this](const hidl_vec<IComponentStore::ComponentTraits>& t) { 449 mTraitsList.resize(t.size()); 450 mAliasesBuffer.resize(t.size()); 451 for (size_t i = 0; i < t.size(); ++i) { 452 c2_status_t status = objcpy( 453 &mTraitsList[i], &mAliasesBuffer[i], t[i]); 454 if (status != C2_OK) { 455 ALOGE("listComponents -- corrupted output."); 456 return; 457 } 458 } 459 }); 460 if (!transStatus.isOk()) { 461 ALOGE("listComponents -- failed transaction."); 462 } 463 mListed = true; 464 return mTraitsList; 465} 466 467c2_status_t Codec2Client::copyBuffer( 468 const std::shared_ptr<C2Buffer>& src, 469 const std::shared_ptr<C2Buffer>& dst) { 470 // TODO: Implement? 471 (void)src; 472 (void)dst; 473 ALOGE("copyBuffer not implemented"); 474 return C2_OMITTED; 475} 476 477std::shared_ptr<C2ParamReflector> 478 Codec2Client::getParamReflector() { 479 // TODO: Implement this once there is a way to construct C2StructDescriptor 480 // dynamically. 481 ALOGE("getParamReflector -- not implemented."); 482 return nullptr; 483} 484 485std::shared_ptr<Codec2Client> Codec2Client::CreateFromService( 486 const char* instanceName, bool waitForService) { 487 if (!instanceName) { 488 return nullptr; 489 } 490 sp<Base> baseStore = waitForService ? 491 Base::getService(instanceName) : 492 Base::tryGetService(instanceName); 493 if (!baseStore) { 494 if (waitForService) { 495 ALOGE("Codec2.0 service inaccessible. Check the device manifest."); 496 } else { 497 ALOGW("Codec2.0 service not available right now. Try again later."); 498 } 499 return nullptr; 500 } 501 return std::make_shared<Codec2Client>(baseStore); 502} 503 504std::shared_ptr<Codec2Client::Component> 505 Codec2Client::CreateComponentByName( 506 const char* componentName, 507 const std::shared_ptr<Listener>& listener, 508 std::shared_ptr<Codec2Client>* owner) { 509 prepareClients(); 510 511 c2_status_t status; 512 std::shared_ptr<Component> component; 513 514 // Cache the mapping componentName -> Codec2Client 515 static std::mutex component2ClientMutex; 516 static std::map<std::string, Codec2Client*> component2Client; 517 518 std::unique_lock<std::mutex> lock(component2ClientMutex); 519 std::map<C2String, Codec2Client*>::const_iterator it = 520 component2Client.find(componentName); 521 if (it != component2Client.end()) { 522 Codec2Client *client = it->second; 523 lock.unlock(); 524 525 status = client->createComponent( 526 componentName, 527 listener, 528 &component); 529 if (status == C2_OK) { 530 return component; 531 } 532 return nullptr; 533 } 534 for (const std::shared_ptr<Codec2Client>& client : gClients) { 535 if (!client) { 536 continue; 537 } 538 status = client->createComponent( 539 componentName, 540 listener, 541 &component); 542 if (status == C2_OK) { 543 if (owner) { 544 *owner = client; 545 } 546 component2Client.emplace(componentName, client.get()); 547 return component; 548 } 549 } 550 return nullptr; 551} 552 553const std::vector<C2Component::Traits>& Codec2Client::ListComponents() { 554 prepareClients(); 555 556 static std::vector<C2Component::Traits> traitsList = [](){ 557 std::vector<C2Component::Traits> list; 558 size_t listSize = 0; 559 for (const std::shared_ptr<Codec2Client>& client : gClients) { 560 if (!client) { 561 continue; 562 } 563 listSize += client->listComponents().size(); 564 } 565 list.reserve(listSize); 566 for (const std::shared_ptr<Codec2Client>& client : gClients) { 567 if (!client) { 568 continue; 569 } 570 list.insert( 571 list.end(), 572 client->listComponents().begin(), 573 client->listComponents().end()); 574 } 575 return list; 576 }(); 577 578 return traitsList; 579} 580 581// Codec2Client::Listener 582 583Codec2Client::Listener::~Listener() { 584} 585 586// Codec2Client::Component 587 588Codec2Client::Component::Base* Codec2Client::Component::base() const { 589 return static_cast<Base*>(mBase.get()); 590} 591 592Codec2Client::Component::Component(const sp<Codec2Client::Component::Base>& base) : 593 Codec2Client::Configurable(base) { 594} 595 596c2_status_t Codec2Client::Component::createBlockPool( 597 C2Allocator::id_t id, 598 C2BlockPool::local_id_t* localId, 599 std::shared_ptr<Codec2Client::Configurable>* configurable) { 600 c2_status_t status; 601 Return<void> transStatus = base()->createBlockPool( 602 static_cast<uint32_t>(id), 603 [&status, localId, configurable]( 604 Status s, 605 uint64_t pId, 606 const sp<IConfigurable>& c) { 607 status = static_cast<c2_status_t>(s); 608 if (status != C2_OK) { 609 ALOGE("createBlockPool -- call failed. " 610 "Error code = %d", static_cast<int>(status)); 611 return; 612 } 613 *localId = static_cast<C2BlockPool::local_id_t>(pId); 614 *configurable = std::make_shared<Codec2Client::Configurable>(c); 615 }); 616 if (!transStatus.isOk()) { 617 ALOGE("createBlockPool -- transaction failed."); 618 return C2_TRANSACTION_FAILED; 619 } 620 return status; 621} 622 623c2_status_t Codec2Client::Component::queue( 624 std::list<std::unique_ptr<C2Work>>* const items) { 625 WorkBundle workBundle; 626 Status hidlStatus = objcpy(&workBundle, *items); 627 if (hidlStatus != Status::OK) { 628 ALOGE("queue -- bad input."); 629 return C2_TRANSACTION_FAILED; 630 } 631 Return<Status> transStatus = base()->queue(workBundle); 632 if (!transStatus.isOk()) { 633 ALOGE("queue -- transaction failed."); 634 return C2_TRANSACTION_FAILED; 635 } 636 c2_status_t status = 637 static_cast<c2_status_t>(static_cast<Status>(transStatus)); 638 if (status != C2_OK) { 639 ALOGE("queue -- call failed. " 640 "Error code = %d", static_cast<int>(status)); 641 } 642 return status; 643} 644 645c2_status_t Codec2Client::Component::flush( 646 C2Component::flush_mode_t mode, 647 std::list<std::unique_ptr<C2Work>>* const flushedWork) { 648 (void)mode; // Flush mode isn't supported in HIDL yet. 649 c2_status_t status; 650 Return<void> transStatus = base()->flush( 651 [&status, flushedWork]( 652 Status s, const WorkBundle& wb) { 653 status = static_cast<c2_status_t>(s); 654 if (status != C2_OK) { 655 ALOGE("flush -- call failed. " 656 "Error code = %d", static_cast<int>(status)); 657 return; 658 } 659 status = objcpy(flushedWork, wb); 660 }); 661 if (!transStatus.isOk()) { 662 ALOGE("flush -- transaction failed."); 663 return C2_TRANSACTION_FAILED; 664 } 665 return status; 666} 667 668c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) { 669 Return<Status> transStatus = base()->drain( 670 mode == C2Component::DRAIN_COMPONENT_WITH_EOS); 671 if (!transStatus.isOk()) { 672 ALOGE("drain -- transaction failed."); 673 return C2_TRANSACTION_FAILED; 674 } 675 c2_status_t status = 676 static_cast<c2_status_t>(static_cast<Status>(transStatus)); 677 if (status != C2_OK) { 678 ALOGE("drain -- call failed. " 679 "Error code = %d", static_cast<int>(status)); 680 } 681 return status; 682} 683 684c2_status_t Codec2Client::Component::start() { 685 Return<Status> transStatus = base()->start(); 686 if (!transStatus.isOk()) { 687 ALOGE("start -- transaction failed."); 688 return C2_TRANSACTION_FAILED; 689 } 690 c2_status_t status = 691 static_cast<c2_status_t>(static_cast<Status>(transStatus)); 692 if (status != C2_OK) { 693 ALOGE("start -- call failed. " 694 "Error code = %d", static_cast<int>(status)); 695 } 696 return status; 697} 698 699c2_status_t Codec2Client::Component::stop() { 700 Return<Status> transStatus = base()->stop(); 701 if (!transStatus.isOk()) { 702 ALOGE("stop -- transaction failed."); 703 return C2_TRANSACTION_FAILED; 704 } 705 c2_status_t status = 706 static_cast<c2_status_t>(static_cast<Status>(transStatus)); 707 if (status != C2_OK) { 708 ALOGE("stop -- call failed. " 709 "Error code = %d", static_cast<int>(status)); 710 } 711 return status; 712} 713 714c2_status_t Codec2Client::Component::reset() { 715 Return<Status> transStatus = base()->reset(); 716 if (!transStatus.isOk()) { 717 ALOGE("reset -- transaction failed."); 718 return C2_TRANSACTION_FAILED; 719 } 720 c2_status_t status = 721 static_cast<c2_status_t>(static_cast<Status>(transStatus)); 722 if (status != C2_OK) { 723 ALOGE("reset -- call failed. " 724 "Error code = %d", static_cast<int>(status)); 725 } 726 return status; 727} 728 729c2_status_t Codec2Client::Component::release() { 730 Return<Status> transStatus = base()->release(); 731 if (!transStatus.isOk()) { 732 ALOGE("release -- transaction failed."); 733 return C2_TRANSACTION_FAILED; 734 } 735 c2_status_t status = 736 static_cast<c2_status_t>(static_cast<Status>(transStatus)); 737 if (status != C2_OK) { 738 ALOGE("release -- call failed. " 739 "Error code = %d", static_cast<int>(status)); 740 } 741 return status; 742} 743 744c2_status_t Codec2Client::Component::setOutputSurface( 745 const sp<IGraphicBufferProducer>& surface) { 746 Return<Status> transStatus = base()->setOutputSurface(surface); 747 if (!transStatus.isOk()) { 748 ALOGE("setOutputSurface -- transaction failed."); 749 return C2_TRANSACTION_FAILED; 750 } 751 c2_status_t status = 752 static_cast<c2_status_t>(static_cast<Status>(transStatus)); 753 if (status != C2_OK) { 754 ALOGE("setOutputSurface -- call failed. " 755 "Error code = %d", static_cast<int>(status)); 756 } 757 return status; 758} 759 760c2_status_t Codec2Client::Component::connectToInputSurface( 761 const std::shared_ptr<InputSurface>& surface) { 762 Return<Status> transStatus = base()->connectToInputSurface( 763 surface->base()); 764 if (!transStatus.isOk()) { 765 ALOGE("connectToInputSurface -- transaction failed."); 766 return C2_TRANSACTION_FAILED; 767 } 768 c2_status_t status = 769 static_cast<c2_status_t>(static_cast<Status>(transStatus)); 770 if (status != C2_OK) { 771 ALOGE("connectToInputSurface -- call failed. " 772 "Error code = %d", static_cast<int>(status)); 773 } 774 return status; 775} 776 777c2_status_t Codec2Client::Component::connectToOmxInputSurface( 778 const sp<IGraphicBufferProducer>& producer, 779 const sp<IGraphicBufferSource>& source) { 780 Return<Status> transStatus = base()->connectToOmxInputSurface( 781 producer, source); 782 if (!transStatus.isOk()) { 783 ALOGE("connectToOmxInputSurface -- transaction failed."); 784 return C2_TRANSACTION_FAILED; 785 } 786 c2_status_t status = 787 static_cast<c2_status_t>(static_cast<Status>(transStatus)); 788 if (status != C2_OK) { 789 ALOGE("connectToOmxInputSurface -- call failed. " 790 "Error code = %d", static_cast<int>(status)); 791 } 792 return status; 793} 794 795c2_status_t Codec2Client::Component::disconnectFromInputSurface() { 796 Return<Status> transStatus = base()->disconnectFromInputSurface(); 797 if (!transStatus.isOk()) { 798 ALOGE("disconnectToInputSurface -- transaction failed."); 799 return C2_TRANSACTION_FAILED; 800 } 801 c2_status_t status = 802 static_cast<c2_status_t>(static_cast<Status>(transStatus)); 803 if (status != C2_OK) { 804 ALOGE("disconnectFromInputSurface -- call failed. " 805 "Error code = %d", static_cast<int>(status)); 806 } 807 return status; 808} 809 810c2_status_t Codec2Client::Component::getLocalBlockPool( 811 C2BlockPool::local_id_t id, 812 std::shared_ptr<C2BlockPool>* pool) const { 813 pool->reset(); 814 if (!mBase) { 815 return C2_BAD_VALUE; 816 } 817 // TODO support pre-registered block pools 818 std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore(); 819 std::shared_ptr<C2Allocator> allocator; 820 c2_status_t res = C2_NOT_FOUND; 821 822 switch (id) { 823 case C2BlockPool::BASIC_LINEAR: 824 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator); 825 if (res == C2_OK) { 826 *pool = std::make_shared<C2BasicLinearBlockPool>(allocator); 827 } 828 break; 829 case C2BlockPool::BASIC_GRAPHIC: 830 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator); 831 if (res == C2_OK) { 832 *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator); 833 } 834 break; 835 default: 836 break; 837 } 838 if (res != C2_OK) { 839 ALOGE("getLocalBlockPool -- failed to get pool with id %d. " 840 "Error code = %d", 841 static_cast<int>(id), 842 res); 843 } 844 return res; 845} 846 847c2_status_t Codec2Client::Component::createLocalBlockPool( 848 C2PlatformAllocatorStore::id_t allocatorId, 849 std::shared_ptr<C2BlockPool>* pool) const { 850 pool->reset(); 851 if (!mBase) { 852 return C2_BAD_VALUE; 853 } 854 // TODO: support caching block pool along with GetCodec2BlockPool. 855 static std::atomic_int sBlockPoolId(C2BlockPool::PLATFORM_START); 856 std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore(); 857 std::shared_ptr<C2Allocator> allocator; 858 c2_status_t res = C2_NOT_FOUND; 859 860 switch (allocatorId) { 861 case C2PlatformAllocatorStore::ION: 862 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator); 863 if (res == C2_OK) { 864 *pool = std::make_shared<C2PooledBlockPool>(allocator, sBlockPoolId++); 865 if (!*pool) { 866 res = C2_NO_MEMORY; 867 } 868 } 869 break; 870 case C2PlatformAllocatorStore::GRALLOC: 871 // TODO: support gralloc 872 break; 873 default: 874 break; 875 } 876 if (res != C2_OK) { 877 ALOGE("createLocalBlockPool -- " 878 "failed to create pool with allocator id %d. " 879 "Error code = %d", 880 static_cast<int>(allocatorId), 881 res); 882 } 883 return res; 884} 885 886// Codec2Client::InputSurface 887 888Codec2Client::InputSurface::Base* Codec2Client::InputSurface::base() const { 889 return static_cast<Base*>(mBase.get()); 890} 891 892Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base) : 893 mBase(base), 894 mGraphicBufferProducer(new 895 ::android::hardware::graphics::bufferqueue::V1_0::utils:: 896 H2BGraphicBufferProducer(base)) { 897} 898 899c2_status_t Codec2Client::InputSurface::connectToComponent( 900 const std::shared_ptr<Codec2Client::Component>& component, 901 std::shared_ptr<Connection>* connection) { 902 c2_status_t status; 903 Return<void> transStatus = base()->connectToComponent( 904 component->base(), 905 [&status, connection]( 906 Status s, 907 const sp<IInputSurfaceConnection>& c) { 908 status = static_cast<c2_status_t>(s); 909 if (status != C2_OK) { 910 ALOGE("connectToComponent -- call failed. " 911 "Error code = %d", static_cast<int>(status)); 912 return; 913 } 914 *connection = std::make_shared<Connection>(c); 915 }); 916 if (!transStatus.isOk()) { 917 ALOGE("connect -- transaction failed."); 918 return C2_TRANSACTION_FAILED; 919 } 920 return status; 921} 922 923std::shared_ptr<Codec2Client::Configurable> 924 Codec2Client::InputSurface::getConfigurable() const { 925 Return<sp<IConfigurable>> transResult = base()->getConfigurable(); 926 if (!transResult.isOk()) { 927 ALOGW("getConfigurable -- transaction failed."); 928 return nullptr; 929 } 930 if (!static_cast<sp<IConfigurable>>(transResult)) { 931 ALOGW("getConfigurable -- null pointer."); 932 return nullptr; 933 } 934 return std::make_shared<Configurable>(transResult); 935} 936 937const sp<IGraphicBufferProducer>& 938 Codec2Client::InputSurface::getGraphicBufferProducer() const { 939 return mGraphicBufferProducer; 940} 941 942// Codec2Client::InputSurfaceConnection 943 944Codec2Client::InputSurfaceConnection::Base* 945 Codec2Client::InputSurfaceConnection::base() const { 946 return static_cast<Base*>(mBase.get()); 947} 948 949Codec2Client::InputSurfaceConnection::InputSurfaceConnection( 950 const sp<Codec2Client::InputSurfaceConnection::Base>& base) : 951 mBase(base) { 952} 953 954c2_status_t Codec2Client::InputSurfaceConnection::disconnect() { 955 Return<Status> transResult = base()->disconnect(); 956 return static_cast<c2_status_t>(static_cast<Status>(transResult)); 957} 958 959} // namespace android 960 961