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