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-types" 19 #include <log/log.h> 20 21 #include <codec2/hidl/1.0/types.h> 22 23 #include <media/stagefright/bqhelper/WGraphicBufferProducer.h> 24 25 #include <C2AllocatorIon.h> 26 #include <C2AllocatorGralloc.h> 27 #include <C2BlockInternal.h> 28 #include <C2Buffer.h> 29 #include <C2Component.h> 30 #include <C2Param.h> 31 #include <C2ParamInternal.h> 32 #include <C2PlatformSupport.h> 33 #include <C2Work.h> 34 #include <util/C2ParamUtils.h> 35 36 #include <algorithm> 37 #include <functional> 38 #include <unordered_map> 39 40 #include <media/stagefright/foundation/AUtils.h> 41 42 namespace hardware { 43 namespace google { 44 namespace media { 45 namespace c2 { 46 namespace V1_0 { 47 namespace utils { 48 49 using namespace ::android; 50 using ::android::hardware::Return; 51 using ::android::hardware::media::bufferpool::BufferPoolData; 52 using ::android::hardware::media::bufferpool::V1_0::BufferStatusMessage; 53 using ::android::hardware::media::bufferpool::V1_0::ResultStatus; 54 using ::android::hardware::media::bufferpool::V1_0::implementation:: 55 ClientManager; 56 using ::android::hardware::media::bufferpool::V1_0::implementation:: 57 TransactionId; 58 using ::android::TWGraphicBufferProducer; 59 60 namespace /* unnamed */ { 61 62 template <typename Common, typename DstVector, typename SrcVector> 63 void copyVector(DstVector* d, const SrcVector& s) { 64 static_assert(sizeof(Common) == sizeof(decltype((*d)[0])), 65 "DstVector's component size does not match Common"); 66 static_assert(sizeof(Common) == sizeof(decltype(s[0])), 67 "SrcVector's component size does not match Common"); 68 d->resize(s.size()); 69 std::copy( 70 reinterpret_cast<const Common*>(&s[0]), 71 reinterpret_cast<const Common*>(&s[0] + s.size()), 72 reinterpret_cast<Common*>(&(*d)[0])); 73 } 74 75 // C2ParamField -> ParamField 76 void objcpy(ParamField *d, const C2ParamField &s) { 77 d->index = static_cast<ParamIndex>(_C2ParamInspector::GetIndex(s)); 78 d->fieldId.offset = static_cast<uint32_t>(_C2ParamInspector::GetOffset(s)); 79 d->fieldId.size = static_cast<uint32_t>(_C2ParamInspector::GetSize(s)); 80 } 81 82 struct C2ParamFieldBuilder : public C2ParamField { 83 C2ParamFieldBuilder() : C2ParamField( 84 static_cast<C2Param::Index>(static_cast<uint32_t>(0)), 0, 0) { 85 } 86 // ParamField -> C2ParamField 87 C2ParamFieldBuilder(const ParamField& s) : C2ParamField( 88 static_cast<C2Param::Index>(static_cast<uint32_t>(s.index)), 89 static_cast<uint32_t>(s.fieldId.offset), 90 static_cast<uint32_t>(s.fieldId.size)) { 91 } 92 }; 93 94 // C2WorkOrdinalStruct -> WorkOrdinal 95 void objcpy(WorkOrdinal *d, const C2WorkOrdinalStruct &s) { 96 d->frameIndex = static_cast<uint64_t>(s.frameIndex.peeku()); 97 d->timestampUs = static_cast<uint64_t>(s.timestamp.peeku()); 98 d->customOrdinal = static_cast<uint64_t>(s.customOrdinal.peeku()); 99 } 100 101 // WorkOrdinal -> C2WorkOrdinalStruct 102 void objcpy(C2WorkOrdinalStruct *d, const WorkOrdinal &s) { 103 d->frameIndex = c2_cntr64_t(s.frameIndex); 104 d->timestamp = c2_cntr64_t(s.timestampUs); 105 d->customOrdinal = c2_cntr64_t(s.customOrdinal); 106 } 107 108 // C2FieldSupportedValues::range's type -> FieldSupportedValues::Range 109 void objcpy( 110 FieldSupportedValues::Range* d, 111 const decltype(C2FieldSupportedValues::range)& s) { 112 d->min = static_cast<PrimitiveValue>(s.min.u64); 113 d->max = static_cast<PrimitiveValue>(s.max.u64); 114 d->step = static_cast<PrimitiveValue>(s.step.u64); 115 d->num = static_cast<PrimitiveValue>(s.num.u64); 116 d->denom = static_cast<PrimitiveValue>(s.denom.u64); 117 } 118 119 // C2FieldSupportedValues -> FieldSupportedValues 120 Status objcpy(FieldSupportedValues *d, const C2FieldSupportedValues &s) { 121 d->typeOther = static_cast<int32_t>(s.type); 122 switch (s.type) { 123 case C2FieldSupportedValues::EMPTY: 124 d->type = FieldSupportedValues::Type::EMPTY; 125 d->values.resize(0); 126 return Status::OK; 127 case C2FieldSupportedValues::RANGE: 128 d->type = FieldSupportedValues::Type::RANGE; 129 objcpy(&d->range, s.range); 130 d->values.resize(0); 131 return Status::OK; 132 default: 133 switch (s.type) { 134 case C2FieldSupportedValues::VALUES: 135 d->type = FieldSupportedValues::Type::VALUES; 136 break; 137 case C2FieldSupportedValues::FLAGS: 138 d->type = FieldSupportedValues::Type::FLAGS; 139 break; 140 default: 141 d->type = FieldSupportedValues::Type::OTHER; 142 // Copy all fields in this case 143 objcpy(&d->range, s.range); 144 } 145 d->values.resize(s.values.size()); 146 copyVector<uint64_t>(&d->values, s.values); 147 return Status::OK; 148 } 149 } 150 151 // FieldSupportedValues::Range -> C2FieldSupportedValues::range's type 152 void objcpy( 153 decltype(C2FieldSupportedValues::range)* d, 154 const FieldSupportedValues::Range& s) { 155 d->min.u64 = static_cast<uint64_t>(s.min); 156 d->max.u64 = static_cast<uint64_t>(s.max); 157 d->step.u64 = static_cast<uint64_t>(s.step); 158 d->num.u64 = static_cast<uint64_t>(s.num); 159 d->denom.u64 = static_cast<uint64_t>(s.denom); 160 } 161 162 // FieldSupportedValues -> C2FieldSupportedValues 163 c2_status_t objcpy(C2FieldSupportedValues *d, const FieldSupportedValues &s) { 164 switch (s.type) { 165 case FieldSupportedValues::Type::EMPTY: 166 d->type = C2FieldSupportedValues::EMPTY; 167 return C2_OK; 168 case FieldSupportedValues::Type::RANGE: 169 d->type = C2FieldSupportedValues::RANGE; 170 objcpy(&d->range, s.range); 171 d->values.resize(0); 172 return C2_OK; 173 default: 174 switch (s.type) { 175 case FieldSupportedValues::Type::VALUES: 176 d->type = C2FieldSupportedValues::VALUES; 177 break; 178 case FieldSupportedValues::Type::FLAGS: 179 d->type = C2FieldSupportedValues::FLAGS; 180 break; 181 default: 182 d->type = static_cast<C2FieldSupportedValues::type_t>(s.typeOther); 183 // Copy all fields in this case 184 objcpy(&d->range, s.range); 185 } 186 copyVector<uint64_t>(&d->values, s.values); 187 return C2_OK; 188 } 189 } 190 191 } // unnamed namespace 192 193 // C2FieldSupportedValuesQuery -> FieldSupportedValuesQuery 194 Status objcpy( 195 FieldSupportedValuesQuery* d, 196 const C2FieldSupportedValuesQuery& s) { 197 objcpy(&d->field, s.field()); 198 switch (s.type()) { 199 case C2FieldSupportedValuesQuery::POSSIBLE: 200 d->type = FieldSupportedValuesQuery::Type::POSSIBLE; 201 break; 202 case C2FieldSupportedValuesQuery::CURRENT: 203 d->type = FieldSupportedValuesQuery::Type::CURRENT; 204 break; 205 default: 206 ALOGE("Unknown type of C2FieldSupportedValuesQuery: %u", 207 static_cast<unsigned>(s.type())); 208 return Status::BAD_VALUE; 209 } 210 return Status::OK; 211 } 212 213 // FieldSupportedValuesQuery -> C2FieldSupportedValuesQuery 214 c2_status_t objcpy( 215 C2FieldSupportedValuesQuery* d, 216 const FieldSupportedValuesQuery& s) { 217 C2FieldSupportedValuesQuery::type_t dType; 218 switch (s.type) { 219 case FieldSupportedValuesQuery::Type::POSSIBLE: 220 dType = C2FieldSupportedValuesQuery::POSSIBLE; 221 break; 222 case FieldSupportedValuesQuery::Type::CURRENT: 223 dType = C2FieldSupportedValuesQuery::CURRENT; 224 break; 225 default: 226 ALOGE("Unknown type of FieldSupportedValuesQuery: %u", 227 static_cast<unsigned>(s.type)); 228 return C2_BAD_VALUE; 229 } 230 *d = C2FieldSupportedValuesQuery(C2ParamFieldBuilder(s.field), dType); 231 return C2_OK; 232 } 233 234 // C2FieldSupportedValuesQuery -> FieldSupportedValuesQueryResult 235 Status objcpy( 236 FieldSupportedValuesQueryResult* d, 237 const C2FieldSupportedValuesQuery& s) { 238 d->status = static_cast<Status>(s.status); 239 return objcpy(&d->values, s.values); 240 } 241 242 // FieldSupportedValuesQuery, FieldSupportedValuesQueryResult -> 243 // C2FieldSupportedValuesQuery 244 c2_status_t objcpy( 245 C2FieldSupportedValuesQuery* d, 246 const FieldSupportedValuesQuery& sq, 247 const FieldSupportedValuesQueryResult& sr) { 248 c2_status_t status = objcpy(d, sq); 249 if (status != C2_OK) { 250 return status; 251 } 252 d->status = static_cast<c2_status_t>(sr.status); 253 return objcpy(&d->values, sr.values); 254 } 255 256 // C2Component::Traits -> IComponentStore::ComponentTraits 257 Status objcpy( 258 IComponentStore::ComponentTraits *d, 259 const C2Component::Traits &s) { 260 d->name = s.name; 261 262 switch (s.domain) { 263 case C2Component::DOMAIN_VIDEO: 264 d->domain = IComponentStore::ComponentTraits::Domain::VIDEO; 265 break; 266 case C2Component::DOMAIN_AUDIO: 267 d->domain = IComponentStore::ComponentTraits::Domain::AUDIO; 268 break; 269 default: 270 d->domain = IComponentStore::ComponentTraits::Domain::OTHER; 271 } 272 d->domainOther = static_cast<uint32_t>(s.domain); 273 274 switch (s.kind) { 275 case C2Component::KIND_DECODER: 276 d->kind = IComponentStore::ComponentTraits::Kind::DECODER; 277 break; 278 case C2Component::KIND_ENCODER: 279 d->kind = IComponentStore::ComponentTraits::Kind::ENCODER; 280 break; 281 default: 282 d->kind = IComponentStore::ComponentTraits::Kind::OTHER; 283 } 284 d->kindOther = static_cast<uint32_t>(s.kind); 285 286 d->rank = static_cast<uint32_t>(s.rank); 287 288 d->mediaType = s.mediaType; 289 290 d->aliases.resize(s.aliases.size()); 291 for (size_t ix = s.aliases.size(); ix > 0; ) { 292 --ix; 293 d->aliases[ix] = s.aliases[ix]; 294 } 295 return Status::OK; 296 } 297 298 // ComponentTraits -> C2Component::Traits, std::unique_ptr<std::vector<std::string>> 299 c2_status_t objcpy( 300 C2Component::Traits* d, 301 std::unique_ptr<std::vector<std::string>>* aliasesBuffer, 302 const IComponentStore::ComponentTraits& s) { 303 d->name = s.name.c_str(); 304 305 switch (s.domain) { 306 case IComponentStore::ComponentTraits::Domain::VIDEO: 307 d->domain = C2Component::DOMAIN_VIDEO; 308 break; 309 case IComponentStore::ComponentTraits::Domain::AUDIO: 310 d->domain = C2Component::DOMAIN_AUDIO; 311 break; 312 default: 313 d->domain = static_cast<C2Component::domain_t>(s.domainOther); 314 } 315 316 switch (s.kind) { 317 case IComponentStore::ComponentTraits::Kind::DECODER: 318 d->kind = C2Component::KIND_DECODER; 319 break; 320 case IComponentStore::ComponentTraits::Kind::ENCODER: 321 d->kind = C2Component::KIND_ENCODER; 322 break; 323 default: 324 d->kind = static_cast<C2Component::kind_t>(s.kindOther); 325 } 326 327 d->rank = static_cast<C2Component::rank_t>(s.rank); 328 d->mediaType = s.mediaType.c_str(); 329 330 // aliasesBuffer must not be resized after this. 331 *aliasesBuffer = std::make_unique<std::vector<std::string>>( 332 s.aliases.size()); 333 (*aliasesBuffer)->resize(s.aliases.size()); 334 std::vector<C2StringLiteral> dAliases(s.aliases.size()); 335 for (size_t i = 0; i < s.aliases.size(); ++i) { 336 (**aliasesBuffer)[i] = s.aliases[i].c_str(); 337 d->aliases[i] = (**aliasesBuffer)[i].c_str(); 338 } 339 return C2_OK; 340 } 341 342 namespace /* unnamed */ { 343 344 // C2ParamFieldValues -> ParamFieldValues 345 Status objcpy(ParamFieldValues *d, const C2ParamFieldValues &s) { 346 objcpy(&d->paramOrField, s.paramOrField); 347 if (s.values) { 348 d->values.resize(1); 349 return objcpy(&d->values[0], *s.values); 350 } 351 d->values.resize(0); 352 return Status::OK; 353 } 354 355 // ParamFieldValues -> C2ParamFieldValues 356 c2_status_t objcpy(C2ParamFieldValues *d, const ParamFieldValues &s) { 357 d->paramOrField = C2ParamFieldBuilder(s.paramOrField); 358 if (s.values.size() == 1) { 359 d->values = std::make_unique<C2FieldSupportedValues>(); 360 return objcpy(d->values.get(), s.values[0]); 361 } else if (s.values.size() == 0) { 362 d->values.reset(); 363 return C2_OK; 364 } 365 ALOGE("Multiple FieldSupportedValues objects. " 366 "(Only one is allowed.)"); 367 return C2_BAD_VALUE; 368 } 369 370 } // unnamed namespace 371 372 // C2SettingResult -> SettingResult 373 Status objcpy(SettingResult *d, const C2SettingResult &s) { 374 d->failureOther = static_cast<uint32_t>(s.failure); 375 switch (s.failure) { 376 case C2SettingResult::READ_ONLY: 377 d->failure = SettingResult::Failure::READ_ONLY; 378 break; 379 case C2SettingResult::MISMATCH: 380 d->failure = SettingResult::Failure::MISMATCH; 381 break; 382 case C2SettingResult::BAD_VALUE: 383 d->failure = SettingResult::Failure::BAD_VALUE; 384 break; 385 case C2SettingResult::BAD_TYPE: 386 d->failure = SettingResult::Failure::BAD_TYPE; 387 break; 388 case C2SettingResult::BAD_PORT: 389 d->failure = SettingResult::Failure::BAD_PORT; 390 break; 391 case C2SettingResult::BAD_INDEX: 392 d->failure = SettingResult::Failure::BAD_INDEX; 393 break; 394 case C2SettingResult::CONFLICT: 395 d->failure = SettingResult::Failure::CONFLICT; 396 break; 397 case C2SettingResult::UNSUPPORTED: 398 d->failure = SettingResult::Failure::UNSUPPORTED; 399 break; 400 case C2SettingResult::INFO_CONFLICT: 401 d->failure = SettingResult::Failure::INFO_CONFLICT; 402 break; 403 default: 404 d->failure = SettingResult::Failure::OTHER; 405 } 406 Status status = objcpy(&d->field, s.field); 407 if (status != Status::OK) { 408 return status; 409 } 410 d->conflicts.resize(s.conflicts.size()); 411 size_t i = 0; 412 for (const C2ParamFieldValues& sConflict : s.conflicts) { 413 ParamFieldValues &dConflict = d->conflicts[i++]; 414 status = objcpy(&dConflict, sConflict); 415 if (status != Status::OK) { 416 return status; 417 } 418 } 419 return Status::OK; 420 } 421 422 // SettingResult -> std::unique_ptr<C2SettingResult> 423 c2_status_t objcpy(std::unique_ptr<C2SettingResult> *d, const SettingResult &s) { 424 *d = std::unique_ptr<C2SettingResult>(new C2SettingResult { 425 .field = C2ParamFieldValues(C2ParamFieldBuilder()) }); 426 if (!*d) { 427 return C2_NO_MEMORY; 428 } 429 430 // failure 431 switch (s.failure) { 432 case SettingResult::Failure::READ_ONLY: 433 (*d)->failure = C2SettingResult::READ_ONLY; 434 break; 435 case SettingResult::Failure::MISMATCH: 436 (*d)->failure = C2SettingResult::MISMATCH; 437 break; 438 case SettingResult::Failure::BAD_VALUE: 439 (*d)->failure = C2SettingResult::BAD_VALUE; 440 break; 441 case SettingResult::Failure::BAD_TYPE: 442 (*d)->failure = C2SettingResult::BAD_TYPE; 443 break; 444 case SettingResult::Failure::BAD_PORT: 445 (*d)->failure = C2SettingResult::BAD_PORT; 446 break; 447 case SettingResult::Failure::BAD_INDEX: 448 (*d)->failure = C2SettingResult::BAD_INDEX; 449 break; 450 case SettingResult::Failure::CONFLICT: 451 (*d)->failure = C2SettingResult::CONFLICT; 452 break; 453 case SettingResult::Failure::UNSUPPORTED: 454 (*d)->failure = C2SettingResult::UNSUPPORTED; 455 break; 456 case SettingResult::Failure::INFO_CONFLICT: 457 (*d)->failure = C2SettingResult::INFO_CONFLICT; 458 break; 459 default: 460 (*d)->failure = static_cast<C2SettingResult::Failure>(s.failureOther); 461 } 462 463 // field 464 c2_status_t status = objcpy(&(*d)->field, s.field); 465 if (status != C2_OK) { 466 return status; 467 } 468 469 // conflicts 470 (*d)->conflicts.clear(); 471 (*d)->conflicts.reserve(s.conflicts.size()); 472 for (const ParamFieldValues& sConflict : s.conflicts) { 473 (*d)->conflicts.emplace_back( 474 C2ParamFieldValues{ C2ParamFieldBuilder(), nullptr }); 475 status = objcpy(&(*d)->conflicts.back(), sConflict); 476 if (status != C2_OK) { 477 return status; 478 } 479 } 480 return C2_OK; 481 } 482 483 // C2ParamDescriptor -> ParamDescriptor 484 Status objcpy(ParamDescriptor *d, const C2ParamDescriptor &s) { 485 d->index = static_cast<ParamIndex>(s.index()); 486 d->attrib = static_cast<hidl_bitfield<ParamDescriptor::Attrib>>( 487 _C2ParamInspector::GetAttrib(s)); 488 d->name = s.name(); 489 copyVector<uint32_t>(&d->dependencies, s.dependencies()); 490 return Status::OK; 491 } 492 493 // ParamDescriptor -> C2ParamDescriptor 494 c2_status_t objcpy(std::shared_ptr<C2ParamDescriptor> *d, const ParamDescriptor &s) { 495 std::vector<C2Param::Index> dDependencies; 496 dDependencies.reserve(s.dependencies.size()); 497 for (const ParamIndex& sDependency : s.dependencies) { 498 dDependencies.emplace_back(static_cast<uint32_t>(sDependency)); 499 } 500 *d = std::make_shared<C2ParamDescriptor>( 501 C2Param::Index(static_cast<uint32_t>(s.index)), 502 static_cast<C2ParamDescriptor::attrib_t>(s.attrib), 503 C2String(s.name.c_str()), 504 std::move(dDependencies)); 505 return C2_OK; 506 } 507 508 // C2StructDescriptor -> StructDescriptor 509 Status objcpy(StructDescriptor *d, const C2StructDescriptor &s) { 510 d->type = static_cast<ParamIndex>(s.coreIndex().coreIndex()); 511 d->fields.resize(s.numFields()); 512 size_t i = 0; 513 for (const auto& sField : s) { 514 FieldDescriptor& dField = d->fields[i++]; 515 dField.fieldId.offset = static_cast<uint32_t>( 516 _C2ParamInspector::GetOffset(sField)); 517 dField.fieldId.size = static_cast<uint32_t>( 518 _C2ParamInspector::GetSize(sField)); 519 dField.type = static_cast<hidl_bitfield<FieldDescriptor::Type>>( 520 sField.type()); 521 dField.length = static_cast<uint32_t>(sField.extent()); 522 dField.name = static_cast<hidl_string>(sField.name()); 523 const auto& sNamedValues = sField.namedValues(); 524 dField.namedValues.resize(sNamedValues.size()); 525 size_t j = 0; 526 for (const auto& sNamedValue : sNamedValues) { 527 FieldDescriptor::NamedValue& dNamedValue = dField.namedValues[j++]; 528 dNamedValue.name = static_cast<hidl_string>(sNamedValue.first); 529 dNamedValue.value = static_cast<PrimitiveValue>( 530 sNamedValue.second.u64); 531 } 532 } 533 return Status::OK; 534 } 535 536 // StructDescriptor -> C2StructDescriptor 537 c2_status_t objcpy(std::unique_ptr<C2StructDescriptor> *d, const StructDescriptor &s) { 538 C2Param::CoreIndex dIndex = C2Param::CoreIndex(static_cast<uint32_t>(s.type)); 539 std::vector<C2FieldDescriptor> dFields; 540 dFields.reserve(s.fields.size()); 541 for (const auto &sField : s.fields) { 542 C2FieldDescriptor dField = { 543 static_cast<uint32_t>(sField.type), 544 sField.length, 545 sField.name, 546 sField.fieldId.offset, 547 sField.fieldId.size }; 548 C2FieldDescriptor::NamedValuesType namedValues; 549 namedValues.reserve(sField.namedValues.size()); 550 for (const auto& sNamedValue : sField.namedValues) { 551 namedValues.emplace_back( 552 sNamedValue.name, 553 C2Value::Primitive(static_cast<uint64_t>(sNamedValue.value))); 554 } 555 _C2ParamInspector::AddNamedValues(dField, std::move(namedValues)); 556 dFields.emplace_back(dField); 557 } 558 *d = std::make_unique<C2StructDescriptor>( 559 _C2ParamInspector::CreateStructDescriptor(dIndex, std::move(dFields))); 560 return C2_OK; 561 } 562 563 namespace /* unnamed */ { 564 565 // Find or add a hidl BaseBlock object from a given C2Handle* to a list and an 566 // associated map. 567 // Note: The handle is not cloned. 568 Status _addBaseBlock( 569 uint32_t* index, 570 const C2Handle* handle, 571 std::list<BaseBlock>* baseBlocks, 572 std::map<const void*, uint32_t>* baseBlockIndices) { 573 if (!handle) { 574 ALOGE("addBaseBlock called on a null C2Handle."); 575 return Status::BAD_VALUE; 576 } 577 auto it = baseBlockIndices->find(handle); 578 if (it != baseBlockIndices->end()) { 579 *index = it->second; 580 } else { 581 *index = baseBlocks->size(); 582 baseBlockIndices->emplace(handle, *index); 583 baseBlocks->emplace_back(); 584 585 BaseBlock &dBaseBlock = baseBlocks->back(); 586 dBaseBlock.type = BaseBlock::Type::NATIVE; 587 // This does not clone the handle. 588 dBaseBlock.nativeBlock = 589 reinterpret_cast<const native_handle_t*>(handle); 590 591 } 592 return Status::OK; 593 } 594 595 // Find or add a hidl BaseBlock object from a given BufferPoolData to a list and 596 // an associated map. 597 Status _addBaseBlock( 598 uint32_t* index, 599 const std::shared_ptr<BufferPoolData> bpData, 600 BufferPoolSender* bufferPoolSender, 601 std::list<BaseBlock>* baseBlocks, 602 std::map<const void*, uint32_t>* baseBlockIndices) { 603 if (!bpData) { 604 ALOGE("addBaseBlock called on a null BufferPoolData."); 605 return Status::BAD_VALUE; 606 } 607 auto it = baseBlockIndices->find(bpData.get()); 608 if (it != baseBlockIndices->end()) { 609 *index = it->second; 610 } else if (!bufferPoolSender) { 611 ALOGE("No access to the receiver's BufferPool."); 612 return Status::BAD_VALUE; 613 } else { 614 *index = baseBlocks->size(); 615 baseBlockIndices->emplace(bpData.get(), *index); 616 baseBlocks->emplace_back(); 617 618 BaseBlock &dBaseBlock = baseBlocks->back(); 619 dBaseBlock.type = BaseBlock::Type::POOLED; 620 ResultStatus bpStatus = bufferPoolSender->send( 621 bpData, 622 &dBaseBlock.pooledBlock); 623 624 if (bpStatus != ResultStatus::OK) { 625 ALOGE("Failed to send buffer with BufferPool. Error: %d.", 626 static_cast<int>(bpStatus)); 627 return Status::BAD_VALUE; 628 } 629 630 } 631 return Status::OK; 632 } 633 634 Status addBaseBlock( 635 uint32_t* index, 636 const C2Handle* handle, 637 const std::shared_ptr<const _C2BlockPoolData>& blockPoolData, 638 BufferPoolSender* bufferPoolSender, 639 std::list<BaseBlock>* baseBlocks, 640 std::map<const void*, uint32_t>* baseBlockIndices) { 641 if (!blockPoolData) { 642 // No BufferPoolData ==> NATIVE block. 643 return _addBaseBlock( 644 index, handle, 645 baseBlocks, baseBlockIndices); 646 } 647 switch (blockPoolData->getType()) { 648 case _C2BlockPoolData::TYPE_BUFFERPOOL: { 649 // BufferPoolData 650 std::shared_ptr<BufferPoolData> bpData; 651 if (!_C2BlockFactory::GetBufferPoolData(blockPoolData, &bpData) 652 || !bpData) { 653 ALOGE("BufferPoolData unavailable in a block."); 654 return Status::BAD_VALUE; 655 } 656 return _addBaseBlock( 657 index, bpData, 658 bufferPoolSender, baseBlocks, baseBlockIndices); 659 } 660 case _C2BlockPoolData::TYPE_BUFFERQUEUE: 661 // Do the same thing as a NATIVE block. 662 return _addBaseBlock( 663 index, handle, 664 baseBlocks, baseBlockIndices); 665 default: 666 ALOGE("Unknown C2BlockPoolData type."); 667 return Status::BAD_VALUE; 668 } 669 } 670 671 // C2Fence -> hidl_handle 672 // Note: File descriptors are not duplicated. The original file descriptor must 673 // not be closed before the transaction is complete. 674 Status objcpy(hidl_handle* d, const C2Fence& s) { 675 (void)s; // TODO: implement s.fd() 676 int fenceFd = -1; 677 d->setTo(nullptr); 678 if (fenceFd >= 0) { 679 native_handle_t *handle = native_handle_create(1, 0); 680 if (!handle) { 681 return Status::NO_MEMORY; 682 } 683 handle->data[0] = fenceFd; 684 d->setTo(handle, true /* owns */); 685 } 686 return Status::OK; 687 } 688 689 // C2ConstLinearBlock -> Block 690 // Note: Native handles are not duplicated. The original handles must not be 691 // closed before the transaction is complete. 692 Status objcpy(Block* d, const C2ConstLinearBlock& s, 693 BufferPoolSender* bufferPoolSender, 694 std::list<BaseBlock>* baseBlocks, 695 std::map<const void*, uint32_t>* baseBlockIndices) { 696 std::shared_ptr<const _C2BlockPoolData> bpData = 697 _C2BlockFactory::GetLinearBlockPoolData(s); 698 Status status = addBaseBlock(&d->index, s.handle(), bpData, 699 bufferPoolSender, baseBlocks, baseBlockIndices); 700 if (status != Status::OK) { 701 return status; 702 } 703 704 // Create the metadata. 705 C2Hidl_RangeInfo dRangeInfo; 706 dRangeInfo.offset = static_cast<uint32_t>(s.offset()); 707 dRangeInfo.length = static_cast<uint32_t>(s.size()); 708 status = createParamsBlob(&d->meta, 709 std::vector<C2Param*>{ &dRangeInfo }); 710 if (status != Status::OK) { 711 return Status::BAD_VALUE; 712 } 713 714 // Copy the fence 715 return objcpy(&d->fence, s.fence()); 716 } 717 718 // C2ConstGraphicBlock -> Block 719 // Note: Native handles are not duplicated. The original handles must not be 720 // closed before the transaction is complete. 721 Status objcpy(Block* d, const C2ConstGraphicBlock& s, 722 BufferPoolSender* bufferPoolSender, 723 std::list<BaseBlock>* baseBlocks, 724 std::map<const void*, uint32_t>* baseBlockIndices) { 725 std::shared_ptr<const _C2BlockPoolData> bpData = 726 _C2BlockFactory::GetGraphicBlockPoolData(s); 727 Status status = addBaseBlock(&d->index, s.handle(), bpData, 728 bufferPoolSender, baseBlocks, baseBlockIndices); 729 730 // Create the metadata. 731 C2Hidl_RectInfo dRectInfo; 732 C2Rect sRect = s.crop(); 733 dRectInfo.left = static_cast<uint32_t>(sRect.left); 734 dRectInfo.top = static_cast<uint32_t>(sRect.top); 735 dRectInfo.width = static_cast<uint32_t>(sRect.width); 736 dRectInfo.height = static_cast<uint32_t>(sRect.height); 737 status = createParamsBlob(&d->meta, 738 std::vector<C2Param*>{ &dRectInfo }); 739 if (status != Status::OK) { 740 return Status::BAD_VALUE; 741 } 742 743 // Copy the fence 744 return objcpy(&d->fence, s.fence()); 745 } 746 747 // C2BufferData -> Buffer 748 // This function only fills in d->blocks. 749 Status objcpy(Buffer* d, const C2BufferData& s, 750 BufferPoolSender* bufferPoolSender, 751 std::list<BaseBlock>* baseBlocks, 752 std::map<const void*, uint32_t>* baseBlockIndices) { 753 Status status; 754 d->blocks.resize( 755 s.linearBlocks().size() + 756 s.graphicBlocks().size()); 757 size_t i = 0; 758 for (const C2ConstLinearBlock& linearBlock : s.linearBlocks()) { 759 Block& dBlock = d->blocks[i++]; 760 status = objcpy( 761 &dBlock, linearBlock, 762 bufferPoolSender, baseBlocks, baseBlockIndices); 763 if (status != Status::OK) { 764 return status; 765 } 766 } 767 for (const C2ConstGraphicBlock& graphicBlock : s.graphicBlocks()) { 768 Block& dBlock = d->blocks[i++]; 769 status = objcpy( 770 &dBlock, graphicBlock, 771 bufferPoolSender, baseBlocks, baseBlockIndices); 772 if (status != Status::OK) { 773 return status; 774 } 775 } 776 return Status::OK; 777 } 778 779 // C2Buffer -> Buffer 780 Status objcpy(Buffer* d, const C2Buffer& s, 781 BufferPoolSender* bufferPoolSender, 782 std::list<BaseBlock>* baseBlocks, 783 std::map<const void*, uint32_t>* baseBlockIndices) { 784 Status status = createParamsBlob(&d->info, s.info()); 785 if (status != Status::OK) { 786 return status; 787 } 788 return objcpy(d, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices); 789 } 790 791 // C2InfoBuffer -> InfoBuffer 792 Status objcpy(InfoBuffer* d, const C2InfoBuffer& s, 793 BufferPoolSender* bufferPoolSender, 794 std::list<BaseBlock>* baseBlocks, 795 std::map<const void*, uint32_t>* baseBlockIndices) { 796 // TODO: C2InfoBuffer is not implemented. 797 (void)d; 798 (void)s; 799 (void)bufferPoolSender; 800 (void)baseBlocks; 801 (void)baseBlockIndices; 802 return Status::OK; 803 /* 804 // Stub implementation that may work in the future. 805 d->index = static_cast<uint32_t>(s.index()); 806 d->buffer.info.resize(0); 807 return objcpy(&d->buffer, s.data(), baseBlocks, baseBlockIndices); 808 */ 809 } 810 811 // C2FrameData -> FrameData 812 Status objcpy(FrameData* d, const C2FrameData& s, 813 BufferPoolSender* bufferPoolSender, 814 std::list<BaseBlock>* baseBlocks, 815 std::map<const void*, uint32_t>* baseBlockIndices) { 816 d->flags = static_cast<hidl_bitfield<FrameData::Flags>>(s.flags); 817 objcpy(&d->ordinal, s.ordinal); 818 819 Status status; 820 d->buffers.resize(s.buffers.size()); 821 size_t i = 0; 822 for (const std::shared_ptr<C2Buffer>& sBuffer : s.buffers) { 823 Buffer& dBuffer = d->buffers[i++]; 824 if (!sBuffer) { 825 // A null (pointer to) C2Buffer corresponds to a Buffer with empty 826 // info and blocks. 827 dBuffer.info.resize(0); 828 dBuffer.blocks.resize(0); 829 continue; 830 } 831 status = objcpy( 832 &dBuffer, *sBuffer, 833 bufferPoolSender, baseBlocks, baseBlockIndices); 834 if (status != Status::OK) { 835 return status; 836 } 837 } 838 839 status = createParamsBlob(&d->configUpdate, s.configUpdate); 840 if (status != Status::OK) { 841 return status; 842 } 843 844 d->infoBuffers.resize(s.infoBuffers.size()); 845 i = 0; 846 for (const std::shared_ptr<C2InfoBuffer>& sInfoBuffer : s.infoBuffers) { 847 InfoBuffer& dInfoBuffer = d->infoBuffers[i++]; 848 if (!sInfoBuffer) { 849 ALOGE("Null C2InfoBuffer"); 850 return Status::BAD_VALUE; 851 } 852 status = objcpy(&dInfoBuffer, *sInfoBuffer, 853 bufferPoolSender, baseBlocks, baseBlockIndices); 854 if (status != Status::OK) { 855 return status; 856 } 857 } 858 859 return status; 860 } 861 862 } // unnamed namespace 863 864 // DefaultBufferPoolSender's implementation 865 866 DefaultBufferPoolSender::DefaultBufferPoolSender( 867 const sp<IClientManager>& receiverManager) : 868 mReceiverManager(receiverManager), mSourceConnectionId(0) { 869 } 870 871 void DefaultBufferPoolSender::setReceiver(const sp<IClientManager>& receiverManager) { 872 std::lock_guard<std::mutex> lock(mMutex); 873 if (mReceiverManager != receiverManager) { 874 mReceiverManager = receiverManager; 875 } 876 } 877 878 ResultStatus DefaultBufferPoolSender::send( 879 const std::shared_ptr<BufferPoolData>& bpData, 880 BufferStatusMessage* bpMessage) { 881 if (!mReceiverManager) { 882 ALOGE("No access to receiver's BufferPool."); 883 return ResultStatus::NOT_FOUND; 884 } 885 ResultStatus rs; 886 std::lock_guard<std::mutex> lock(mMutex); 887 if (!mSenderManager) { 888 mSenderManager = ClientManager::getInstance(); 889 if (!mSenderManager) { 890 ALOGE("Failed to retrieve local BufferPool ClientManager."); 891 return ResultStatus::CRITICAL_ERROR; 892 } 893 } 894 int64_t connectionId = bpData->mConnectionId; 895 if (mSourceConnectionId == 0 || mSourceConnectionId != connectionId) { 896 // Initialize the bufferpool connection. 897 mSourceConnectionId = connectionId; 898 if (mSourceConnectionId == 0) { 899 return ResultStatus::CRITICAL_ERROR; 900 } 901 int64_t receiverConnectionId; 902 rs = mSenderManager->registerSender(mReceiverManager, connectionId, &receiverConnectionId); 903 if ((rs != ResultStatus::OK) && (rs != ResultStatus::ALREADY_EXISTS)) { 904 ALOGW("registerSender -- returned error: %d.", 905 static_cast<int>(rs)); 906 return rs; 907 } else { 908 mReceiverConnectionId = receiverConnectionId; 909 } 910 } 911 912 uint64_t transactionId; 913 int64_t timestampUs; 914 rs = mSenderManager->postSend( 915 mReceiverConnectionId, bpData, &transactionId, ×tampUs); 916 if (rs != ResultStatus::OK) { 917 ALOGE("ClientManager::postSend -- returned error: %d.", 918 static_cast<int>(rs)); 919 return rs; 920 } 921 if (!bpMessage) { 922 ALOGE("Null output parameter for BufferStatusMessage."); 923 return ResultStatus::CRITICAL_ERROR; 924 } 925 bpMessage->connectionId = mReceiverConnectionId; 926 bpMessage->bufferId = bpData->mId; 927 bpMessage->transactionId = transactionId; 928 bpMessage->timestampUs = timestampUs; 929 return rs; 930 } 931 932 // std::list<std::unique_ptr<C2Work>> -> WorkBundle 933 Status objcpy( 934 WorkBundle* d, 935 const std::list<std::unique_ptr<C2Work>>& s, 936 BufferPoolSender* bufferPoolSender) { 937 Status status = Status::OK; 938 939 // baseBlocks holds a list of BaseBlock objects that Blocks can refer to. 940 std::list<BaseBlock> baseBlocks; 941 942 // baseBlockIndices maps a raw pointer to native_handle_t or BufferPoolData 943 // inside baseBlocks to the corresponding index into baseBlocks. The keys 944 // (pointers) are used to identify blocks that have the same "base block" in 945 // s, a list of C2Work objects. Because baseBlocks will be copied into a 946 // hidl_vec eventually, the values of baseBlockIndices are zero-based 947 // integer indices instead of list iterators. 948 // 949 // Note that the pointers can be raw because baseBlockIndices has a shorter 950 // lifespan than all of base blocks. 951 std::map<const void*, uint32_t> baseBlockIndices; 952 953 d->works.resize(s.size()); 954 size_t i = 0; 955 for (const std::unique_ptr<C2Work>& sWork : s) { 956 Work &dWork = d->works[i++]; 957 if (!sWork) { 958 ALOGW("Null C2Work encountered."); 959 continue; 960 } 961 status = objcpy(&dWork.input, sWork->input, 962 bufferPoolSender, &baseBlocks, &baseBlockIndices); 963 if (status != Status::OK) { 964 return status; 965 } 966 if (sWork->worklets.size() == 0) { 967 ALOGW("Work with no worklets."); 968 } else { 969 if (sWork->worklets.size() > 1) { 970 ALOGW("Work with multiple worklets. " 971 "Only the first worklet will be marshalled."); 972 } 973 if (!sWork->worklets.front()) { 974 ALOGE("Null worklet encountered."); 975 return Status::BAD_VALUE; 976 } 977 978 // Parcel the first worklet. 979 const C2Worklet &sWorklet = *sWork->worklets.front(); 980 Worklet &dWorklet = dWork.worklet; 981 982 dWorklet.tunings.resize(sWorklet.tunings.size()); 983 size_t j = 0; 984 for (const std::unique_ptr<C2Tuning>& sTuning : sWorklet.tunings) { 985 status = createParamsBlob( 986 &dWorklet.tunings[j++], 987 std::vector<C2Param*> 988 { reinterpret_cast<C2Param*>(sTuning.get()) }); 989 if (status != Status::OK) { 990 return status; 991 } 992 } 993 994 dWorklet.failures.resize(sWorklet.failures.size()); 995 j = 0; 996 for (const std::unique_ptr<C2SettingResult>& sFailure : 997 sWorklet.failures) { 998 if (!sFailure) { 999 ALOGE("Null C2SettingResult"); 1000 return Status::BAD_VALUE; 1001 } 1002 status = objcpy(&dWorklet.failures[j++], *sFailure); 1003 if (status != Status::OK) { 1004 return status; 1005 } 1006 } 1007 1008 status = objcpy(&dWorklet.output, sWorklet.output, 1009 bufferPoolSender, &baseBlocks, &baseBlockIndices); 1010 if (status != Status::OK) { 1011 return status; 1012 } 1013 } 1014 dWork.workletProcessed = sWork->workletsProcessed > 0; 1015 dWork.result = static_cast<Status>(sWork->result); 1016 } 1017 1018 // Copy std::list<BaseBlock> to hidl_vec<BaseBlock>. 1019 { 1020 d->baseBlocks.resize(baseBlocks.size()); 1021 size_t i = 0; 1022 for (const BaseBlock& baseBlock : baseBlocks) { 1023 d->baseBlocks[i++] = baseBlock; 1024 } 1025 } 1026 1027 return Status::OK; 1028 } 1029 1030 namespace /* unnamed */ { 1031 1032 struct C2BaseBlock { 1033 enum type_t { 1034 LINEAR, 1035 GRAPHIC, 1036 }; 1037 type_t type; 1038 std::shared_ptr<C2LinearBlock> linear; 1039 std::shared_ptr<C2GraphicBlock> graphic; 1040 }; 1041 1042 // hidl_handle -> C2Fence 1043 // Note: File descriptors are not duplicated. The original file descriptor must 1044 // not be closed before the transaction is complete. 1045 c2_status_t objcpy(C2Fence* d, const hidl_handle& s) { 1046 // TODO: Implement. 1047 (void)s; 1048 *d = C2Fence(); 1049 return C2_OK; 1050 } 1051 1052 // C2LinearBlock, vector<C2Param*>, C2Fence -> C2Buffer 1053 c2_status_t createLinearBuffer( 1054 std::shared_ptr<C2Buffer>* buffer, 1055 const std::shared_ptr<C2LinearBlock>& block, 1056 const std::vector<C2Param*>& meta, 1057 const C2Fence& fence) { 1058 // Check the block meta. It should have exactly 1 C2Info: 1059 // C2Hidl_RangeInfo. 1060 if ((meta.size() != 1) || !meta[0]) { 1061 ALOGE("Invalid block metadata for ion block."); 1062 return C2_BAD_VALUE; 1063 } 1064 if (meta[0]->size() != sizeof(C2Hidl_RangeInfo)) { 1065 ALOGE("Invalid block metadata for ion block: range."); 1066 return C2_BAD_VALUE; 1067 } 1068 C2Hidl_RangeInfo *rangeInfo = 1069 reinterpret_cast<C2Hidl_RangeInfo*>(meta[0]); 1070 1071 // Create C2Buffer from C2LinearBlock. 1072 *buffer = C2Buffer::CreateLinearBuffer(block->share( 1073 rangeInfo->offset, rangeInfo->length, 1074 fence)); 1075 if (!(*buffer)) { 1076 ALOGE("Cannot create a linear buffer."); 1077 return C2_BAD_VALUE; 1078 } 1079 return C2_OK; 1080 } 1081 1082 // C2GraphicBlock, vector<C2Param*>, C2Fence -> C2Buffer 1083 c2_status_t createGraphicBuffer( 1084 std::shared_ptr<C2Buffer>* buffer, 1085 const std::shared_ptr<C2GraphicBlock>& block, 1086 const std::vector<C2Param*>& meta, 1087 const C2Fence& fence) { 1088 // Check the block meta. It should have exactly 1 C2Info: 1089 // C2Hidl_RectInfo. 1090 if ((meta.size() != 1) || !meta[0]) { 1091 ALOGE("Invalid block metadata for graphic block."); 1092 return C2_BAD_VALUE; 1093 } 1094 if (meta[0]->size() != sizeof(C2Hidl_RectInfo)) { 1095 ALOGE("Invalid block metadata for graphic block: crop rect."); 1096 return C2_BAD_VALUE; 1097 } 1098 C2Hidl_RectInfo *rectInfo = 1099 reinterpret_cast<C2Hidl_RectInfo*>(meta[0]); 1100 1101 // Create C2Buffer from C2GraphicBlock. 1102 *buffer = C2Buffer::CreateGraphicBuffer(block->share( 1103 C2Rect(rectInfo->width, rectInfo->height). 1104 at(rectInfo->left, rectInfo->top), 1105 fence)); 1106 if (!(*buffer)) { 1107 ALOGE("Cannot create a graphic buffer."); 1108 return C2_BAD_VALUE; 1109 } 1110 return C2_OK; 1111 } 1112 1113 // Buffer -> C2Buffer 1114 // Note: The native handles will be cloned. 1115 c2_status_t objcpy(std::shared_ptr<C2Buffer>* d, const Buffer& s, 1116 const std::vector<C2BaseBlock>& baseBlocks) { 1117 c2_status_t status; 1118 *d = nullptr; 1119 1120 // Currently, a non-null C2Buffer must contain exactly 1 block. 1121 if (s.blocks.size() == 0) { 1122 return C2_OK; 1123 } else if (s.blocks.size() != 1) { 1124 ALOGE("Currently, a C2Buffer must contain exactly 1 block."); 1125 return C2_BAD_VALUE; 1126 } 1127 1128 const Block &sBlock = s.blocks[0]; 1129 if (sBlock.index >= baseBlocks.size()) { 1130 ALOGE("Index into baseBlocks is out of range."); 1131 return C2_BAD_VALUE; 1132 } 1133 const C2BaseBlock &baseBlock = baseBlocks[sBlock.index]; 1134 1135 // Parse meta. 1136 std::vector<C2Param*> sBlockMeta; 1137 status = parseParamsBlob(&sBlockMeta, sBlock.meta); 1138 if (status != C2_OK) { 1139 ALOGE("Invalid block params blob."); 1140 return C2_BAD_VALUE; 1141 } 1142 1143 // Copy fence. 1144 C2Fence dFence; 1145 status = objcpy(&dFence, sBlock.fence); 1146 1147 // Construct a block. 1148 switch (baseBlock.type) { 1149 case C2BaseBlock::LINEAR: 1150 status = createLinearBuffer(d, baseBlock.linear, sBlockMeta, dFence); 1151 break; 1152 case C2BaseBlock::GRAPHIC: 1153 status = createGraphicBuffer(d, baseBlock.graphic, sBlockMeta, dFence); 1154 break; 1155 default: 1156 ALOGE("Invalid BaseBlock type."); 1157 return C2_BAD_VALUE; 1158 } 1159 if (status != C2_OK) { 1160 return status; 1161 } 1162 1163 // Parse info 1164 std::vector<C2Param*> params; 1165 status = parseParamsBlob(¶ms, s.info); 1166 if (status != C2_OK) { 1167 ALOGE("Invalid buffer params blob."); 1168 return status; 1169 } 1170 for (C2Param* param : params) { 1171 if (param == nullptr) { 1172 ALOGE("Null buffer param encountered."); 1173 return C2_BAD_VALUE; 1174 } 1175 std::shared_ptr<C2Param> c2param( 1176 C2Param::Copy(*param).release()); 1177 if (!c2param) { 1178 ALOGE("Invalid buffer param inside a blob."); 1179 return C2_BAD_VALUE; 1180 } 1181 status = (*d)->setInfo(std::static_pointer_cast<C2Info>(c2param)); 1182 if (status != C2_OK) { 1183 ALOGE("C2Buffer::setInfo failed()."); 1184 return C2_BAD_VALUE; 1185 } 1186 } 1187 1188 return C2_OK; 1189 } 1190 1191 // FrameData -> C2FrameData 1192 c2_status_t objcpy(C2FrameData* d, const FrameData& s, 1193 const std::vector<C2BaseBlock>& baseBlocks) { 1194 c2_status_t status; 1195 d->flags = static_cast<C2FrameData::flags_t>(s.flags); 1196 objcpy(&d->ordinal, s.ordinal); 1197 d->buffers.clear(); 1198 d->buffers.reserve(s.buffers.size()); 1199 for (const Buffer& sBuffer : s.buffers) { 1200 std::shared_ptr<C2Buffer> dBuffer; 1201 status = objcpy(&dBuffer, sBuffer, baseBlocks); 1202 if (status != C2_OK) { 1203 return status; 1204 } 1205 d->buffers.emplace_back(dBuffer); 1206 } 1207 1208 std::vector<C2Param*> params; 1209 status = parseParamsBlob(¶ms, s.configUpdate); 1210 if (status != C2_OK) { 1211 ALOGE("Failed to parse frame data params."); 1212 return status; 1213 } 1214 d->configUpdate.clear(); 1215 for (C2Param* param : params) { 1216 d->configUpdate.emplace_back(C2Param::Copy(*param)); 1217 if (!d->configUpdate.back()) { 1218 ALOGE("Unexpected error while parsing frame data params."); 1219 return C2_BAD_VALUE; 1220 } 1221 } 1222 1223 // TODO: Implement this once C2InfoBuffer has constructors. 1224 d->infoBuffers.clear(); 1225 return C2_OK; 1226 } 1227 1228 // BaseBlock -> C2BaseBlock 1229 c2_status_t objcpy(C2BaseBlock* d, const BaseBlock& s) { 1230 switch (s.type) { 1231 case BaseBlock::Type::NATIVE: { 1232 native_handle_t* sHandle = 1233 native_handle_clone(s.nativeBlock); 1234 if (sHandle == nullptr) { 1235 ALOGE("Null native handle in a block."); 1236 return C2_BAD_VALUE; 1237 } 1238 const C2Handle *sC2Handle = 1239 reinterpret_cast<const C2Handle*>(sHandle); 1240 1241 d->linear = _C2BlockFactory::CreateLinearBlock(sC2Handle); 1242 if (d->linear) { 1243 d->type = C2BaseBlock::LINEAR; 1244 return C2_OK; 1245 } 1246 1247 d->graphic = _C2BlockFactory::CreateGraphicBlock(sC2Handle); 1248 if (d->graphic) { 1249 d->type = C2BaseBlock::GRAPHIC; 1250 return C2_OK; 1251 } 1252 1253 ALOGE("Unknown handle type in native BaseBlock."); 1254 if (sHandle) { 1255 native_handle_close(sHandle); 1256 native_handle_delete(sHandle); 1257 } 1258 return C2_BAD_VALUE; 1259 } 1260 case BaseBlock::Type::POOLED: { 1261 const BufferStatusMessage &bpMessage = 1262 s.pooledBlock; 1263 sp<ClientManager> bp = ClientManager::getInstance(); 1264 std::shared_ptr<BufferPoolData> bpData; 1265 native_handle_t *cHandle; 1266 ResultStatus bpStatus = bp->receive( 1267 bpMessage.connectionId, 1268 bpMessage.transactionId, 1269 bpMessage.bufferId, 1270 bpMessage.timestampUs, 1271 &cHandle, 1272 &bpData); 1273 if (bpStatus != ResultStatus::OK) { 1274 ALOGE("Failed to receive buffer from bufferpool -- " 1275 "resultStatus = %d", 1276 static_cast<int>(bpStatus)); 1277 return toC2Status(bpStatus); 1278 } else if (!bpData) { 1279 ALOGE("No data in bufferpool transaction."); 1280 return C2_BAD_VALUE; 1281 } 1282 1283 d->linear = _C2BlockFactory::CreateLinearBlock(cHandle, bpData); 1284 if (d->linear) { 1285 d->type = C2BaseBlock::LINEAR; 1286 return C2_OK; 1287 } 1288 1289 d->graphic = _C2BlockFactory::CreateGraphicBlock(cHandle, bpData); 1290 if (d->graphic) { 1291 d->type = C2BaseBlock::GRAPHIC; 1292 return C2_OK; 1293 } 1294 1295 ALOGE("Unknown handle type in pooled BaseBlock."); 1296 return C2_BAD_VALUE; 1297 } 1298 default: 1299 ALOGE("Corrupted BaseBlock type: %d", static_cast<int>(s.type)); 1300 return C2_BAD_VALUE; 1301 } 1302 } 1303 1304 } // unnamed namespace 1305 1306 // WorkBundle -> std::list<std::unique_ptr<C2Work>> 1307 c2_status_t objcpy(std::list<std::unique_ptr<C2Work>>* d, const WorkBundle& s) { 1308 c2_status_t status; 1309 1310 // Convert BaseBlocks to C2BaseBlocks. 1311 std::vector<C2BaseBlock> dBaseBlocks(s.baseBlocks.size()); 1312 for (size_t i = 0; i < s.baseBlocks.size(); ++i) { 1313 status = objcpy(&dBaseBlocks[i], s.baseBlocks[i]); 1314 if (status != C2_OK) { 1315 return status; 1316 } 1317 } 1318 1319 d->clear(); 1320 for (const Work& sWork : s.works) { 1321 d->emplace_back(std::make_unique<C2Work>()); 1322 C2Work& dWork = *d->back(); 1323 1324 // input 1325 status = objcpy(&dWork.input, sWork.input, dBaseBlocks); 1326 if (status != C2_OK) { 1327 ALOGE("Error constructing C2Work's input."); 1328 return C2_BAD_VALUE; 1329 } 1330 1331 // worklet(s) 1332 dWork.worklets.clear(); 1333 // TODO: Currently, tunneling is not supported. 1334 if (sWork.workletProcessed) { 1335 dWork.workletsProcessed = 1; 1336 1337 const Worklet &sWorklet = sWork.worklet; 1338 std::unique_ptr<C2Worklet> dWorklet = std::make_unique<C2Worklet>(); 1339 1340 // tunings 1341 dWorklet->tunings.clear(); 1342 dWorklet->tunings.reserve(sWorklet.tunings.size()); 1343 for (const Params& sTuning : sWorklet.tunings) { 1344 std::vector<C2Param*> dParams; 1345 status = parseParamsBlob(&dParams, sTuning); 1346 if (status != C2_OK) { 1347 ALOGE("Failed to parse C2Tuning in C2Worklet."); 1348 return C2_BAD_VALUE; 1349 } 1350 for (C2Param* param : dParams) { 1351 std::unique_ptr<C2Param> dParam = C2Param::Copy(*param); 1352 if (!dParam) { 1353 ALOGE("Null C2Tuning encountered while " 1354 "parsing C2Worklet."); 1355 return C2_BAD_VALUE; 1356 } 1357 dWorklet->tunings.emplace_back( 1358 std::unique_ptr<C2Tuning>( 1359 reinterpret_cast<C2Tuning*>( 1360 dParam.release()))); 1361 } 1362 } 1363 // failures 1364 dWorklet->failures.clear(); 1365 dWorklet->failures.reserve(sWorklet.failures.size()); 1366 for (const SettingResult& sFailure : sWorklet.failures) { 1367 std::unique_ptr<C2SettingResult> dFailure; 1368 status = objcpy(&dFailure, sFailure); 1369 if (status != C2_OK) { 1370 ALOGE("Failed to create C2SettingResult in C2Worklet."); 1371 return C2_BAD_VALUE; 1372 } 1373 dWorklet->failures.emplace_back(std::move(dFailure)); 1374 } 1375 // output 1376 status = objcpy(&dWorklet->output, sWorklet.output, dBaseBlocks); 1377 if (status != C2_OK) { 1378 ALOGE("Failed to create output C2FrameData."); 1379 return C2_BAD_VALUE; 1380 } 1381 dWork.worklets.emplace_back(std::move(dWorklet)); 1382 } else { 1383 dWork.worklets.emplace_back(std::make_unique<C2Worklet>()); 1384 dWork.workletsProcessed = 0; 1385 } 1386 1387 // result 1388 dWork.result = static_cast<c2_status_t>(sWork.result); 1389 } 1390 1391 return C2_OK; 1392 } 1393 1394 constexpr size_t PARAMS_ALIGNMENT = 8; // 64-bit alignment 1395 static_assert(PARAMS_ALIGNMENT % alignof(C2Param) == 0, "C2Param alignment mismatch"); 1396 static_assert(PARAMS_ALIGNMENT % alignof(C2Info) == 0, "C2Param alignment mismatch"); 1397 static_assert(PARAMS_ALIGNMENT % alignof(C2Tuning) == 0, "C2Param alignment mismatch"); 1398 1399 // Params -> std::vector<C2Param*> 1400 c2_status_t parseParamsBlob(std::vector<C2Param*> *params, const hidl_vec<uint8_t> &blob) { 1401 // assuming blob is const here 1402 size_t size = blob.size(); 1403 size_t ix = 0; 1404 const uint8_t *data = blob.data(); 1405 C2Param *p = nullptr; 1406 1407 do { 1408 p = C2ParamUtils::ParseFirst(data + ix, size - ix); 1409 if (p) { 1410 params->emplace_back(p); 1411 ix += p->size(); 1412 ix = align(ix, PARAMS_ALIGNMENT); 1413 } 1414 } while (p); 1415 1416 return ix == size ? C2_OK : C2_BAD_VALUE; 1417 } 1418 1419 namespace /* unnamed */ { 1420 1421 /** 1422 * Concatenates a list of C2Params into a params blob. 1423 * \param[out] blob target blob 1424 * \param[in] params parameters to concatenate 1425 * \retval C2_OK if the blob was successfully created 1426 * \retval C2_BAD_VALUE if the blob was not successful (this only happens if the parameters were 1427 * not const) 1428 */ 1429 template<typename T> 1430 Status _createParamsBlob(hidl_vec<uint8_t> *blob, const T ¶ms) { 1431 // assuming the parameter values are const 1432 size_t size = 0; 1433 for (const auto &p : params) { 1434 if (!p) { 1435 continue; 1436 } 1437 size += p->size(); 1438 size = align(size, PARAMS_ALIGNMENT); 1439 } 1440 blob->resize(size); 1441 size_t ix = 0; 1442 for (const auto &p : params) { 1443 if (!p) { 1444 continue; 1445 } 1446 // NEVER overwrite even if param values (e.g. size) changed 1447 size_t paramSize = std::min(p->size(), size - ix); 1448 std::copy( 1449 reinterpret_cast<const uint8_t*>(&*p), 1450 reinterpret_cast<const uint8_t*>(&*p) + paramSize, 1451 &(*blob)[ix]); 1452 ix += paramSize; 1453 ix = align(ix, PARAMS_ALIGNMENT); 1454 } 1455 blob->resize(ix); 1456 return ix == size ? Status::OK : Status::CORRUPTED; 1457 } 1458 1459 } // unnamed namespace 1460 1461 // std::vector<const C2Param*> -> Params 1462 Status createParamsBlob( 1463 hidl_vec<uint8_t> *blob, 1464 const std::vector<const C2Param*> ¶ms) { 1465 return _createParamsBlob(blob, params); 1466 } 1467 1468 // std::vector<C2Param*> -> Params 1469 Status createParamsBlob( 1470 hidl_vec<uint8_t> *blob, 1471 const std::vector<C2Param*> ¶ms) { 1472 return _createParamsBlob(blob, params); 1473 } 1474 1475 // std::vector<std::unique_ptr<C2Param>> -> Params 1476 Status createParamsBlob( 1477 hidl_vec<uint8_t> *blob, 1478 const std::vector<std::unique_ptr<C2Param>> ¶ms) { 1479 return _createParamsBlob(blob, params); 1480 } 1481 1482 // std::vector<std::unique_ptr<C2Tuning>> -> Params 1483 Status createParamsBlob( 1484 hidl_vec<uint8_t> *blob, 1485 const std::vector<std::unique_ptr<C2Tuning>> ¶ms) { 1486 return _createParamsBlob(blob, params); 1487 } 1488 1489 // std::vector<std::shared_ptr<const C2Info>> -> Params 1490 Status createParamsBlob( 1491 hidl_vec<uint8_t> *blob, 1492 const std::vector<std::shared_ptr<const C2Info>> ¶ms) { 1493 return _createParamsBlob(blob, params); 1494 } 1495 1496 // Params -> std::vector<std::unique_ptr<C2Param>> 1497 c2_status_t copyParamsFromBlob( 1498 std::vector<std::unique_ptr<C2Param>>* params, 1499 Params blob) { 1500 std::vector<C2Param*> paramPointers; 1501 c2_status_t status = parseParamsBlob(¶mPointers, blob); 1502 if (status != C2_OK) { 1503 ALOGE("copyParamsFromBlob -- blob parsing failed."); 1504 return status; 1505 } 1506 params->resize(paramPointers.size()); 1507 size_t i = 0; 1508 for (C2Param* const& paramPointer : paramPointers) { 1509 if (!paramPointer) { 1510 ALOGE("copyParamsFromBlob -- corrupted params blob."); 1511 return C2_BAD_VALUE; 1512 } 1513 (*params)[i++] = C2Param::Copy(*paramPointer); 1514 } 1515 return C2_OK; 1516 } 1517 1518 // Params -> update std::vector<std::unique_ptr<C2Param>> 1519 c2_status_t updateParamsFromBlob( 1520 const std::vector<C2Param*>& params, 1521 const Params& blob) { 1522 std::unordered_map<uint32_t, C2Param*> index2param; 1523 for (C2Param* const& param : params) { 1524 if (!param) { 1525 ALOGE("updateParamsFromBlob -- corrupted input params."); 1526 return C2_BAD_VALUE; 1527 } 1528 if (index2param.find(param->index()) == index2param.end()) { 1529 index2param.emplace(param->index(), param); 1530 } 1531 } 1532 1533 std::vector<C2Param*> paramPointers; 1534 c2_status_t status = parseParamsBlob(¶mPointers, blob); 1535 if (status != C2_OK) { 1536 ALOGE("updateParamsFromBlob -- blob parsing failed."); 1537 return status; 1538 } 1539 1540 for (C2Param* const& paramPointer : paramPointers) { 1541 if (!paramPointer) { 1542 ALOGE("updateParamsFromBlob -- corrupted param in blob."); 1543 return C2_BAD_VALUE; 1544 } 1545 decltype(index2param)::iterator i = index2param.find( 1546 paramPointer->index()); 1547 if (i == index2param.end()) { 1548 ALOGW("updateParamsFromBlob -- unseen param index."); 1549 continue; 1550 } 1551 if (!i->second->updateFrom(*paramPointer)) { 1552 ALOGE("updateParamsFromBlob -- mismatching sizes: " 1553 "%u vs %u (index = %u).", 1554 static_cast<unsigned>(params.size()), 1555 static_cast<unsigned>(paramPointer->size()), 1556 static_cast<unsigned>(i->first)); 1557 return C2_BAD_VALUE; 1558 } 1559 } 1560 return C2_OK; 1561 } 1562 1563 // Convert BufferPool ResultStatus to c2_status_t. 1564 c2_status_t toC2Status(ResultStatus rs) { 1565 switch (rs) { 1566 case ResultStatus::OK: 1567 return C2_OK; 1568 case ResultStatus::NO_MEMORY: 1569 return C2_NO_MEMORY; 1570 case ResultStatus::ALREADY_EXISTS: 1571 return C2_DUPLICATE; 1572 case ResultStatus::NOT_FOUND: 1573 return C2_NOT_FOUND; 1574 case ResultStatus::CRITICAL_ERROR: 1575 return C2_CORRUPTED; 1576 default: 1577 ALOGW("Unrecognized BufferPool ResultStatus: %d", static_cast<int>(rs)); 1578 return C2_CORRUPTED; 1579 } 1580 } 1581 1582 namespace /* unnamed */ { 1583 1584 // Create a GraphicBuffer object from a graphic block. 1585 sp<GraphicBuffer> createGraphicBuffer(const C2ConstGraphicBlock& block) { 1586 uint32_t width; 1587 uint32_t height; 1588 uint32_t format; 1589 uint64_t usage; 1590 uint32_t stride; 1591 uint64_t bqId; 1592 int32_t bqSlot; 1593 _UnwrapNativeCodec2GrallocMetadata( 1594 block.handle(), &width, &height, &format, &usage, 1595 &stride, &bqId, reinterpret_cast<uint32_t*>(&bqSlot)); 1596 native_handle_t *grallocHandle = 1597 UnwrapNativeCodec2GrallocHandle(block.handle()); 1598 sp<GraphicBuffer> graphicBuffer = 1599 new GraphicBuffer(grallocHandle, 1600 GraphicBuffer::CLONE_HANDLE, 1601 width, height, format, 1602 1, usage, stride); 1603 native_handle_delete(grallocHandle); 1604 return graphicBuffer; 1605 } 1606 1607 template <typename BlockProcessor> 1608 void forEachBlock(C2FrameData& frameData, 1609 BlockProcessor process) { 1610 for (const std::shared_ptr<C2Buffer>& buffer : frameData.buffers) { 1611 if (buffer) { 1612 for (const C2ConstGraphicBlock& block : 1613 buffer->data().graphicBlocks()) { 1614 process(block); 1615 } 1616 } 1617 } 1618 } 1619 1620 template <typename BlockProcessor> 1621 void forEachBlock(const std::list<std::unique_ptr<C2Work>>& workList, 1622 BlockProcessor process, 1623 bool processInput, bool processOutput) { 1624 for (const std::unique_ptr<C2Work>& work : workList) { 1625 if (!work) { 1626 continue; 1627 } 1628 if (processInput) { 1629 forEachBlock(work->input, process); 1630 } 1631 if (processOutput) { 1632 for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) { 1633 if (worklet) { 1634 forEachBlock(worklet->output, 1635 process); 1636 } 1637 } 1638 } 1639 } 1640 } 1641 1642 sp<HGraphicBufferProducer> getHgbp(const sp<IGraphicBufferProducer>& igbp) { 1643 sp<HGraphicBufferProducer> hgbp = igbp->getHalInterface(); 1644 return hgbp ? hgbp : 1645 new TWGraphicBufferProducer<HGraphicBufferProducer>(igbp); 1646 } 1647 1648 } // unnamed namespace 1649 1650 status_t attachToBufferQueue(const C2ConstGraphicBlock& block, 1651 const sp<IGraphicBufferProducer>& igbp, 1652 uint32_t generation, 1653 int32_t* bqSlot) { 1654 if (!igbp) { 1655 ALOGW("attachToBufferQueue -- null producer."); 1656 return NO_INIT; 1657 } 1658 1659 sp<GraphicBuffer> graphicBuffer = createGraphicBuffer(block); 1660 graphicBuffer->setGenerationNumber(generation); 1661 1662 ALOGV("attachToBufferQueue -- attaching buffer: " 1663 "block dimension %ux%u, " 1664 "graphicBuffer dimension %ux%u, " 1665 "format %#x, usage %#llx, stride %u, generation %u.", 1666 static_cast<unsigned>(block.width()), 1667 static_cast<unsigned>(block.height()), 1668 static_cast<unsigned>(graphicBuffer->getWidth()), 1669 static_cast<unsigned>(graphicBuffer->getHeight()), 1670 static_cast<unsigned>(graphicBuffer->getPixelFormat()), 1671 static_cast<unsigned long long>(graphicBuffer->getUsage()), 1672 static_cast<unsigned>(graphicBuffer->getStride()), 1673 static_cast<unsigned>(graphicBuffer->getGenerationNumber())); 1674 1675 status_t result = igbp->attachBuffer(bqSlot, graphicBuffer); 1676 if (result != OK) { 1677 ALOGW("attachToBufferQueue -- attachBuffer failed. Error code = %d", 1678 static_cast<int>(result)); 1679 return false; 1680 } 1681 ALOGV("attachToBufferQueue -- attachBuffer returned slot %d", 1682 static_cast<int>(*bqSlot)); 1683 return true; 1684 } 1685 1686 bool getBufferQueueAssignment(const C2ConstGraphicBlock& block, 1687 uint64_t* bqId, 1688 int32_t* bqSlot) { 1689 return _C2BlockFactory::GetBufferQueueData( 1690 _C2BlockFactory::GetGraphicBlockPoolData(block), 1691 bqId, bqSlot); 1692 } 1693 1694 bool yieldBufferQueueBlock(const C2ConstGraphicBlock& block) { 1695 std::shared_ptr<_C2BlockPoolData> data = 1696 _C2BlockFactory::GetGraphicBlockPoolData(block); 1697 if (data && _C2BlockFactory::GetBufferQueueData(data)) { 1698 _C2BlockFactory::YieldBlockToBufferQueue(data); 1699 return true; 1700 } 1701 return false; 1702 } 1703 1704 void yieldBufferQueueBlocks( 1705 const std::list<std::unique_ptr<C2Work>>& workList, 1706 bool processInput, bool processOutput) { 1707 forEachBlock(workList, yieldBufferQueueBlock, processInput, processOutput); 1708 } 1709 1710 bool holdBufferQueueBlock(const C2ConstGraphicBlock& block, 1711 const sp<IGraphicBufferProducer>& igbp, 1712 uint64_t bqId, 1713 uint32_t generation) { 1714 std::shared_ptr<_C2BlockPoolData> data = 1715 _C2BlockFactory::GetGraphicBlockPoolData(block); 1716 if (!data) { 1717 return false; 1718 } 1719 1720 uint64_t oldId; 1721 int32_t oldSlot; 1722 // If the block is not bufferqueue-based, do nothing. 1723 if (!_C2BlockFactory::GetBufferQueueData(data, &oldId, &oldSlot) || 1724 (oldId == 0)) { 1725 return false; 1726 } 1727 1728 // If the block's bqId is the same as the desired bqId, just hold. 1729 if (oldId == bqId) { 1730 ALOGV("holdBufferQueueBlock -- import without attaching: " 1731 "bqId %llu, bqSlot %d, generation %u.", 1732 static_cast<long long unsigned>(oldId), 1733 static_cast<int>(oldSlot), 1734 static_cast<unsigned>(generation)); 1735 _C2BlockFactory::HoldBlockFromBufferQueue(data, getHgbp(igbp)); 1736 return true; 1737 } 1738 1739 // Otherwise, attach to the given igbp, which must not be null. 1740 if (!igbp) { 1741 return false; 1742 } 1743 1744 int32_t bqSlot; 1745 status_t result = attachToBufferQueue(block, igbp, generation, &bqSlot); 1746 1747 if (result != OK) { 1748 ALOGE("holdBufferQueueBlock -- fail to attach: " 1749 "target bqId %llu, generation %u.", 1750 static_cast<long long unsigned>(bqId), 1751 static_cast<unsigned>(generation)); 1752 1753 return false; 1754 } 1755 1756 ALOGV("holdBufferQueueBlock -- attached: " 1757 "bqId %llu, bqSlot %d, generation %u.", 1758 static_cast<long long unsigned>(bqId), 1759 static_cast<int>(bqSlot), 1760 static_cast<unsigned>(generation)); 1761 _C2BlockFactory::AssignBlockToBufferQueue( 1762 data, getHgbp(igbp), bqId, bqSlot, true); 1763 return true; 1764 } 1765 1766 void holdBufferQueueBlocks(const std::list<std::unique_ptr<C2Work>>& workList, 1767 const sp<IGraphicBufferProducer>& igbp, 1768 uint64_t bqId, 1769 uint32_t generation, 1770 bool forInput) { 1771 forEachBlock(workList, 1772 std::bind(holdBufferQueueBlock, 1773 std::placeholders::_1, igbp, bqId, generation), 1774 forInput, !forInput); 1775 } 1776 1777 } // namespace utils 1778 } // namespace V1_0 1779 } // namespace c2 1780 } // namespace media 1781 } // namespace google 1782 } // namespace hardware 1783 1784