1 /* 2 * Copyright (C) 2022 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 #pragma once 18 19 #include <aidl/android/hardware/graphics/common/BlendMode.h> 20 #include <aidl/android/hardware/graphics/common/BufferUsage.h> 21 #include <aidl/android/hardware/graphics/common/Cta861_3.h> 22 #include <aidl/android/hardware/graphics/common/Dataspace.h> 23 #include <aidl/android/hardware/graphics/common/ExtendableType.h> 24 #include <aidl/android/hardware/graphics/common/PixelFormat.h> 25 #include <aidl/android/hardware/graphics/common/PlaneLayout.h> 26 #include <aidl/android/hardware/graphics/common/PlaneLayoutComponent.h> 27 #include <aidl/android/hardware/graphics/common/Rect.h> 28 #include <aidl/android/hardware/graphics/common/Smpte2086.h> 29 #include <aidl/android/hardware/graphics/common/StandardMetadataType.h> 30 #include <aidl/android/hardware/graphics/common/XyColor.h> 31 #include <android/hardware/graphics/mapper/IMapper.h> 32 33 #include <cinttypes> 34 #include <string_view> 35 #include <type_traits> 36 #include <vector> 37 38 namespace android::hardware::graphics::mapper { 39 40 using ::aidl::android::hardware::graphics::common::BlendMode; 41 using ::aidl::android::hardware::graphics::common::BufferUsage; 42 using ::aidl::android::hardware::graphics::common::Cta861_3; 43 using ::aidl::android::hardware::graphics::common::Dataspace; 44 using ::aidl::android::hardware::graphics::common::ExtendableType; 45 using ::aidl::android::hardware::graphics::common::PixelFormat; 46 using ::aidl::android::hardware::graphics::common::PlaneLayout; 47 using ::aidl::android::hardware::graphics::common::PlaneLayoutComponent; 48 using ::aidl::android::hardware::graphics::common::Rect; 49 using ::aidl::android::hardware::graphics::common::Smpte2086; 50 using ::aidl::android::hardware::graphics::common::StandardMetadataType; 51 using ::aidl::android::hardware::graphics::common::XyColor; 52 53 class MetadataWriter { 54 private: 55 uint8_t* _Nonnull mDest; 56 size_t mSizeRemaining = 0; 57 int32_t mDesiredSize = 0; 58 reserve(size_t sizeToWrite)59 void* _Nullable reserve(size_t sizeToWrite) { 60 if (mDesiredSize < 0) { 61 // Error state 62 return nullptr; 63 } 64 if (__builtin_add_overflow(mDesiredSize, sizeToWrite, &mDesiredSize)) { 65 // Overflowed, abort writing any further data 66 mDesiredSize = -AIMAPPER_ERROR_BAD_VALUE; 67 mSizeRemaining = 0; 68 return nullptr; 69 } 70 if (sizeToWrite > mSizeRemaining) { 71 mSizeRemaining = 0; 72 return nullptr; 73 } else { 74 mSizeRemaining -= sizeToWrite; 75 uint8_t* whereToWrite = mDest; 76 mDest += sizeToWrite; 77 return whereToWrite; 78 } 79 } 80 81 public: MetadataWriter(void * _Nullable destBuffer,size_t destBufferSize)82 explicit MetadataWriter(void* _Nullable destBuffer, size_t destBufferSize) 83 : mDest(reinterpret_cast<uint8_t*>(destBuffer)), mSizeRemaining(destBufferSize) {} 84 desiredSize()85 [[nodiscard]] int32_t desiredSize() const { return mDesiredSize; } 86 87 template <typename HEADER> writeHeader()88 MetadataWriter& writeHeader() { 89 return write(HEADER::name).template write<int64_t>(HEADER::value); 90 } 91 92 template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>> write(T value)93 MetadataWriter& write(T value) { 94 auto sizeToWrite = sizeof(T); 95 if (void* dest = reserve(sizeToWrite)) { 96 memcpy(dest, &value, sizeToWrite); 97 } 98 return *this; 99 } 100 write(float value)101 MetadataWriter& write(float value) { 102 auto sizeToWrite = sizeof(float); 103 if (void* dest = reserve(sizeToWrite)) { 104 memcpy(dest, &value, sizeToWrite); 105 } 106 return *this; 107 } 108 write(const std::string_view & value)109 MetadataWriter& write(const std::string_view& value) { 110 auto sizeToWrite = value.length(); 111 write<int64_t>(sizeToWrite); 112 if (void* dest = reserve(sizeToWrite)) { 113 memcpy(dest, value.data(), sizeToWrite); 114 } 115 return *this; 116 } 117 write(const std::vector<uint8_t> & value)118 MetadataWriter& write(const std::vector<uint8_t>& value) { 119 auto sizeToWrite = value.size(); 120 write<int64_t>(sizeToWrite); 121 if (void* dest = reserve(sizeToWrite)) { 122 memcpy(dest, value.data(), sizeToWrite); 123 } 124 return *this; 125 } 126 write(const ExtendableType & value)127 MetadataWriter& write(const ExtendableType& value) { 128 return write(value.name).write(value.value); 129 } 130 write(const XyColor & value)131 MetadataWriter& write(const XyColor& value) { return write(value.x).write(value.y); } 132 }; 133 134 class MetadataReader { 135 private: 136 const uint8_t* _Nonnull mSrc; 137 size_t mSizeRemaining = 0; 138 bool mOk = true; 139 advance(size_t size)140 const void* _Nullable advance(size_t size) { 141 if (mOk && mSizeRemaining >= size) { 142 const void* buf = mSrc; 143 mSrc += size; 144 mSizeRemaining -= size; 145 return buf; 146 } 147 mOk = false; 148 return nullptr; 149 } 150 151 public: MetadataReader(const void * _Nonnull metadata,size_t metadataSize)152 explicit MetadataReader(const void* _Nonnull metadata, size_t metadataSize) 153 : mSrc(reinterpret_cast<const uint8_t*>(metadata)), mSizeRemaining(metadataSize) {} 154 remaining()155 [[nodiscard]] size_t remaining() const { return mSizeRemaining; } ok()156 [[nodiscard]] bool ok() const { return mOk; } 157 158 template <typename HEADER> checkHeader()159 MetadataReader& checkHeader() { 160 if (HEADER::name != readString()) { 161 mOk = false; 162 } 163 auto value = readInt<int64_t>(); 164 if (!value || *value != HEADER::value) { 165 mOk = false; 166 } 167 return *this; 168 } 169 170 template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>> read(T & dest)171 MetadataReader& read(T& dest) { 172 if (const void* src = advance(sizeof(T))) { 173 memcpy(&dest, src, sizeof(T)); 174 } 175 return *this; 176 } 177 read(float & dest)178 MetadataReader& read(float& dest) { 179 if (const void* src = advance(sizeof(float))) { 180 memcpy(&dest, src, sizeof(float)); 181 } 182 return *this; 183 } 184 read(std::string & dest)185 MetadataReader& read(std::string& dest) { 186 dest = readString(); 187 return *this; 188 } 189 read(ExtendableType & dest)190 MetadataReader& read(ExtendableType& dest) { 191 dest.name = readString(); 192 read(dest.value); 193 return *this; 194 } 195 read(XyColor & dest)196 MetadataReader& read(XyColor& dest) { 197 read(dest.x); 198 read(dest.y); 199 return *this; 200 } 201 202 template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>> readInt()203 [[nodiscard]] std::optional<T> readInt() { 204 auto sizeToRead = sizeof(T); 205 if (const void* src = advance(sizeof(T))) { 206 T ret; 207 memcpy(&ret, src, sizeToRead); 208 return ret; 209 } 210 return std::nullopt; 211 } 212 readString()213 [[nodiscard]] std::string_view readString() { 214 auto lengthOpt = readInt<int64_t>(); 215 if (!lengthOpt) { 216 return std::string_view{}; 217 } 218 size_t length = lengthOpt.value(); 219 if (const void* src = advance(length)) { 220 return std::string_view{reinterpret_cast<const char*>(src), length}; 221 } 222 return std::string_view{}; 223 } 224 readExtendable()225 [[nodiscard]] std::optional<ExtendableType> readExtendable() { 226 ExtendableType ret; 227 ret.name = readString(); 228 auto value = readInt<int64_t>(); 229 if (value) { 230 ret.value = value.value(); 231 return ret; 232 } else { 233 return std::nullopt; 234 } 235 } 236 readBuffer()237 [[nodiscard]] std::vector<uint8_t> readBuffer() { 238 std::vector<uint8_t> ret; 239 size_t length = readInt<int64_t>().value_or(0); 240 if (const void* src = advance(length)) { 241 ret.resize(length); 242 memcpy(ret.data(), src, length); 243 } 244 return ret; 245 } 246 }; 247 248 template <typename HEADER, typename T, class Enable = void> 249 struct MetadataValue {}; 250 251 template <typename HEADER, typename T> 252 struct MetadataValue<HEADER, T, std::enable_if_t<std::is_integral_v<T>>> { 253 [[nodiscard]] static int32_t encode(T value, void* _Nullable destBuffer, 254 size_t destBufferSize) { 255 return MetadataWriter{destBuffer, destBufferSize} 256 .template writeHeader<HEADER>() 257 .write(value) 258 .desiredSize(); 259 } 260 261 [[nodiscard]] static std::optional<T> decode(const void* _Nonnull metadata, 262 size_t metadataSize) { 263 return MetadataReader{metadata, metadataSize} 264 .template checkHeader<HEADER>() 265 .template readInt<T>(); 266 } 267 }; 268 269 template <typename HEADER, typename T> 270 struct MetadataValue<HEADER, T, std::enable_if_t<std::is_enum_v<T>>> { 271 [[nodiscard]] static int32_t encode(T value, void* _Nullable destBuffer, 272 size_t destBufferSize) { 273 return MetadataWriter{destBuffer, destBufferSize} 274 .template writeHeader<HEADER>() 275 .write(static_cast<std::underlying_type_t<T>>(value)) 276 .desiredSize(); 277 } 278 279 [[nodiscard]] static std::optional<T> decode(const void* _Nonnull metadata, 280 size_t metadataSize) { 281 std::underlying_type_t<T> temp; 282 return MetadataReader{metadata, metadataSize}.template checkHeader<HEADER>().read(temp).ok() 283 ? std::optional<T>(static_cast<T>(temp)) 284 : std::nullopt; 285 } 286 }; 287 288 template <typename HEADER> 289 struct MetadataValue<HEADER, std::string> { 290 [[nodiscard]] static int32_t encode(const std::string_view& value, void* _Nullable destBuffer, 291 size_t destBufferSize) { 292 return MetadataWriter{destBuffer, destBufferSize} 293 .template writeHeader<HEADER>() 294 .write(value) 295 .desiredSize(); 296 } 297 298 [[nodiscard]] static std::optional<std::string> decode(const void* _Nonnull metadata, 299 size_t metadataSize) { 300 auto reader = MetadataReader{metadata, metadataSize}.template checkHeader<HEADER>(); 301 auto result = reader.readString(); 302 return reader.ok() ? std::optional<std::string>{result} : std::nullopt; 303 } 304 }; 305 306 template <typename HEADER> 307 struct MetadataValue<HEADER, ExtendableType> { 308 static_assert(sizeof(int64_t) == sizeof(ExtendableType::value)); 309 310 [[nodiscard]] static int32_t encode(const ExtendableType& value, void* _Nullable destBuffer, 311 size_t destBufferSize) { 312 return MetadataWriter{destBuffer, destBufferSize} 313 .template writeHeader<HEADER>() 314 .write(value) 315 .desiredSize(); 316 } 317 318 [[nodiscard]] static std::optional<ExtendableType> decode(const void* _Nonnull metadata, 319 size_t metadataSize) { 320 return MetadataReader{metadata, metadataSize} 321 .template checkHeader<HEADER>() 322 .readExtendable(); 323 } 324 }; 325 326 template <typename HEADER> 327 struct MetadataValue<HEADER, std::vector<PlaneLayout>> { 328 [[nodiscard]] static int32_t encode(const std::vector<PlaneLayout>& values, 329 void* _Nullable destBuffer, size_t destBufferSize) { 330 MetadataWriter writer{destBuffer, destBufferSize}; 331 writer.template writeHeader<HEADER>(); 332 writer.write<int64_t>(values.size()); 333 for (const auto& value : values) { 334 writer.write<int64_t>(value.components.size()); 335 for (const auto& component : value.components) { 336 writer.write(component.type) 337 .write<int64_t>(component.offsetInBits) 338 .write<int64_t>(component.sizeInBits); 339 } 340 writer.write<int64_t>(value.offsetInBytes) 341 .write<int64_t>(value.sampleIncrementInBits) 342 .write<int64_t>(value.strideInBytes) 343 .write<int64_t>(value.widthInSamples) 344 .write<int64_t>(value.heightInSamples) 345 .write<int64_t>(value.totalSizeInBytes) 346 .write<int64_t>(value.horizontalSubsampling) 347 .write<int64_t>(value.verticalSubsampling); 348 } 349 return writer.desiredSize(); 350 } 351 352 using DecodeResult = std::optional<std::vector<PlaneLayout>>; 353 [[nodiscard]] static DecodeResult decode(const void* _Nonnull metadata, size_t metadataSize) { 354 std::vector<PlaneLayout> values; 355 MetadataReader reader{metadata, metadataSize}; 356 reader.template checkHeader<HEADER>(); 357 auto numPlanes = reader.readInt<int64_t>().value_or(0); 358 values.reserve(numPlanes); 359 for (int i = 0; i < numPlanes && reader.ok(); i++) { 360 PlaneLayout& value = values.emplace_back(); 361 auto numPlaneComponents = reader.readInt<int64_t>().value_or(0); 362 value.components.reserve(numPlaneComponents); 363 for (int j = 0; j < numPlaneComponents && reader.ok(); j++) { 364 PlaneLayoutComponent& component = value.components.emplace_back(); 365 reader.read(component.type) 366 .read<int64_t>(component.offsetInBits) 367 .read<int64_t>(component.sizeInBits); 368 } 369 reader.read<int64_t>(value.offsetInBytes) 370 .read<int64_t>(value.sampleIncrementInBits) 371 .read<int64_t>(value.strideInBytes) 372 .read<int64_t>(value.widthInSamples) 373 .read<int64_t>(value.heightInSamples) 374 .read<int64_t>(value.totalSizeInBytes) 375 .read<int64_t>(value.horizontalSubsampling) 376 .read<int64_t>(value.verticalSubsampling); 377 } 378 return reader.ok() ? DecodeResult{std::move(values)} : std::nullopt; 379 } 380 }; 381 382 template <typename HEADER> 383 struct MetadataValue<HEADER, std::vector<Rect>> { 384 [[nodiscard]] static int32_t encode(const std::vector<Rect>& value, void* _Nullable destBuffer, 385 size_t destBufferSize) { 386 MetadataWriter writer{destBuffer, destBufferSize}; 387 writer.template writeHeader<HEADER>(); 388 writer.write<int64_t>(value.size()); 389 for (auto& rect : value) { 390 writer.write<int32_t>(rect.left) 391 .write<int32_t>(rect.top) 392 .write<int32_t>(rect.right) 393 .write<int32_t>(rect.bottom); 394 } 395 return writer.desiredSize(); 396 } 397 398 using DecodeResult = std::optional<std::vector<Rect>>; 399 [[nodiscard]] static DecodeResult decode(const void* _Nonnull metadata, size_t metadataSize) { 400 MetadataReader reader{metadata, metadataSize}; 401 reader.template checkHeader<HEADER>(); 402 std::vector<Rect> value; 403 auto numRects = reader.readInt<int64_t>().value_or(0); 404 value.reserve(numRects); 405 for (int i = 0; i < numRects && reader.ok(); i++) { 406 Rect& rect = value.emplace_back(); 407 reader.read<int32_t>(rect.left) 408 .read<int32_t>(rect.top) 409 .read<int32_t>(rect.right) 410 .read<int32_t>(rect.bottom); 411 } 412 return reader.ok() ? DecodeResult{std::move(value)} : std::nullopt; 413 } 414 }; 415 416 template <typename HEADER> 417 struct MetadataValue<HEADER, std::optional<Smpte2086>> { 418 [[nodiscard]] static int32_t encode(const std::optional<Smpte2086>& optValue, 419 void* _Nullable destBuffer, size_t destBufferSize) { 420 if (optValue.has_value()) { 421 const auto& value = *optValue; 422 return MetadataWriter{destBuffer, destBufferSize} 423 .template writeHeader<HEADER>() 424 .write(value.primaryRed) 425 .write(value.primaryGreen) 426 .write(value.primaryBlue) 427 .write(value.whitePoint) 428 .write(value.maxLuminance) 429 .write(value.minLuminance) 430 .desiredSize(); 431 } else { 432 return 0; 433 } 434 } 435 436 // Double optional because the value type itself is an optional<> 437 using DecodeResult = std::optional<std::optional<Smpte2086>>; 438 [[nodiscard]] static DecodeResult decode(const void* _Nullable metadata, size_t metadataSize) { 439 std::optional<Smpte2086> optValue{std::nullopt}; 440 if (metadataSize > 0) { 441 Smpte2086 value; 442 MetadataReader reader{metadata, metadataSize}; 443 reader.template checkHeader<HEADER>(); 444 reader.read(value.primaryRed) 445 .read(value.primaryGreen) 446 .read(value.primaryBlue) 447 .read(value.whitePoint) 448 .read(value.maxLuminance) 449 .read(value.minLuminance); 450 if (reader.ok()) { 451 optValue = std::move(value); 452 } else { 453 return std::nullopt; 454 } 455 } 456 return DecodeResult{std::move(optValue)}; 457 } 458 }; 459 460 template <typename HEADER> 461 struct MetadataValue<HEADER, std::optional<Cta861_3>> { 462 [[nodiscard]] static int32_t encode(const std::optional<Cta861_3>& optValue, 463 void* _Nullable destBuffer, size_t destBufferSize) { 464 if (optValue.has_value()) { 465 const auto& value = *optValue; 466 return MetadataWriter{destBuffer, destBufferSize} 467 .template writeHeader<HEADER>() 468 .write(value.maxContentLightLevel) 469 .write(value.maxFrameAverageLightLevel) 470 .desiredSize(); 471 } else { 472 return 0; 473 } 474 } 475 476 // Double optional because the value type itself is an optional<> 477 using DecodeResult = std::optional<std::optional<Cta861_3>>; 478 [[nodiscard]] static DecodeResult decode(const void* _Nullable metadata, size_t metadataSize) { 479 std::optional<Cta861_3> optValue{std::nullopt}; 480 if (metadataSize > 0) { 481 MetadataReader reader{metadata, metadataSize}; 482 reader.template checkHeader<HEADER>(); 483 Cta861_3 value; 484 reader.read(value.maxContentLightLevel).read(value.maxFrameAverageLightLevel); 485 if (reader.ok()) { 486 optValue = std::move(value); 487 } else { 488 return std::nullopt; 489 } 490 } 491 return DecodeResult{std::move(optValue)}; 492 } 493 }; 494 495 template <typename HEADER> 496 struct MetadataValue<HEADER, std::optional<std::vector<uint8_t>>> { 497 [[nodiscard]] static int32_t encode(const std::optional<std::vector<uint8_t>>& value, 498 void* _Nullable destBuffer, size_t destBufferSize) { 499 if (!value.has_value()) { 500 return 0; 501 } 502 return MetadataWriter{destBuffer, destBufferSize} 503 .template writeHeader<HEADER>() 504 .write(*value) 505 .desiredSize(); 506 } 507 508 using DecodeResult = std::optional<std::optional<std::vector<uint8_t>>>; 509 [[nodiscard]] static DecodeResult decode(const void* _Nonnull metadata, size_t metadataSize) { 510 std::optional<std::vector<uint8_t>> optValue; 511 if (metadataSize > 0) { 512 MetadataReader reader{metadata, metadataSize}; 513 reader.template checkHeader<HEADER>(); 514 auto value = reader.readBuffer(); 515 if (reader.ok()) { 516 optValue = std::move(value); 517 } else { 518 return std::nullopt; 519 } 520 } 521 return DecodeResult{std::move(optValue)}; 522 } 523 }; 524 525 template <StandardMetadataType> 526 struct StandardMetadata {}; 527 528 #define DEFINE_TYPE(typeName, typeArg) \ 529 template <> \ 530 struct StandardMetadata<StandardMetadataType::typeName> { \ 531 using value_type = typeArg; \ 532 struct Header { \ 533 static constexpr auto name = "android.hardware.graphics.common.StandardMetadataType"; \ 534 static constexpr auto value = static_cast<int64_t>(StandardMetadataType::typeName); \ 535 }; \ 536 using value = MetadataValue<Header, value_type>; \ 537 static_assert( \ 538 StandardMetadataType::typeName == \ 539 ndk::internal::enum_values<StandardMetadataType>[static_cast<size_t>( \ 540 StandardMetadataType::typeName)], \ 541 "StandardMetadataType must have equivalent value to index"); \ 542 } 543 544 DEFINE_TYPE(BUFFER_ID, uint64_t); 545 DEFINE_TYPE(NAME, std::string); 546 DEFINE_TYPE(WIDTH, uint64_t); 547 DEFINE_TYPE(HEIGHT, uint64_t); 548 DEFINE_TYPE(LAYER_COUNT, uint64_t); 549 DEFINE_TYPE(PIXEL_FORMAT_REQUESTED, PixelFormat); 550 DEFINE_TYPE(PIXEL_FORMAT_FOURCC, uint32_t); 551 DEFINE_TYPE(PIXEL_FORMAT_MODIFIER, uint64_t); 552 DEFINE_TYPE(USAGE, BufferUsage); 553 DEFINE_TYPE(ALLOCATION_SIZE, uint64_t); 554 DEFINE_TYPE(PROTECTED_CONTENT, uint64_t); 555 DEFINE_TYPE(COMPRESSION, ExtendableType); 556 DEFINE_TYPE(INTERLACED, ExtendableType); 557 DEFINE_TYPE(CHROMA_SITING, ExtendableType); 558 DEFINE_TYPE(PLANE_LAYOUTS, std::vector<PlaneLayout>); 559 DEFINE_TYPE(CROP, std::vector<Rect>); 560 DEFINE_TYPE(DATASPACE, Dataspace); 561 DEFINE_TYPE(BLEND_MODE, BlendMode); 562 DEFINE_TYPE(SMPTE2086, std::optional<Smpte2086>); 563 DEFINE_TYPE(CTA861_3, std::optional<Cta861_3>); 564 DEFINE_TYPE(SMPTE2094_10, std::optional<std::vector<uint8_t>>); 565 DEFINE_TYPE(SMPTE2094_40, std::optional<std::vector<uint8_t>>); 566 DEFINE_TYPE(STRIDE, uint32_t); 567 568 #undef DEFINE_TYPE 569 570 #if defined(__cplusplus) && __cplusplus >= 202002L 571 572 template <typename F, std::size_t... I> 573 void invokeWithStandardMetadata(F&& f, StandardMetadataType type, std::index_sequence<I...>) { 574 // Setup the jump table, mapping from each type to a springboard that invokes the template 575 // function with the appropriate concrete type 576 using F_PTR = decltype(&f); 577 using THUNK = void (*)(F_PTR); 578 static constexpr auto jump = std::array<THUNK, sizeof...(I)>{[](F_PTR fp) { 579 constexpr StandardMetadataType type = ndk::internal::enum_values<StandardMetadataType>[I]; 580 if constexpr (type != StandardMetadataType::INVALID) { 581 (*fp)(StandardMetadata<type>{}); 582 } 583 }...}; 584 585 auto index = static_cast<size_t>(type); 586 if (index >= 0 && index < jump.size()) { 587 jump[index](&f); 588 } 589 } 590 591 template <typename F, typename StandardMetadataSequence = std::make_index_sequence< 592 ndk::internal::enum_values<StandardMetadataType>.size()>> 593 int32_t provideStandardMetadata(StandardMetadataType type, void* _Nullable destBuffer, 594 size_t destBufferSize, F&& f) { 595 int32_t retVal = -AIMAPPER_ERROR_UNSUPPORTED; 596 invokeWithStandardMetadata( 597 [&]<StandardMetadataType T>(StandardMetadata<T>) { 598 retVal = f.template operator()<T>( 599 [&](const typename StandardMetadata<T>::value_type& value) -> int32_t { 600 return StandardMetadata<T>::value::encode(value, destBuffer, 601 destBufferSize); 602 }); 603 }, 604 type, StandardMetadataSequence{}); 605 return retVal; 606 } 607 608 template <typename F, typename StandardMetadataSequence = std::make_index_sequence< 609 ndk::internal::enum_values<StandardMetadataType>.size()>> 610 AIMapper_Error applyStandardMetadata(StandardMetadataType type, const void* _Nonnull metadata, 611 size_t metadataSize, F&& f) { 612 AIMapper_Error retVal = AIMAPPER_ERROR_UNSUPPORTED; 613 invokeWithStandardMetadata( 614 [&]<StandardMetadataType T>(StandardMetadata<T>) { 615 auto value = StandardMetadata<T>::value::decode(metadata, metadataSize); 616 if (value.has_value()) { 617 retVal = f.template operator()<T>(std::move(*value)); 618 } else { 619 retVal = AIMAPPER_ERROR_BAD_VALUE; 620 } 621 }, 622 type, StandardMetadataSequence{}); 623 return retVal; 624 } 625 626 #endif 627 628 } // namespace android::hardware::graphics::mapper