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