mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-02 23:48:30 +00:00
Merge changes Iee37bb97,If7c549b8 am: 83ea817a8c
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2359329 Change-Id: I3b0d23d69f350fe84e41e02d51eb81d691bdb252 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -22,9 +22,9 @@ package android.hardware.graphics.common;
|
|||||||
* This is an enum that defines the common types of gralloc 4 buffer metadata. The comments for
|
* This is an enum that defines the common types of gralloc 4 buffer metadata. The comments for
|
||||||
* each enum include a description of the metadata that is associated with the type.
|
* each enum include a description of the metadata that is associated with the type.
|
||||||
*
|
*
|
||||||
* IMapper@4.x must support getting the following standard buffer metadata types, with the exception
|
* IMapper@4.x & later must support getting the following standard buffer metadata types, with the
|
||||||
* of SMPTE 2094-10 metadata. IMapper@4.x may support setting these standard buffer metadata types
|
* exception of SMPTE 2094-10 and SMPTE 2094-40 metadata. IMapper@4.x & later may support setting
|
||||||
* as well.
|
* these standard buffer metadata types as well.
|
||||||
*
|
*
|
||||||
* When encoding these StandardMetadataTypes into a byte stream, the associated MetadataType is
|
* When encoding these StandardMetadataTypes into a byte stream, the associated MetadataType is
|
||||||
* is first encoded followed by the StandardMetadataType value. The MetadataType is encoded by
|
* is first encoded followed by the StandardMetadataType value. The MetadataType is encoded by
|
||||||
|
|||||||
@@ -61,6 +61,10 @@ cc_test {
|
|||||||
srcs: [
|
srcs: [
|
||||||
"implutils/impltests.cpp",
|
"implutils/impltests.cpp",
|
||||||
],
|
],
|
||||||
|
shared_libs: [
|
||||||
|
"libgralloctypes",
|
||||||
|
"libhidlbase",
|
||||||
|
],
|
||||||
visibility: [":__subpackages__"],
|
visibility: [":__subpackages__"],
|
||||||
cpp_std: "experimental",
|
cpp_std: "experimental",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,123 +18,29 @@
|
|||||||
|
|
||||||
#include <android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h>
|
#include <android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h>
|
||||||
#include <android/hardware/graphics/mapper/utils/IMapperProvider.h>
|
#include <android/hardware/graphics/mapper/utils/IMapperProvider.h>
|
||||||
|
#include <drm/drm_fourcc.h>
|
||||||
|
#include <gralloctypes/Gralloc4.h>
|
||||||
|
#include <span>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace ::android;
|
||||||
using namespace ::android::hardware::graphics::mapper;
|
using namespace ::android::hardware::graphics::mapper;
|
||||||
using namespace ::aidl::android::hardware::graphics::common;
|
using namespace ::aidl::android::hardware::graphics::common;
|
||||||
|
namespace gralloc4 = ::android::gralloc4;
|
||||||
|
using ::android::hardware::hidl_vec;
|
||||||
|
|
||||||
// These tests are primarily interested in hitting all the different *types* that can be
|
// These tests are primarily interested in hitting all the different *types* that can be
|
||||||
// serialized/deserialized than in exhaustively testing all the StandardMetadataTypes.
|
// serialized/deserialized than in exhaustively testing all the StandardMetadataTypes.
|
||||||
// Exhaustive testing of the actual metadata types is relegated for IMapper's VTS suite
|
// Exhaustive testing of the actual metadata types is relegated for IMapper's VTS suite
|
||||||
// where meaning & correctness of values are more narrowly defined (eg, read-only values)
|
// where meaning & correctness of values are more narrowly defined (eg, read-only values)
|
||||||
|
|
||||||
TEST(Metadata, setGetBufferId) {
|
static constexpr auto HeaderSize = 69;
|
||||||
using BufferId = StandardMetadata<StandardMetadataType::BUFFER_ID>::value;
|
|
||||||
|
|
||||||
std::vector<char> buffer;
|
static std::span<uint8_t> SkipHeader(std::vector<uint8_t>& buffer) {
|
||||||
buffer.resize(12, 0);
|
return std::span<uint8_t>(buffer).subspan(HeaderSize);
|
||||||
*reinterpret_cast<int64_t*>(buffer.data()) = 42;
|
|
||||||
|
|
||||||
EXPECT_EQ(8, BufferId::encode(18, buffer.data(), 0));
|
|
||||||
EXPECT_EQ(42, *reinterpret_cast<int64_t*>(buffer.data()));
|
|
||||||
EXPECT_EQ(8, BufferId::encode(18, buffer.data(), buffer.size()));
|
|
||||||
EXPECT_EQ(18, *reinterpret_cast<int64_t*>(buffer.data()));
|
|
||||||
EXPECT_FALSE(BufferId::decode(buffer.data(), 0));
|
|
||||||
auto read = BufferId::decode(buffer.data(), buffer.size());
|
|
||||||
EXPECT_TRUE(read.has_value());
|
|
||||||
EXPECT_EQ(18, read.value_or(0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Metadata, setGetDataspace) {
|
static std::vector<PlaneLayout> fakePlaneLayouts() {
|
||||||
using DataspaceValue = StandardMetadata<StandardMetadataType::DATASPACE>::value;
|
|
||||||
using intType = std::underlying_type_t<Dataspace>;
|
|
||||||
std::vector<char> buffer;
|
|
||||||
buffer.resize(12, 0);
|
|
||||||
|
|
||||||
EXPECT_EQ(4, DataspaceValue::encode(Dataspace::BT2020, buffer.data(), 0));
|
|
||||||
EXPECT_EQ(0, *reinterpret_cast<intType*>(buffer.data()));
|
|
||||||
EXPECT_EQ(4, DataspaceValue::encode(Dataspace::BT2020, buffer.data(), buffer.size()));
|
|
||||||
EXPECT_EQ(static_cast<intType>(Dataspace::BT2020), *reinterpret_cast<intType*>(buffer.data()));
|
|
||||||
EXPECT_FALSE(DataspaceValue::decode(buffer.data(), 0));
|
|
||||||
auto read = DataspaceValue::decode(buffer.data(), buffer.size());
|
|
||||||
ASSERT_TRUE(read.has_value());
|
|
||||||
EXPECT_EQ(Dataspace::BT2020, *read);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Metadata, setGetValidName) {
|
|
||||||
using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
|
|
||||||
|
|
||||||
std::vector<char> buffer;
|
|
||||||
buffer.resize(100, 'a');
|
|
||||||
buffer[buffer.size() - 1] = '\0';
|
|
||||||
|
|
||||||
// len("Hello") + sizeof(int64)
|
|
||||||
constexpr int expectedSize = 5 + sizeof(int64_t);
|
|
||||||
EXPECT_EQ(expectedSize, NameValue::encode("Hello", buffer.data(), buffer.size()));
|
|
||||||
EXPECT_EQ(5, *reinterpret_cast<int64_t*>(buffer.data()));
|
|
||||||
// Verify didn't write past the end of the desired size
|
|
||||||
EXPECT_EQ('a', buffer[expectedSize]);
|
|
||||||
|
|
||||||
auto readValue = NameValue::decode(buffer.data(), buffer.size());
|
|
||||||
ASSERT_TRUE(readValue.has_value());
|
|
||||||
EXPECT_EQ(5, readValue->length());
|
|
||||||
EXPECT_EQ("Hello", *readValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Metadata, setGetInvalidName) {
|
|
||||||
using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
|
|
||||||
|
|
||||||
std::vector<char> buffer;
|
|
||||||
buffer.resize(12, 'a');
|
|
||||||
buffer[buffer.size() - 1] = '\0';
|
|
||||||
|
|
||||||
// len("This is a long string") + sizeof(int64)
|
|
||||||
constexpr int expectedSize = 21 + sizeof(int64_t);
|
|
||||||
EXPECT_EQ(expectedSize,
|
|
||||||
NameValue::encode("This is a long string", buffer.data(), buffer.size()));
|
|
||||||
EXPECT_EQ(21, *reinterpret_cast<int64_t*>(buffer.data()));
|
|
||||||
// Verify didn't write the too-long string
|
|
||||||
EXPECT_EQ('a', buffer[9]);
|
|
||||||
EXPECT_EQ('\0', buffer[buffer.size() - 1]);
|
|
||||||
|
|
||||||
auto readValue = NameValue::decode(buffer.data(), buffer.size());
|
|
||||||
EXPECT_FALSE(readValue.has_value());
|
|
||||||
readValue = NameValue::decode(buffer.data(), 0);
|
|
||||||
ASSERT_FALSE(readValue.has_value());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Metadata, wouldOverflowName) {
|
|
||||||
using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
|
|
||||||
std::vector<char> buffer(100, 0);
|
|
||||||
|
|
||||||
// int_max + sizeof(int64) overflows int32
|
|
||||||
std::string_view bad_string{"badbeef", std::numeric_limits<int32_t>::max()};
|
|
||||||
EXPECT_EQ(-AIMAPPER_ERROR_BAD_VALUE,
|
|
||||||
NameValue::encode(bad_string, buffer.data(), buffer.size()));
|
|
||||||
|
|
||||||
// check barely overflows
|
|
||||||
bad_string = std::string_view{"badbeef", std::numeric_limits<int32_t>::max() - 7};
|
|
||||||
EXPECT_EQ(-AIMAPPER_ERROR_BAD_VALUE,
|
|
||||||
NameValue::encode(bad_string, buffer.data(), buffer.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Metadata, setGetCompression) {
|
|
||||||
using CompressionValue = StandardMetadata<StandardMetadataType::COMPRESSION>::value;
|
|
||||||
ExtendableType myCompression{"bestest_compression_ever", 42};
|
|
||||||
std::vector<char> buffer(100, '\0');
|
|
||||||
const int expectedSize = myCompression.name.length() + sizeof(int64_t) + sizeof(int64_t);
|
|
||||||
EXPECT_EQ(expectedSize, CompressionValue::encode(myCompression, buffer.data(), 0));
|
|
||||||
EXPECT_EQ(0, buffer[0]);
|
|
||||||
EXPECT_EQ(expectedSize, CompressionValue::encode(myCompression, buffer.data(), buffer.size()));
|
|
||||||
EXPECT_EQ(myCompression.name.length(), *reinterpret_cast<int64_t*>(buffer.data()));
|
|
||||||
EXPECT_FALSE(CompressionValue::decode(buffer.data(), 0).has_value());
|
|
||||||
auto read = CompressionValue::decode(buffer.data(), buffer.size());
|
|
||||||
ASSERT_TRUE(read.has_value());
|
|
||||||
EXPECT_EQ(myCompression, read.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Metadata, setGetPlaneLayout) {
|
|
||||||
using PlaneLayoutValue = StandardMetadata<StandardMetadataType::PLANE_LAYOUTS>::value;
|
|
||||||
PlaneLayout myPlaneLayout;
|
PlaneLayout myPlaneLayout;
|
||||||
myPlaneLayout.offsetInBytes = 10;
|
myPlaneLayout.offsetInBytes = 10;
|
||||||
myPlaneLayout.sampleIncrementInBits = 11;
|
myPlaneLayout.sampleIncrementInBits = 11;
|
||||||
@@ -153,23 +59,147 @@ TEST(Metadata, setGetPlaneLayout) {
|
|||||||
it.sizeInBits = 30 + i;
|
it.sizeInBits = 30 + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<PlaneLayout> layouts{myPlaneLayout, PlaneLayout{}};
|
return std::vector<PlaneLayout>{myPlaneLayout, PlaneLayout{}};
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<char> buffer(5000, '\0');
|
TEST(Metadata, setGetBufferId) {
|
||||||
|
using BufferId = StandardMetadata<StandardMetadataType::BUFFER_ID>::value;
|
||||||
|
|
||||||
|
std::vector<uint8_t> buffer(10000, 0);
|
||||||
|
int64_t* payload = reinterpret_cast<int64_t*>(SkipHeader(buffer).data());
|
||||||
|
*payload = 42;
|
||||||
|
|
||||||
|
EXPECT_EQ(8 + HeaderSize, BufferId::encode(18, buffer.data(), 0));
|
||||||
|
EXPECT_EQ(42, *payload);
|
||||||
|
EXPECT_EQ(8 + HeaderSize, BufferId::encode(18, buffer.data(), buffer.size()));
|
||||||
|
EXPECT_EQ(18, *payload);
|
||||||
|
EXPECT_FALSE(BufferId::decode(buffer.data(), 0));
|
||||||
|
auto read = BufferId::decode(buffer.data(), buffer.size());
|
||||||
|
EXPECT_TRUE(read.has_value());
|
||||||
|
EXPECT_EQ(18, read.value_or(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Metadata, setGetDataspace) {
|
||||||
|
using DataspaceValue = StandardMetadata<StandardMetadataType::DATASPACE>::value;
|
||||||
|
using intType = std::underlying_type_t<Dataspace>;
|
||||||
|
std::vector<uint8_t> buffer(10000, 0);
|
||||||
|
auto data = SkipHeader(buffer);
|
||||||
|
|
||||||
|
EXPECT_EQ(4 + HeaderSize, DataspaceValue::encode(Dataspace::BT2020, buffer.data(), 0));
|
||||||
|
EXPECT_EQ(0, *reinterpret_cast<intType*>(data.data()));
|
||||||
|
EXPECT_EQ(4 + HeaderSize,
|
||||||
|
DataspaceValue::encode(Dataspace::BT2020, buffer.data(), buffer.size()));
|
||||||
|
EXPECT_EQ(static_cast<intType>(Dataspace::BT2020), *reinterpret_cast<intType*>(data.data()));
|
||||||
|
EXPECT_FALSE(DataspaceValue::decode(buffer.data(), 0));
|
||||||
|
auto read = DataspaceValue::decode(buffer.data(), buffer.size());
|
||||||
|
ASSERT_TRUE(read.has_value());
|
||||||
|
EXPECT_EQ(Dataspace::BT2020, *read);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Metadata, setGetValidName) {
|
||||||
|
using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
|
||||||
|
|
||||||
|
std::vector<uint8_t> buffer(10000, 'a');
|
||||||
|
|
||||||
|
// len("Hello") + sizeof(int64)
|
||||||
|
constexpr int expectedSize = 5 + sizeof(int64_t) + HeaderSize;
|
||||||
|
EXPECT_EQ(expectedSize, NameValue::encode("Hello", buffer.data(), buffer.size()));
|
||||||
|
EXPECT_EQ(5, *reinterpret_cast<int64_t*>(SkipHeader(buffer).data()));
|
||||||
|
// Verify didn't write past the end of the desired size
|
||||||
|
EXPECT_EQ('a', buffer[expectedSize]);
|
||||||
|
|
||||||
|
auto readValue = NameValue::decode(buffer.data(), buffer.size());
|
||||||
|
ASSERT_TRUE(readValue.has_value());
|
||||||
|
EXPECT_EQ(5, readValue->length());
|
||||||
|
EXPECT_EQ("Hello", *readValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Metadata, setGetInvalidName) {
|
||||||
|
using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
|
||||||
|
|
||||||
|
std::vector<uint8_t> buffer;
|
||||||
|
buffer.resize(12 + HeaderSize, 'a');
|
||||||
|
buffer[buffer.size() - 1] = '\0';
|
||||||
|
|
||||||
|
// len("This is a long string") + sizeof(int64)
|
||||||
|
constexpr int expectedSize = 21 + sizeof(int64_t) + HeaderSize;
|
||||||
|
EXPECT_EQ(expectedSize,
|
||||||
|
NameValue::encode("This is a long string", buffer.data(), buffer.size()));
|
||||||
|
EXPECT_EQ(21, *reinterpret_cast<int64_t*>(SkipHeader(buffer).data()));
|
||||||
|
|
||||||
|
auto readValue = NameValue::decode(buffer.data(), buffer.size());
|
||||||
|
EXPECT_FALSE(readValue.has_value());
|
||||||
|
readValue = NameValue::decode(buffer.data(), 0);
|
||||||
|
ASSERT_FALSE(readValue.has_value());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Metadata, wouldOverflowName) {
|
||||||
|
using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
|
||||||
|
std::vector<uint8_t> buffer(10000, 0);
|
||||||
|
|
||||||
|
// int_max + sizeof(int64) overflows int32
|
||||||
|
std::string_view bad_string{"badbeef", std::numeric_limits<int32_t>::max()};
|
||||||
|
EXPECT_EQ(-AIMAPPER_ERROR_BAD_VALUE,
|
||||||
|
NameValue::encode(bad_string, buffer.data(), buffer.size()));
|
||||||
|
|
||||||
|
// check barely overflows
|
||||||
|
bad_string = std::string_view{"badbeef", std::numeric_limits<int32_t>::max() - 7};
|
||||||
|
EXPECT_EQ(-AIMAPPER_ERROR_BAD_VALUE,
|
||||||
|
NameValue::encode(bad_string, buffer.data(), buffer.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Metadata, setGetMismatchedWidthHight) {
|
||||||
|
// Validates that the header is properly validated on decode
|
||||||
|
using WidthValue = StandardMetadata<StandardMetadataType::WIDTH>::value;
|
||||||
|
using HeightValue = StandardMetadata<StandardMetadataType::HEIGHT>::value;
|
||||||
|
std::vector<uint8_t> buffer(10000, 0);
|
||||||
|
|
||||||
|
EXPECT_EQ(8 + HeaderSize, WidthValue::encode(100, buffer.data(), buffer.size()));
|
||||||
|
EXPECT_EQ(100, *reinterpret_cast<uint64_t*>(SkipHeader(buffer).data()));
|
||||||
|
auto read = WidthValue::decode(buffer.data(), buffer.size());
|
||||||
|
ASSERT_TRUE(read.has_value());
|
||||||
|
EXPECT_EQ(100, *read);
|
||||||
|
read = HeightValue::decode(buffer.data(), buffer.size());
|
||||||
|
EXPECT_FALSE(read.has_value());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Metadata, setGetCompression) {
|
||||||
|
using CompressionValue = StandardMetadata<StandardMetadataType::COMPRESSION>::value;
|
||||||
|
ExtendableType myCompression{"bestest_compression_ever", 42};
|
||||||
|
std::vector<uint8_t> buffer(10000, 0);
|
||||||
|
const int expectedSize =
|
||||||
|
myCompression.name.length() + sizeof(int64_t) + sizeof(int64_t) + HeaderSize;
|
||||||
|
EXPECT_EQ(expectedSize, CompressionValue::encode(myCompression, buffer.data(), 0));
|
||||||
|
EXPECT_EQ(0, buffer[0]);
|
||||||
|
EXPECT_EQ(expectedSize, CompressionValue::encode(myCompression, buffer.data(), buffer.size()));
|
||||||
|
EXPECT_EQ(myCompression.name.length(), *reinterpret_cast<int64_t*>(SkipHeader(buffer).data()));
|
||||||
|
EXPECT_FALSE(CompressionValue::decode(buffer.data(), 0).has_value());
|
||||||
|
auto read = CompressionValue::decode(buffer.data(), buffer.size());
|
||||||
|
ASSERT_TRUE(read.has_value());
|
||||||
|
EXPECT_EQ(myCompression, read.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Metadata, setGetPlaneLayout) {
|
||||||
|
using PlaneLayoutValue = StandardMetadata<StandardMetadataType::PLANE_LAYOUTS>::value;
|
||||||
|
|
||||||
|
std::vector<PlaneLayout> layouts = fakePlaneLayouts();
|
||||||
|
|
||||||
|
std::vector<uint8_t> buffer(10000, 0);
|
||||||
constexpr int componentSize = 8 + (4 * sizeof(int64_t));
|
constexpr int componentSize = 8 + (4 * sizeof(int64_t));
|
||||||
constexpr int firstLayoutSize = (8 + 1) * sizeof(int64_t) + (3 * componentSize);
|
constexpr int firstLayoutSize = (8 + 1) * sizeof(int64_t) + (3 * componentSize);
|
||||||
constexpr int secondLayoutSize = (8 + 1) * sizeof(int64_t);
|
constexpr int secondLayoutSize = (8 + 1) * sizeof(int64_t);
|
||||||
constexpr int expectedSize = firstLayoutSize + secondLayoutSize + sizeof(int64_t);
|
constexpr int expectedSize = firstLayoutSize + secondLayoutSize + sizeof(int64_t) + HeaderSize;
|
||||||
EXPECT_EQ(expectedSize, PlaneLayoutValue::encode(layouts, buffer.data(), 0));
|
EXPECT_EQ(expectedSize, PlaneLayoutValue::encode(layouts, buffer.data(), 0));
|
||||||
EXPECT_EQ(0, buffer[0]);
|
EXPECT_EQ(0, buffer[0]);
|
||||||
EXPECT_EQ(expectedSize, PlaneLayoutValue::encode(layouts, buffer.data(), buffer.size()));
|
EXPECT_EQ(expectedSize, PlaneLayoutValue::encode(layouts, buffer.data(), buffer.size()));
|
||||||
EXPECT_EQ(3, reinterpret_cast<int64_t*>(buffer.data())[1]);
|
int64_t* payload = reinterpret_cast<int64_t*>(SkipHeader(buffer).data());
|
||||||
EXPECT_EQ(8, reinterpret_cast<int64_t*>(buffer.data())[2]);
|
EXPECT_EQ(3, payload[1]);
|
||||||
EXPECT_EQ(40, reinterpret_cast<int64_t*>(buffer.data())[4]);
|
EXPECT_EQ(8, payload[2]);
|
||||||
EXPECT_EQ(31, reinterpret_cast<int64_t*>(buffer.data())[11]);
|
EXPECT_EQ(40, payload[4]);
|
||||||
EXPECT_EQ(22, reinterpret_cast<int64_t*>(buffer.data())[15]);
|
EXPECT_EQ(31, payload[11]);
|
||||||
EXPECT_EQ(10, reinterpret_cast<int64_t*>(buffer.data())[17]);
|
EXPECT_EQ(22, payload[15]);
|
||||||
EXPECT_EQ(11, reinterpret_cast<int64_t*>(buffer.data())[18]);
|
EXPECT_EQ(10, payload[17]);
|
||||||
|
EXPECT_EQ(11, payload[18]);
|
||||||
EXPECT_FALSE(PlaneLayoutValue::decode(buffer.data(), 0).has_value());
|
EXPECT_FALSE(PlaneLayoutValue::decode(buffer.data(), 0).has_value());
|
||||||
auto read = PlaneLayoutValue::decode(buffer.data(), buffer.size());
|
auto read = PlaneLayoutValue::decode(buffer.data(), buffer.size());
|
||||||
ASSERT_TRUE(read.has_value());
|
ASSERT_TRUE(read.has_value());
|
||||||
@@ -178,15 +208,15 @@ TEST(Metadata, setGetPlaneLayout) {
|
|||||||
|
|
||||||
TEST(Metadata, setGetRects) {
|
TEST(Metadata, setGetRects) {
|
||||||
using RectsValue = StandardMetadata<StandardMetadataType::CROP>::value;
|
using RectsValue = StandardMetadata<StandardMetadataType::CROP>::value;
|
||||||
std::vector<uint8_t> buffer(500, 0);
|
std::vector<uint8_t> buffer(10000, 0);
|
||||||
std::vector<Rect> cropRects{2};
|
std::vector<Rect> cropRects{2};
|
||||||
cropRects[0] = Rect{10, 11, 12, 13};
|
cropRects[0] = Rect{10, 11, 12, 13};
|
||||||
cropRects[1] = Rect{20, 21, 22, 23};
|
cropRects[1] = Rect{20, 21, 22, 23};
|
||||||
|
|
||||||
constexpr int expectedSize = sizeof(int64_t) + (8 * sizeof(int32_t));
|
constexpr int expectedSize = sizeof(int64_t) + (8 * sizeof(int32_t)) + HeaderSize;
|
||||||
EXPECT_EQ(expectedSize, RectsValue::encode(cropRects, buffer.data(), buffer.size()));
|
EXPECT_EQ(expectedSize, RectsValue::encode(cropRects, buffer.data(), buffer.size()));
|
||||||
EXPECT_EQ(2, reinterpret_cast<int64_t*>(buffer.data())[0]);
|
EXPECT_EQ(2, reinterpret_cast<int64_t*>(SkipHeader(buffer).data())[0]);
|
||||||
EXPECT_EQ(10, reinterpret_cast<int32_t*>(buffer.data())[2]);
|
EXPECT_EQ(10, reinterpret_cast<int32_t*>(SkipHeader(buffer).data())[2]);
|
||||||
auto read = RectsValue::decode(buffer.data(), buffer.size());
|
auto read = RectsValue::decode(buffer.data(), buffer.size());
|
||||||
ASSERT_TRUE(read.has_value());
|
ASSERT_TRUE(read.has_value());
|
||||||
EXPECT_EQ(cropRects.size(), read->size());
|
EXPECT_EQ(cropRects.size(), read->size());
|
||||||
@@ -203,8 +233,8 @@ TEST(Metadata, setGetSmpte2086) {
|
|||||||
source.primaryGreen = XyColor{.3f, .4f};
|
source.primaryGreen = XyColor{.3f, .4f};
|
||||||
source.primaryBlue = XyColor{.5f, .6f};
|
source.primaryBlue = XyColor{.5f, .6f};
|
||||||
|
|
||||||
constexpr int expectedSize = 10 * sizeof(float);
|
constexpr int expectedSize = 10 * sizeof(float) + HeaderSize;
|
||||||
std::vector<uint8_t> buffer(500, 0);
|
std::vector<uint8_t> buffer(10000, 0);
|
||||||
EXPECT_EQ(expectedSize, Smpte2086Value::encode(source, buffer.data(), buffer.size()));
|
EXPECT_EQ(expectedSize, Smpte2086Value::encode(source, buffer.data(), buffer.size()));
|
||||||
auto read = Smpte2086Value::decode(buffer.data(), buffer.size());
|
auto read = Smpte2086Value::decode(buffer.data(), buffer.size());
|
||||||
ASSERT_TRUE(read.has_value());
|
ASSERT_TRUE(read.has_value());
|
||||||
@@ -223,8 +253,8 @@ TEST(Metadata, setGetCta861_3) {
|
|||||||
source.maxFrameAverageLightLevel = 244.55f;
|
source.maxFrameAverageLightLevel = 244.55f;
|
||||||
source.maxContentLightLevel = 202.202f;
|
source.maxContentLightLevel = 202.202f;
|
||||||
|
|
||||||
constexpr int expectedSize = 2 * sizeof(float);
|
constexpr int expectedSize = 2 * sizeof(float) + HeaderSize;
|
||||||
std::vector<uint8_t> buffer(500, 0);
|
std::vector<uint8_t> buffer(10000, 0);
|
||||||
EXPECT_EQ(expectedSize, Cta861_3Value::encode(source, buffer.data(), buffer.size()));
|
EXPECT_EQ(expectedSize, Cta861_3Value::encode(source, buffer.data(), buffer.size()));
|
||||||
auto read = Cta861_3Value::decode(buffer.data(), buffer.size());
|
auto read = Cta861_3Value::decode(buffer.data(), buffer.size());
|
||||||
ASSERT_TRUE(read.has_value());
|
ASSERT_TRUE(read.has_value());
|
||||||
@@ -240,14 +270,14 @@ TEST(Metadata, setGetCta861_3) {
|
|||||||
TEST(Metadata, setGetSmpte2094_10) {
|
TEST(Metadata, setGetSmpte2094_10) {
|
||||||
using SMPTE2094_10Value = StandardMetadata<StandardMetadataType::SMPTE2094_10>::value;
|
using SMPTE2094_10Value = StandardMetadata<StandardMetadataType::SMPTE2094_10>::value;
|
||||||
|
|
||||||
std::vector<uint8_t> buffer(500, 0);
|
std::vector<uint8_t> buffer(10000, 0);
|
||||||
EXPECT_EQ(0, SMPTE2094_10Value::encode(std::nullopt, buffer.data(), buffer.size()));
|
EXPECT_EQ(0, SMPTE2094_10Value::encode(std::nullopt, buffer.data(), buffer.size()));
|
||||||
auto read = SMPTE2094_10Value::decode(buffer.data(), 0);
|
auto read = SMPTE2094_10Value::decode(buffer.data(), 0);
|
||||||
ASSERT_TRUE(read.has_value());
|
ASSERT_TRUE(read.has_value());
|
||||||
EXPECT_FALSE(read->has_value());
|
EXPECT_FALSE(read->has_value());
|
||||||
|
|
||||||
const std::vector<uint8_t> emptyBuffer;
|
const std::vector<uint8_t> emptyBuffer;
|
||||||
EXPECT_EQ(sizeof(int64_t),
|
EXPECT_EQ(sizeof(int64_t) + HeaderSize,
|
||||||
SMPTE2094_10Value::encode(emptyBuffer, buffer.data(), buffer.size()));
|
SMPTE2094_10Value::encode(emptyBuffer, buffer.data(), buffer.size()));
|
||||||
read = SMPTE2094_10Value::decode(buffer.data(), buffer.size());
|
read = SMPTE2094_10Value::decode(buffer.data(), buffer.size());
|
||||||
ASSERT_TRUE(read.has_value());
|
ASSERT_TRUE(read.has_value());
|
||||||
@@ -255,7 +285,7 @@ TEST(Metadata, setGetSmpte2094_10) {
|
|||||||
EXPECT_EQ(0, read->value().size());
|
EXPECT_EQ(0, read->value().size());
|
||||||
|
|
||||||
const std::vector<uint8_t> simpleBuffer{0, 1, 2, 3, 4, 5};
|
const std::vector<uint8_t> simpleBuffer{0, 1, 2, 3, 4, 5};
|
||||||
EXPECT_EQ(sizeof(int64_t) + 6,
|
EXPECT_EQ(sizeof(int64_t) + 6 + HeaderSize,
|
||||||
SMPTE2094_10Value::encode(simpleBuffer, buffer.data(), buffer.size()));
|
SMPTE2094_10Value::encode(simpleBuffer, buffer.data(), buffer.size()));
|
||||||
read = SMPTE2094_10Value::decode(buffer.data(), buffer.size());
|
read = SMPTE2094_10Value::decode(buffer.data(), buffer.size());
|
||||||
ASSERT_TRUE(read.has_value());
|
ASSERT_TRUE(read.has_value());
|
||||||
@@ -266,7 +296,7 @@ TEST(Metadata, setGetSmpte2094_10) {
|
|||||||
|
|
||||||
TEST(MetadataProvider, bufferId) {
|
TEST(MetadataProvider, bufferId) {
|
||||||
using BufferId = StandardMetadata<StandardMetadataType::BUFFER_ID>::value;
|
using BufferId = StandardMetadata<StandardMetadataType::BUFFER_ID>::value;
|
||||||
std::vector<uint8_t> buffer(500, 0);
|
std::vector<uint8_t> buffer(10000, 0);
|
||||||
int result = provideStandardMetadata(StandardMetadataType::BUFFER_ID, buffer.data(),
|
int result = provideStandardMetadata(StandardMetadataType::BUFFER_ID, buffer.data(),
|
||||||
buffer.size(), []<StandardMetadataType T>(auto&& provide) {
|
buffer.size(), []<StandardMetadataType T>(auto&& provide) {
|
||||||
if constexpr (T == StandardMetadataType::BUFFER_ID) {
|
if constexpr (T == StandardMetadataType::BUFFER_ID) {
|
||||||
@@ -275,7 +305,7 @@ TEST(MetadataProvider, bufferId) {
|
|||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXPECT_EQ(8, result);
|
EXPECT_EQ(8 + HeaderSize, result);
|
||||||
auto read = BufferId::decode(buffer.data(), buffer.size());
|
auto read = BufferId::decode(buffer.data(), buffer.size());
|
||||||
EXPECT_EQ(42, read.value_or(0));
|
EXPECT_EQ(42, read.value_or(0));
|
||||||
}
|
}
|
||||||
@@ -312,3 +342,193 @@ TEST(MetadataProvider, outOfBounds) {
|
|||||||
EXPECT_EQ(-AIMAPPER_ERROR_UNSUPPORTED, result)
|
EXPECT_EQ(-AIMAPPER_ERROR_UNSUPPORTED, result)
|
||||||
<< "100 (out of range) should have resulted in UNSUPPORTED";
|
<< "100 (out of range) should have resulted in UNSUPPORTED";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <StandardMetadataType T>
|
||||||
|
std::vector<uint8_t> encode(const typename StandardMetadata<T>::value_type& value) {
|
||||||
|
using Value = typename StandardMetadata<T>::value;
|
||||||
|
|
||||||
|
int desiredSize = Value::encode(value, nullptr, 0);
|
||||||
|
EXPECT_GE(desiredSize, 0);
|
||||||
|
std::vector<uint8_t> buffer;
|
||||||
|
buffer.resize(desiredSize);
|
||||||
|
EXPECT_EQ(desiredSize, Value::encode(value, buffer.data(), buffer.size()));
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, BufferId) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::BUFFER_ID>(42);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodeBufferId(42, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, Name) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::NAME>("Hello, Interop!");
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodeName("Hello, Interop!", &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, Width) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::WIDTH>(128);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodeWidth(128, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, Height) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::HEIGHT>(64);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodeHeight(64, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, LayerCount) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::LAYER_COUNT>(3);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodeLayerCount(3, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, PixelFormatRequested) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::PIXEL_FORMAT_REQUESTED>(PixelFormat::RGBX_8888);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodePixelFormatRequested(
|
||||||
|
hardware::graphics::common::V1_2::PixelFormat::RGBX_8888, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, PixelFormatFourcc) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::PIXEL_FORMAT_FOURCC>(DRM_FORMAT_ABGR8888);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodePixelFormatFourCC(DRM_FORMAT_ABGR8888, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, PixelFormatModifier) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::PIXEL_FORMAT_MODIFIER>(123456);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodePixelFormatModifier(123456, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, Usage) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::USAGE>(BufferUsage::COMPOSER_OVERLAY);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR,
|
||||||
|
gralloc4::encodeUsage(
|
||||||
|
static_cast<uint64_t>(
|
||||||
|
hardware::graphics::common::V1_2::BufferUsage::COMPOSER_OVERLAY),
|
||||||
|
&g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, AllocationSize) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::ALLOCATION_SIZE>(10200);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodeAllocationSize(10200, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, ProtectedContent) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::PROTECTED_CONTENT>(1);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodeProtectedContent(1, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, Compression) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::COMPRESSION>(
|
||||||
|
gralloc4::Compression_DisplayStreamCompression);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR,
|
||||||
|
gralloc4::encodeCompression(gralloc4::Compression_DisplayStreamCompression, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, Interlaced) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::INTERLACED>(gralloc4::Interlaced_TopBottom);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodeInterlaced(gralloc4::Interlaced_TopBottom, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, ChromeSitting) {
|
||||||
|
auto mpbuf =
|
||||||
|
encode<StandardMetadataType::CHROMA_SITING>(gralloc4::ChromaSiting_SitedInterstitial);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR,
|
||||||
|
gralloc4::encodeChromaSiting(gralloc4::ChromaSiting_SitedInterstitial, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, PlaneLayouts) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::PLANE_LAYOUTS>(fakePlaneLayouts());
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodePlaneLayouts(fakePlaneLayouts(), &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, Crop) {
|
||||||
|
std::vector<Rect> cropRects{Rect{10, 11, 12, 13}, Rect{20, 21, 22, 23}};
|
||||||
|
auto mpbuf = encode<StandardMetadataType::CROP>(cropRects);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodeCrop(cropRects, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, Dataspace) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::DATASPACE>(Dataspace::DISPLAY_P3);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(Dataspace::DISPLAY_P3, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, BlendMode) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::BLEND_MODE>(BlendMode::PREMULTIPLIED);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodeBlendMode(BlendMode::PREMULTIPLIED, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, Smpte2086) {
|
||||||
|
Smpte2086 hdrdata{XyColor{.1f, .2f}, XyColor{.3f, .4f}, XyColor{.5f, .6f},
|
||||||
|
XyColor{.7f, .8f}, 452.889f, 12.335f};
|
||||||
|
|
||||||
|
auto mpbuf = encode<StandardMetadataType::SMPTE2086>(hdrdata);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2086(hdrdata, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, Cta861_3) {
|
||||||
|
Cta861_3 hdrdata{302.202f, 244.55f};
|
||||||
|
auto mpbuf = encode<StandardMetadataType::CTA861_3>(hdrdata);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodeCta861_3(hdrdata, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, Smpte2094_10) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::SMPTE2094_10>(std::nullopt);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2094_10(std::nullopt, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
|
||||||
|
std::vector<uint8_t> hdrdata{1, 2, 3, 4, 5, 6};
|
||||||
|
mpbuf = encode<StandardMetadataType::SMPTE2094_10>(hdrdata);
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2094_10(hdrdata, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MetadataGralloc4Interop, Smpte2094_40) {
|
||||||
|
auto mpbuf = encode<StandardMetadataType::SMPTE2094_40>(std::nullopt);
|
||||||
|
hidl_vec<uint8_t> g4buf;
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2094_40(std::nullopt, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
|
||||||
|
std::vector<uint8_t> hdrdata{1, 2, 3, 4, 5, 6};
|
||||||
|
mpbuf = encode<StandardMetadataType::SMPTE2094_40>(hdrdata);
|
||||||
|
ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2094_40(hdrdata, &g4buf));
|
||||||
|
EXPECT_EQ(mpbuf, g4buf);
|
||||||
|
}
|
||||||
|
|||||||
@@ -82,7 +82,12 @@ class MetadataWriter {
|
|||||||
explicit MetadataWriter(void* _Nullable destBuffer, size_t destBufferSize)
|
explicit MetadataWriter(void* _Nullable destBuffer, size_t destBufferSize)
|
||||||
: mDest(reinterpret_cast<uint8_t*>(destBuffer)), mSizeRemaining(destBufferSize) {}
|
: mDest(reinterpret_cast<uint8_t*>(destBuffer)), mSizeRemaining(destBufferSize) {}
|
||||||
|
|
||||||
int32_t desiredSize() const { return mDesiredSize; }
|
[[nodiscard]] int32_t desiredSize() const { return mDesiredSize; }
|
||||||
|
|
||||||
|
template <typename HEADER>
|
||||||
|
MetadataWriter& writeHeader() {
|
||||||
|
return write(HEADER::name).template write<int64_t>(HEADER::value);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
|
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
|
||||||
MetadataWriter& write(T value) {
|
MetadataWriter& write(T value) {
|
||||||
@@ -150,6 +155,18 @@ class MetadataReader {
|
|||||||
[[nodiscard]] size_t remaining() const { return mSizeRemaining; }
|
[[nodiscard]] size_t remaining() const { return mSizeRemaining; }
|
||||||
[[nodiscard]] bool ok() const { return mOk; }
|
[[nodiscard]] bool ok() const { return mOk; }
|
||||||
|
|
||||||
|
template <typename HEADER>
|
||||||
|
MetadataReader& checkHeader() {
|
||||||
|
if (HEADER::name != readString()) {
|
||||||
|
mOk = false;
|
||||||
|
}
|
||||||
|
auto value = readInt<int64_t>();
|
||||||
|
if (!value || *value != HEADER::value) {
|
||||||
|
mOk = false;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
|
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
|
||||||
MetadataReader& read(T& dest) {
|
MetadataReader& read(T& dest) {
|
||||||
if (const void* src = advance(sizeof(T))) {
|
if (const void* src = advance(sizeof(T))) {
|
||||||
@@ -228,27 +245,33 @@ class MetadataReader {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, class Enable = void>
|
template <typename HEADER, typename T, class Enable = void>
|
||||||
struct MetadataValue {};
|
struct MetadataValue {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename HEADER, typename T>
|
||||||
struct MetadataValue<T, std::enable_if_t<std::is_integral_v<T>>> {
|
struct MetadataValue<HEADER, T, std::enable_if_t<std::is_integral_v<T>>> {
|
||||||
[[nodiscard]] static int32_t encode(T value, void* _Nullable destBuffer,
|
[[nodiscard]] static int32_t encode(T value, void* _Nullable destBuffer,
|
||||||
size_t destBufferSize) {
|
size_t destBufferSize) {
|
||||||
return MetadataWriter{destBuffer, destBufferSize}.write(value).desiredSize();
|
return MetadataWriter{destBuffer, destBufferSize}
|
||||||
|
.template writeHeader<HEADER>()
|
||||||
|
.write(value)
|
||||||
|
.desiredSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static std::optional<T> decode(const void* _Nonnull metadata,
|
[[nodiscard]] static std::optional<T> decode(const void* _Nonnull metadata,
|
||||||
size_t metadataSize) {
|
size_t metadataSize) {
|
||||||
return MetadataReader{metadata, metadataSize}.readInt<T>();
|
return MetadataReader{metadata, metadataSize}
|
||||||
|
.template checkHeader<HEADER>()
|
||||||
|
.template readInt<T>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename HEADER, typename T>
|
||||||
struct MetadataValue<T, std::enable_if_t<std::is_enum_v<T>>> {
|
struct MetadataValue<HEADER, T, std::enable_if_t<std::is_enum_v<T>>> {
|
||||||
[[nodiscard]] static int32_t encode(T value, void* _Nullable destBuffer,
|
[[nodiscard]] static int32_t encode(T value, void* _Nullable destBuffer,
|
||||||
size_t destBufferSize) {
|
size_t destBufferSize) {
|
||||||
return MetadataWriter{destBuffer, destBufferSize}
|
return MetadataWriter{destBuffer, destBufferSize}
|
||||||
|
.template writeHeader<HEADER>()
|
||||||
.write(static_cast<std::underlying_type_t<T>>(value))
|
.write(static_cast<std::underlying_type_t<T>>(value))
|
||||||
.desiredSize();
|
.desiredSize();
|
||||||
}
|
}
|
||||||
@@ -256,47 +279,56 @@ struct MetadataValue<T, std::enable_if_t<std::is_enum_v<T>>> {
|
|||||||
[[nodiscard]] static std::optional<T> decode(const void* _Nonnull metadata,
|
[[nodiscard]] static std::optional<T> decode(const void* _Nonnull metadata,
|
||||||
size_t metadataSize) {
|
size_t metadataSize) {
|
||||||
std::underlying_type_t<T> temp;
|
std::underlying_type_t<T> temp;
|
||||||
return MetadataReader{metadata, metadataSize}.read(temp).ok()
|
return MetadataReader{metadata, metadataSize}.template checkHeader<HEADER>().read(temp).ok()
|
||||||
? std::optional<T>(static_cast<T>(temp))
|
? std::optional<T>(static_cast<T>(temp))
|
||||||
: std::nullopt;
|
: std::nullopt;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <typename HEADER>
|
||||||
struct MetadataValue<std::string> {
|
struct MetadataValue<HEADER, std::string> {
|
||||||
[[nodiscard]] static int32_t encode(const std::string_view& value, void* _Nullable destBuffer,
|
[[nodiscard]] static int32_t encode(const std::string_view& value, void* _Nullable destBuffer,
|
||||||
size_t destBufferSize) {
|
size_t destBufferSize) {
|
||||||
return MetadataWriter{destBuffer, destBufferSize}.write(value).desiredSize();
|
return MetadataWriter{destBuffer, destBufferSize}
|
||||||
|
.template writeHeader<HEADER>()
|
||||||
|
.write(value)
|
||||||
|
.desiredSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static std::optional<std::string> decode(const void* _Nonnull metadata,
|
[[nodiscard]] static std::optional<std::string> decode(const void* _Nonnull metadata,
|
||||||
size_t metadataSize) {
|
size_t metadataSize) {
|
||||||
auto reader = MetadataReader{metadata, metadataSize};
|
auto reader = MetadataReader{metadata, metadataSize}.template checkHeader<HEADER>();
|
||||||
auto result = reader.readString();
|
auto result = reader.readString();
|
||||||
return reader.ok() ? std::optional<std::string>{result} : std::nullopt;
|
return reader.ok() ? std::optional<std::string>{result} : std::nullopt;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <typename HEADER>
|
||||||
struct MetadataValue<ExtendableType> {
|
struct MetadataValue<HEADER, ExtendableType> {
|
||||||
static_assert(sizeof(int64_t) == sizeof(ExtendableType::value));
|
static_assert(sizeof(int64_t) == sizeof(ExtendableType::value));
|
||||||
|
|
||||||
[[nodiscard]] static int32_t encode(const ExtendableType& value, void* _Nullable destBuffer,
|
[[nodiscard]] static int32_t encode(const ExtendableType& value, void* _Nullable destBuffer,
|
||||||
size_t destBufferSize) {
|
size_t destBufferSize) {
|
||||||
return MetadataWriter{destBuffer, destBufferSize}.write(value).desiredSize();
|
return MetadataWriter{destBuffer, destBufferSize}
|
||||||
|
.template writeHeader<HEADER>()
|
||||||
|
.write(value)
|
||||||
|
.desiredSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static std::optional<ExtendableType> decode(const void* _Nonnull metadata,
|
[[nodiscard]] static std::optional<ExtendableType> decode(const void* _Nonnull metadata,
|
||||||
size_t metadataSize) {
|
size_t metadataSize) {
|
||||||
return MetadataReader{metadata, metadataSize}.readExtendable();
|
return MetadataReader{metadata, metadataSize}
|
||||||
|
.template checkHeader<HEADER>()
|
||||||
|
.readExtendable();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <typename HEADER>
|
||||||
struct MetadataValue<std::vector<PlaneLayout>> {
|
struct MetadataValue<HEADER, std::vector<PlaneLayout>> {
|
||||||
[[nodiscard]] static int32_t encode(const std::vector<PlaneLayout>& values,
|
[[nodiscard]] static int32_t encode(const std::vector<PlaneLayout>& values,
|
||||||
void* _Nullable destBuffer, size_t destBufferSize) {
|
void* _Nullable destBuffer, size_t destBufferSize) {
|
||||||
MetadataWriter writer{destBuffer, destBufferSize};
|
MetadataWriter writer{destBuffer, destBufferSize};
|
||||||
|
writer.template writeHeader<HEADER>();
|
||||||
writer.write<int64_t>(values.size());
|
writer.write<int64_t>(values.size());
|
||||||
for (const auto& value : values) {
|
for (const auto& value : values) {
|
||||||
writer.write<int64_t>(value.components.size());
|
writer.write<int64_t>(value.components.size());
|
||||||
@@ -321,13 +353,14 @@ struct MetadataValue<std::vector<PlaneLayout>> {
|
|||||||
[[nodiscard]] static DecodeResult decode(const void* _Nonnull metadata, size_t metadataSize) {
|
[[nodiscard]] static DecodeResult decode(const void* _Nonnull metadata, size_t metadataSize) {
|
||||||
std::vector<PlaneLayout> values;
|
std::vector<PlaneLayout> values;
|
||||||
MetadataReader reader{metadata, metadataSize};
|
MetadataReader reader{metadata, metadataSize};
|
||||||
|
reader.template checkHeader<HEADER>();
|
||||||
auto numPlanes = reader.readInt<int64_t>().value_or(0);
|
auto numPlanes = reader.readInt<int64_t>().value_or(0);
|
||||||
values.reserve(numPlanes);
|
values.reserve(numPlanes);
|
||||||
for (int i = 0; i < numPlanes && reader.ok(); i++) {
|
for (int i = 0; i < numPlanes && reader.ok(); i++) {
|
||||||
PlaneLayout& value = values.emplace_back();
|
PlaneLayout& value = values.emplace_back();
|
||||||
auto numPlaneComponents = reader.readInt<int64_t>().value_or(0);
|
auto numPlaneComponents = reader.readInt<int64_t>().value_or(0);
|
||||||
value.components.reserve(numPlaneComponents);
|
value.components.reserve(numPlaneComponents);
|
||||||
for (int i = 0; i < numPlaneComponents && reader.ok(); i++) {
|
for (int j = 0; j < numPlaneComponents && reader.ok(); j++) {
|
||||||
PlaneLayoutComponent& component = value.components.emplace_back();
|
PlaneLayoutComponent& component = value.components.emplace_back();
|
||||||
reader.read(component.type)
|
reader.read(component.type)
|
||||||
.read<int64_t>(component.offsetInBits)
|
.read<int64_t>(component.offsetInBits)
|
||||||
@@ -346,11 +379,12 @@ struct MetadataValue<std::vector<PlaneLayout>> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <typename HEADER>
|
||||||
struct MetadataValue<std::vector<Rect>> {
|
struct MetadataValue<HEADER, std::vector<Rect>> {
|
||||||
[[nodiscard]] static int32_t encode(const std::vector<Rect>& value, void* _Nullable destBuffer,
|
[[nodiscard]] static int32_t encode(const std::vector<Rect>& value, void* _Nullable destBuffer,
|
||||||
size_t destBufferSize) {
|
size_t destBufferSize) {
|
||||||
MetadataWriter writer{destBuffer, destBufferSize};
|
MetadataWriter writer{destBuffer, destBufferSize};
|
||||||
|
writer.template writeHeader<HEADER>();
|
||||||
writer.write<int64_t>(value.size());
|
writer.write<int64_t>(value.size());
|
||||||
for (auto& rect : value) {
|
for (auto& rect : value) {
|
||||||
writer.write<int32_t>(rect.left)
|
writer.write<int32_t>(rect.left)
|
||||||
@@ -364,6 +398,7 @@ struct MetadataValue<std::vector<Rect>> {
|
|||||||
using DecodeResult = std::optional<std::vector<Rect>>;
|
using DecodeResult = std::optional<std::vector<Rect>>;
|
||||||
[[nodiscard]] static DecodeResult decode(const void* _Nonnull metadata, size_t metadataSize) {
|
[[nodiscard]] static DecodeResult decode(const void* _Nonnull metadata, size_t metadataSize) {
|
||||||
MetadataReader reader{metadata, metadataSize};
|
MetadataReader reader{metadata, metadataSize};
|
||||||
|
reader.template checkHeader<HEADER>();
|
||||||
std::vector<Rect> value;
|
std::vector<Rect> value;
|
||||||
auto numRects = reader.readInt<int64_t>().value_or(0);
|
auto numRects = reader.readInt<int64_t>().value_or(0);
|
||||||
value.reserve(numRects);
|
value.reserve(numRects);
|
||||||
@@ -378,13 +413,14 @@ struct MetadataValue<std::vector<Rect>> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <typename HEADER>
|
||||||
struct MetadataValue<std::optional<Smpte2086>> {
|
struct MetadataValue<HEADER, std::optional<Smpte2086>> {
|
||||||
[[nodiscard]] static int32_t encode(const std::optional<Smpte2086>& optValue,
|
[[nodiscard]] static int32_t encode(const std::optional<Smpte2086>& optValue,
|
||||||
void* _Nullable destBuffer, size_t destBufferSize) {
|
void* _Nullable destBuffer, size_t destBufferSize) {
|
||||||
if (optValue.has_value()) {
|
if (optValue.has_value()) {
|
||||||
const auto& value = *optValue;
|
const auto& value = *optValue;
|
||||||
return MetadataWriter{destBuffer, destBufferSize}
|
return MetadataWriter{destBuffer, destBufferSize}
|
||||||
|
.template writeHeader<HEADER>()
|
||||||
.write(value.primaryRed)
|
.write(value.primaryRed)
|
||||||
.write(value.primaryGreen)
|
.write(value.primaryGreen)
|
||||||
.write(value.primaryBlue)
|
.write(value.primaryBlue)
|
||||||
@@ -404,6 +440,7 @@ struct MetadataValue<std::optional<Smpte2086>> {
|
|||||||
if (metadataSize > 0) {
|
if (metadataSize > 0) {
|
||||||
Smpte2086 value;
|
Smpte2086 value;
|
||||||
MetadataReader reader{metadata, metadataSize};
|
MetadataReader reader{metadata, metadataSize};
|
||||||
|
reader.template checkHeader<HEADER>();
|
||||||
reader.read(value.primaryRed)
|
reader.read(value.primaryRed)
|
||||||
.read(value.primaryGreen)
|
.read(value.primaryGreen)
|
||||||
.read(value.primaryBlue)
|
.read(value.primaryBlue)
|
||||||
@@ -420,13 +457,14 @@ struct MetadataValue<std::optional<Smpte2086>> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <typename HEADER>
|
||||||
struct MetadataValue<std::optional<Cta861_3>> {
|
struct MetadataValue<HEADER, std::optional<Cta861_3>> {
|
||||||
[[nodiscard]] static int32_t encode(const std::optional<Cta861_3>& optValue,
|
[[nodiscard]] static int32_t encode(const std::optional<Cta861_3>& optValue,
|
||||||
void* _Nullable destBuffer, size_t destBufferSize) {
|
void* _Nullable destBuffer, size_t destBufferSize) {
|
||||||
if (optValue.has_value()) {
|
if (optValue.has_value()) {
|
||||||
const auto& value = *optValue;
|
const auto& value = *optValue;
|
||||||
return MetadataWriter{destBuffer, destBufferSize}
|
return MetadataWriter{destBuffer, destBufferSize}
|
||||||
|
.template writeHeader<HEADER>()
|
||||||
.write(value.maxContentLightLevel)
|
.write(value.maxContentLightLevel)
|
||||||
.write(value.maxFrameAverageLightLevel)
|
.write(value.maxFrameAverageLightLevel)
|
||||||
.desiredSize();
|
.desiredSize();
|
||||||
@@ -441,6 +479,7 @@ struct MetadataValue<std::optional<Cta861_3>> {
|
|||||||
std::optional<Cta861_3> optValue{std::nullopt};
|
std::optional<Cta861_3> optValue{std::nullopt};
|
||||||
if (metadataSize > 0) {
|
if (metadataSize > 0) {
|
||||||
MetadataReader reader{metadata, metadataSize};
|
MetadataReader reader{metadata, metadataSize};
|
||||||
|
reader.template checkHeader<HEADER>();
|
||||||
Cta861_3 value;
|
Cta861_3 value;
|
||||||
reader.read(value.maxContentLightLevel).read(value.maxFrameAverageLightLevel);
|
reader.read(value.maxContentLightLevel).read(value.maxFrameAverageLightLevel);
|
||||||
if (reader.ok()) {
|
if (reader.ok()) {
|
||||||
@@ -453,14 +492,17 @@ struct MetadataValue<std::optional<Cta861_3>> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <typename HEADER>
|
||||||
struct MetadataValue<std::optional<std::vector<uint8_t>>> {
|
struct MetadataValue<HEADER, std::optional<std::vector<uint8_t>>> {
|
||||||
[[nodiscard]] static int32_t encode(const std::optional<std::vector<uint8_t>>& value,
|
[[nodiscard]] static int32_t encode(const std::optional<std::vector<uint8_t>>& value,
|
||||||
void* _Nullable destBuffer, size_t destBufferSize) {
|
void* _Nullable destBuffer, size_t destBufferSize) {
|
||||||
if (!value.has_value()) {
|
if (!value.has_value()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return MetadataWriter{destBuffer, destBufferSize}.write(*value).desiredSize();
|
return MetadataWriter{destBuffer, destBufferSize}
|
||||||
|
.template writeHeader<HEADER>()
|
||||||
|
.write(*value)
|
||||||
|
.desiredSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
using DecodeResult = std::optional<std::optional<std::vector<uint8_t>>>;
|
using DecodeResult = std::optional<std::optional<std::vector<uint8_t>>>;
|
||||||
@@ -468,6 +510,7 @@ struct MetadataValue<std::optional<std::vector<uint8_t>>> {
|
|||||||
std::optional<std::vector<uint8_t>> optValue;
|
std::optional<std::vector<uint8_t>> optValue;
|
||||||
if (metadataSize > 0) {
|
if (metadataSize > 0) {
|
||||||
MetadataReader reader{metadata, metadataSize};
|
MetadataReader reader{metadata, metadataSize};
|
||||||
|
reader.template checkHeader<HEADER>();
|
||||||
auto value = reader.readBuffer();
|
auto value = reader.readBuffer();
|
||||||
if (reader.ok()) {
|
if (reader.ok()) {
|
||||||
optValue = std::move(value);
|
optValue = std::move(value);
|
||||||
@@ -482,16 +525,20 @@ struct MetadataValue<std::optional<std::vector<uint8_t>>> {
|
|||||||
template <StandardMetadataType>
|
template <StandardMetadataType>
|
||||||
struct StandardMetadata {};
|
struct StandardMetadata {};
|
||||||
|
|
||||||
#define DEFINE_TYPE(name, typeArg) \
|
#define DEFINE_TYPE(typeName, typeArg) \
|
||||||
template <> \
|
template <> \
|
||||||
struct StandardMetadata<StandardMetadataType::name> { \
|
struct StandardMetadata<StandardMetadataType::typeName> { \
|
||||||
using value_type = typeArg; \
|
using value_type = typeArg; \
|
||||||
using value = MetadataValue<value_type>; \
|
struct Header { \
|
||||||
static_assert( \
|
static constexpr auto name = "android.hardware.graphics.common.StandardMetadataType"; \
|
||||||
StandardMetadataType::name == \
|
static constexpr auto value = static_cast<int64_t>(StandardMetadataType::typeName); \
|
||||||
ndk::internal::enum_values<StandardMetadataType>[static_cast<size_t>( \
|
}; \
|
||||||
StandardMetadataType::name)], \
|
using value = MetadataValue<Header, value_type>; \
|
||||||
"StandardMetadataType must have equivalent value to index"); \
|
static_assert( \
|
||||||
|
StandardMetadataType::typeName == \
|
||||||
|
ndk::internal::enum_values<StandardMetadataType>[static_cast<size_t>( \
|
||||||
|
StandardMetadataType::typeName)], \
|
||||||
|
"StandardMetadataType must have equivalent value to index"); \
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_TYPE(BUFFER_ID, uint64_t);
|
DEFINE_TYPE(BUFFER_ID, uint64_t);
|
||||||
|
|||||||
@@ -509,11 +509,12 @@ typedef struct AIMapperV5 {
|
|||||||
* particular Metadata field.
|
* particular Metadata field.
|
||||||
*
|
*
|
||||||
* The framework will attempt to set the following StandardMetadataType
|
* The framework will attempt to set the following StandardMetadataType
|
||||||
* values: DATASPACE, SMPTE2086, CTA861_3, SMPTE2094_40 and BLEND_MODE.
|
* values: DATASPACE, SMPTE2086, CTA861_3, and BLEND_MODE.
|
||||||
* We require everyone to support setting those fields. If a device's Composer
|
* We require everyone to support setting those fields. Framework will also attempt to set
|
||||||
* implementation supports a field, it should be supported here. Over time these
|
* SMPTE2094_40 and SMPTE2094_10 if available, and it is required to support setting those
|
||||||
* metadata fields will be moved out of Composer/BufferQueue/etc. and into the
|
* if it is possible to get them. If a device's Composer implementation supports a field,
|
||||||
* buffer's Metadata fields.
|
* it should be supported here. Over time these metadata fields will be moved out of
|
||||||
|
* Composer/BufferQueue/etc. and into the buffer's Metadata fields.
|
||||||
*
|
*
|
||||||
* @param buffer Buffer receiving desired metadata
|
* @param buffer Buffer receiving desired metadata
|
||||||
* @param metadataType MetadataType for the metadata value being set
|
* @param metadataType MetadataType for the metadata value being set
|
||||||
@@ -546,11 +547,12 @@ typedef struct AIMapperV5 {
|
|||||||
* particular Metadata field.
|
* particular Metadata field.
|
||||||
*
|
*
|
||||||
* The framework will attempt to set the following StandardMetadataType
|
* The framework will attempt to set the following StandardMetadataType
|
||||||
* values: DATASPACE, SMPTE2086, CTA861_3, SMPTE2094_40 and BLEND_MODE.
|
* values: DATASPACE, SMPTE2086, CTA861_3, and BLEND_MODE.
|
||||||
* We require everyone to support setting those fields. If a device's Composer
|
* We require everyone to support setting those fields. Framework will also attempt to set
|
||||||
* implementation supports a field, it should be supported here. Over time these
|
* SMPTE2094_40 and SMPTE2094_10 if available, and it is required to support setting those
|
||||||
* metadata fields will be moved out of Composer/BufferQueue/etc. and into the
|
* if it is possible to get them. If a device's Composer implementation supports a field,
|
||||||
* buffer's Metadata fields.
|
* it should be supported here. Over time these metadata fields will be moved out of
|
||||||
|
* Composer/BufferQueue/etc. and into the buffer's Metadata fields.
|
||||||
*
|
*
|
||||||
* @param buffer Buffer receiving desired metadata
|
* @param buffer Buffer receiving desired metadata
|
||||||
* @param standardMetadataType StandardMetadataType for the metadata value being set
|
* @param standardMetadataType StandardMetadataType for the metadata value being set
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <aidl/android/hardware/graphics/common/BufferUsage.h>
|
#include <aidl/android/hardware/graphics/common/BufferUsage.h>
|
||||||
#include <aidl/android/hardware/graphics/common/PixelFormat.h>
|
#include <aidl/android/hardware/graphics/common/PixelFormat.h>
|
||||||
#include <aidlcommonsupport/NativeHandle.h>
|
#include <aidlcommonsupport/NativeHandle.h>
|
||||||
|
#include <android/binder_enums.h>
|
||||||
#include <android/binder_manager.h>
|
#include <android/binder_manager.h>
|
||||||
#include <android/dlext.h>
|
#include <android/dlext.h>
|
||||||
#include <android/hardware/graphics/mapper/IMapper.h>
|
#include <android/hardware/graphics/mapper/IMapper.h>
|
||||||
@@ -66,6 +67,24 @@ struct YCbCr {
|
|||||||
int64_t verticalSubSampling;
|
int64_t verticalSubSampling;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr const char* STANDARD_METADATA_NAME =
|
||||||
|
"android.hardware.graphics.common.StandardMetadataType";
|
||||||
|
|
||||||
|
static bool isStandardMetadata(AIMapper_MetadataType metadataType) {
|
||||||
|
return strcmp(STANDARD_METADATA_NAME, metadataType.name) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string toString(const std::vector<StandardMetadataType> types) {
|
||||||
|
std::stringstream buf;
|
||||||
|
buf << "[";
|
||||||
|
for (auto type : types) {
|
||||||
|
buf << toString(type) << ", ";
|
||||||
|
}
|
||||||
|
buf.seekp(-2, buf.cur);
|
||||||
|
buf << "]";
|
||||||
|
return buf.str();
|
||||||
|
}
|
||||||
|
|
||||||
class BufferHandle {
|
class BufferHandle {
|
||||||
AIMapper* mIMapper;
|
AIMapper* mIMapper;
|
||||||
buffer_handle_t mHandle = nullptr;
|
buffer_handle_t mHandle = nullptr;
|
||||||
@@ -215,7 +234,7 @@ class GraphicsTestsBase {
|
|||||||
sizeRequired = mapper()->v5.getStandardMetadata(bufferHandle, static_cast<int64_t>(T),
|
sizeRequired = mapper()->v5.getStandardMetadata(bufferHandle, static_cast<int64_t>(T),
|
||||||
buffer.data(), buffer.size());
|
buffer.data(), buffer.size());
|
||||||
}
|
}
|
||||||
if (sizeRequired < 0 || sizeRequired >= buffer.size()) {
|
if (sizeRequired < 0 || sizeRequired > buffer.size()) {
|
||||||
ADD_FAILURE() << "getStandardMetadata failed, received " << sizeRequired
|
ADD_FAILURE() << "getStandardMetadata failed, received " << sizeRequired
|
||||||
<< " with buffer size " << buffer.size();
|
<< " with buffer size " << buffer.size();
|
||||||
// Generate a fail type
|
// Generate a fail type
|
||||||
@@ -1533,8 +1552,187 @@ TEST_P(GraphicsMapperStableCTests, GetSmpte2094_40) {
|
|||||||
auto bufferHandle = buffer->import();
|
auto bufferHandle = buffer->import();
|
||||||
ASSERT_TRUE(bufferHandle);
|
ASSERT_TRUE(bufferHandle);
|
||||||
auto value = getStandardMetadata<StandardMetadataType::SMPTE2094_40>(*bufferHandle);
|
auto value = getStandardMetadata<StandardMetadataType::SMPTE2094_40>(*bufferHandle);
|
||||||
ASSERT_TRUE(value.has_value());
|
if (value.has_value()) {
|
||||||
EXPECT_FALSE(value->has_value());
|
EXPECT_FALSE(value->has_value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(GraphicsMapperStableCTests, SupportsRequiredGettersSetters) {
|
||||||
|
auto buffer = allocateGeneric();
|
||||||
|
ASSERT_TRUE(buffer);
|
||||||
|
auto bufferHandle = buffer->import();
|
||||||
|
ASSERT_TRUE(bufferHandle);
|
||||||
|
const AIMapper_MetadataTypeDescription* descriptions = nullptr;
|
||||||
|
size_t descriptionCount = 0;
|
||||||
|
ASSERT_EQ(AIMAPPER_ERROR_NONE,
|
||||||
|
mapper()->v5.listSupportedMetadataTypes(&descriptions, &descriptionCount));
|
||||||
|
std::vector<StandardMetadataType> requiredGetters = {
|
||||||
|
StandardMetadataType::BUFFER_ID,
|
||||||
|
StandardMetadataType::NAME,
|
||||||
|
StandardMetadataType::WIDTH,
|
||||||
|
StandardMetadataType::HEIGHT,
|
||||||
|
StandardMetadataType::LAYER_COUNT,
|
||||||
|
StandardMetadataType::PIXEL_FORMAT_REQUESTED,
|
||||||
|
StandardMetadataType::PIXEL_FORMAT_FOURCC,
|
||||||
|
StandardMetadataType::PIXEL_FORMAT_MODIFIER,
|
||||||
|
StandardMetadataType::USAGE,
|
||||||
|
StandardMetadataType::ALLOCATION_SIZE,
|
||||||
|
StandardMetadataType::PROTECTED_CONTENT,
|
||||||
|
StandardMetadataType::COMPRESSION,
|
||||||
|
StandardMetadataType::INTERLACED,
|
||||||
|
StandardMetadataType::CHROMA_SITING,
|
||||||
|
StandardMetadataType::PLANE_LAYOUTS,
|
||||||
|
StandardMetadataType::CROP,
|
||||||
|
StandardMetadataType::DATASPACE,
|
||||||
|
StandardMetadataType::BLEND_MODE,
|
||||||
|
StandardMetadataType::SMPTE2086,
|
||||||
|
StandardMetadataType::CTA861_3,
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<StandardMetadataType> requiredSetters = {
|
||||||
|
StandardMetadataType::DATASPACE,
|
||||||
|
StandardMetadataType::BLEND_MODE,
|
||||||
|
StandardMetadataType::SMPTE2086,
|
||||||
|
StandardMetadataType::CTA861_3,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < descriptionCount; i++) {
|
||||||
|
const auto& it = descriptions[i];
|
||||||
|
if (isStandardMetadata(it.metadataType)) {
|
||||||
|
EXPECT_GT(it.metadataType.value, static_cast<int64_t>(StandardMetadataType::INVALID));
|
||||||
|
EXPECT_LT(it.metadataType.value,
|
||||||
|
ndk::internal::enum_values<StandardMetadataType>.size());
|
||||||
|
|
||||||
|
if (it.isGettable) {
|
||||||
|
std::erase(requiredGetters,
|
||||||
|
static_cast<StandardMetadataType>(it.metadataType.value));
|
||||||
|
}
|
||||||
|
if (it.isSettable) {
|
||||||
|
std::erase(requiredSetters,
|
||||||
|
static_cast<StandardMetadataType>(it.metadataType.value));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
EXPECT_NE(nullptr, it.description) << "Non-standard metadata must have a description";
|
||||||
|
int len = strlen(it.description);
|
||||||
|
EXPECT_GE(len, 0) << "Non-standard metadata must have a description";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(0, requiredGetters.size()) << "Missing required getters" << toString(requiredGetters);
|
||||||
|
EXPECT_EQ(0, requiredSetters.size()) << "Missing required setters" << toString(requiredSetters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test that verifies that if the optional StandardMetadataTypes have getters, they have
|
||||||
|
* the required setters as well
|
||||||
|
*/
|
||||||
|
TEST_P(GraphicsMapperStableCTests, CheckRequiredSettersIfHasGetters) {
|
||||||
|
auto buffer = allocateGeneric();
|
||||||
|
ASSERT_TRUE(buffer);
|
||||||
|
auto bufferHandle = buffer->import();
|
||||||
|
ASSERT_TRUE(bufferHandle);
|
||||||
|
const AIMapper_MetadataTypeDescription* descriptions = nullptr;
|
||||||
|
size_t descriptionCount = 0;
|
||||||
|
ASSERT_EQ(AIMAPPER_ERROR_NONE,
|
||||||
|
mapper()->v5.listSupportedMetadataTypes(&descriptions, &descriptionCount));
|
||||||
|
|
||||||
|
for (int i = 0; i < descriptionCount; i++) {
|
||||||
|
const auto& it = descriptions[i];
|
||||||
|
if (isStandardMetadata(it.metadataType)) {
|
||||||
|
const auto type = static_cast<StandardMetadataType>(it.metadataType.value);
|
||||||
|
switch (type) {
|
||||||
|
case StandardMetadataType::SMPTE2094_10:
|
||||||
|
case StandardMetadataType::SMPTE2094_40:
|
||||||
|
if (it.isGettable) {
|
||||||
|
EXPECT_TRUE(it.isSettable)
|
||||||
|
<< "Type " << toString(type) << " must be settable if gettable";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(GraphicsMapperStableCTests, ListSupportedWorks) {
|
||||||
|
auto buffer = allocateGeneric();
|
||||||
|
ASSERT_TRUE(buffer);
|
||||||
|
auto bufferHandle = buffer->import();
|
||||||
|
ASSERT_TRUE(bufferHandle);
|
||||||
|
const AIMapper_MetadataTypeDescription* descriptions = nullptr;
|
||||||
|
size_t descriptionCount = 0;
|
||||||
|
ASSERT_EQ(AIMAPPER_ERROR_NONE,
|
||||||
|
mapper()->v5.listSupportedMetadataTypes(&descriptions, &descriptionCount));
|
||||||
|
|
||||||
|
std::vector<uint8_t> metadataBuffer;
|
||||||
|
auto get = [&](AIMapper_MetadataType metadataType) -> int32_t {
|
||||||
|
int32_t size = mapper()->v5.getMetadata(*bufferHandle, metadataType, nullptr, 0);
|
||||||
|
if (size >= 0) {
|
||||||
|
metadataBuffer.resize(size);
|
||||||
|
size = mapper()->v5.getMetadata(*bufferHandle, metadataType, metadataBuffer.data(),
|
||||||
|
metadataBuffer.size());
|
||||||
|
EXPECT_EQ(size, metadataBuffer.size());
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < descriptionCount; i++) {
|
||||||
|
const auto& it = descriptions[i];
|
||||||
|
if (!isStandardMetadata(it.metadataType)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!it.isGettable) {
|
||||||
|
EXPECT_FALSE(it.isSettable)
|
||||||
|
<< "StandardMetadata that isn't gettable must not be settable";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
EXPECT_GE(get(it.metadataType), 0)
|
||||||
|
<< "Get failed for claimed supported getter of "
|
||||||
|
<< toString(static_cast<StandardMetadataType>(it.metadataType.value));
|
||||||
|
if (it.isSettable) {
|
||||||
|
EXPECT_EQ(AIMAPPER_ERROR_NONE,
|
||||||
|
mapper()->v5.setMetadata(*bufferHandle, it.metadataType,
|
||||||
|
metadataBuffer.data(), metadataBuffer.size()))
|
||||||
|
<< "Failed to set metadata for "
|
||||||
|
<< toString(static_cast<StandardMetadataType>(it.metadataType.value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(GraphicsMapperStableCTests, GetMetadataBadValue) {
|
||||||
|
auto get = [this](StandardMetadataType type) -> AIMapper_Error {
|
||||||
|
// This is a _Nonnull parameter, but this is enough obfuscation to fool the linter
|
||||||
|
buffer_handle_t buffer = nullptr;
|
||||||
|
int32_t ret =
|
||||||
|
mapper()->v5.getStandardMetadata(buffer, static_cast<int64_t>(type), nullptr, 0);
|
||||||
|
return (ret < 0) ? (AIMapper_Error)-ret : AIMAPPER_ERROR_NONE;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto type : ndk::enum_range<StandardMetadataType>()) {
|
||||||
|
if (type == StandardMetadataType::INVALID) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, get(type)) << "Wrong error for " << toString(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(GraphicsMapperStableCTests, GetUnsupportedMetadata) {
|
||||||
|
auto buffer = allocateGeneric();
|
||||||
|
ASSERT_TRUE(buffer);
|
||||||
|
auto bufferHandle = buffer->import();
|
||||||
|
ASSERT_TRUE(bufferHandle);
|
||||||
|
|
||||||
|
int result = mapper()->v5.getMetadata(*bufferHandle, {"Fake", 1}, nullptr, 0);
|
||||||
|
EXPECT_EQ(AIMAPPER_ERROR_UNSUPPORTED, -result);
|
||||||
|
|
||||||
|
result = mapper()->v5.getStandardMetadata(
|
||||||
|
*bufferHandle, static_cast<int64_t>(StandardMetadataType::INVALID), nullptr, 0);
|
||||||
|
EXPECT_EQ(AIMAPPER_ERROR_UNSUPPORTED, -result);
|
||||||
|
|
||||||
|
constexpr int64_t unknownStandardType = ndk::internal::enum_values<StandardMetadataType>.size();
|
||||||
|
result = mapper()->v5.getStandardMetadata(*bufferHandle, unknownStandardType, nullptr, 0);
|
||||||
|
EXPECT_EQ(AIMAPPER_ERROR_UNSUPPORTED, -result);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::tuple<std::string, std::shared_ptr<IAllocator>>> getIAllocatorsAtLeastVersion(
|
std::vector<std::tuple<std::string, std::shared_ptr<IAllocator>>> getIAllocatorsAtLeastVersion(
|
||||||
|
|||||||
Reference in New Issue
Block a user