/* * Copyright (c) 2020, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of The Linux Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "QtiGralloc.h" #include namespace qtigralloc { using android::hardware::graphics::mapper::V4_0::IMapper; static sp getInstance() { static sp mapper = IMapper::getService(); return mapper; } Error decodeMetadataState(hidl_vec &in, bool *out) { if (!in.size() || !out) { return Error::BAD_VALUE; } memcpy(out, in.data(), METADATA_SET_SIZE); return Error::NONE; } Error encodeMetadataState(bool *in, hidl_vec *out) { if (!in || !out) { return Error::BAD_VALUE; } out->resize(sizeof(bool) * METADATA_SET_SIZE); memcpy(out->data(), in, sizeof(bool) * METADATA_SET_SIZE); return Error::NONE; } Error decodeColorMetadata(hidl_vec &in, ColorMetaData *out) { if (!in.size() || !out) { return Error::BAD_VALUE; } memcpy(out, in.data(), sizeof(ColorMetaData)); return Error::NONE; } Error encodeColorMetadata(ColorMetaData &in, hidl_vec *out) { if (!out) { return Error::BAD_VALUE; } out->resize(sizeof(ColorMetaData)); memcpy(out->data(), &in, sizeof(ColorMetaData)); return Error::NONE; } // decode the raw graphics metadata from bytestream and store it in 'data' member of // GraphicsMetadata struct during mapper->set call, 'size' member is unused. Error decodeGraphicsMetadata(hidl_vec &in, GraphicsMetadata *out) { if (!in.size() || !out) { return Error::BAD_VALUE; } memcpy(&(out->data), in.data(), GRAPHICS_METADATA_SIZE_IN_BYTES); return Error::NONE; } // encode only 'data' member of GraphicsMetadata struct for retrieval of // graphics metadata during mapper->get call Error encodeGraphicsMetadata(GraphicsMetadata &in, hidl_vec *out) { if (!out) { return Error::BAD_VALUE; } out->resize(GRAPHICS_METADATA_SIZE_IN_BYTES); memcpy(out->data(), &(in.data), GRAPHICS_METADATA_SIZE_IN_BYTES); return Error::NONE; } // decode the raw graphics metadata from bytestream before presenting it to caller Error decodeGraphicsMetadataRaw(hidl_vec &in, void *out) { if (!in.size() || !out) { return Error::BAD_VALUE; } memcpy(out, in.data(), GRAPHICS_METADATA_SIZE_IN_BYTES); return Error::NONE; } // encode the raw graphics metadata in bytestream before calling mapper->set Error encodeGraphicsMetadataRaw(void *in, hidl_vec *out) { if (!in || !out) { return Error::BAD_VALUE; } out->resize(GRAPHICS_METADATA_SIZE_IN_BYTES); memcpy(out->data(), in, GRAPHICS_METADATA_SIZE_IN_BYTES); return Error::NONE; } Error decodeUBWCStats(hidl_vec &in, UBWCStats *out) { if (!in.size() || !out) { return Error::BAD_VALUE; } memcpy(out, in.data(), UBWC_STATS_ARRAY_SIZE * sizeof(UBWCStats)); return Error::NONE; } Error encodeUBWCStats(UBWCStats *in, hidl_vec *out) { if (!in || !out) { return Error::BAD_VALUE; } out->resize(UBWC_STATS_ARRAY_SIZE * sizeof(UBWCStats)); memcpy(out->data(), in, UBWC_STATS_ARRAY_SIZE * sizeof(UBWCStats)); return Error::NONE; } Error decodeCVPMetadata(hidl_vec &in, CVPMetadata *out) { if (!in.size() || !out) { return Error::BAD_VALUE; } memcpy(out, in.data(), sizeof(CVPMetadata)); return Error::NONE; } Error encodeCVPMetadata(CVPMetadata &in, hidl_vec *out) { if (!out) { return Error::BAD_VALUE; } out->resize(sizeof(CVPMetadata)); memcpy(out->data(), &in, sizeof(CVPMetadata)); return Error::NONE; } Error decodeVideoHistogramMetadata(hidl_vec &in, VideoHistogramMetadata *out) { if (!in.size() || !out) { return Error::BAD_VALUE; } memcpy(out, in.data(), sizeof(VideoHistogramMetadata)); return Error::NONE; } Error encodeVideoHistogramMetadata(VideoHistogramMetadata &in, hidl_vec *out) { if (!out) { return Error::BAD_VALUE; } out->resize(sizeof(VideoHistogramMetadata)); memcpy(out->data(), &in, sizeof(VideoHistogramMetadata)); return Error::NONE; } Error decodeVideoTimestampInfo(hidl_vec &in, VideoTimestampInfo *out) { if (!in.size() || !out) { return Error::BAD_VALUE; } memcpy(out, in.data(), sizeof(VideoTimestampInfo)); return Error::NONE; } Error encodeVideoTimestampInfo(VideoTimestampInfo &in, hidl_vec *out) { if (!out) { return Error::BAD_VALUE; } out->resize(sizeof(VideoTimestampInfo)); memcpy(out->data(), &in, sizeof(VideoTimestampInfo)); return Error::NONE; } Error decodeYUVPlaneInfoMetadata(hidl_vec &in, qti_ycbcr *out) { if (!in.size() || !out) { return Error::BAD_VALUE; } qti_ycbcr *p = reinterpret_cast(in.data()); memcpy(out, in.data(), (YCBCR_LAYOUT_ARRAY_SIZE * sizeof(qti_ycbcr))); return Error::NONE; } Error encodeYUVPlaneInfoMetadata(qti_ycbcr *in, hidl_vec *out) { if (!out) { return Error::BAD_VALUE; } out->resize(YCBCR_LAYOUT_ARRAY_SIZE * sizeof(qti_ycbcr)); memcpy(out->data(), in, YCBCR_LAYOUT_ARRAY_SIZE * sizeof(qti_ycbcr)); return Error::NONE; } MetadataType getMetadataType(uint32_t in) { switch (in) { case QTI_VT_TIMESTAMP: return MetadataType_VTTimestamp; case QTI_VIDEO_PERF_MODE: return MetadataType_VideoPerfMode; case QTI_LINEAR_FORMAT: return MetadataType_LinearFormat; case QTI_SINGLE_BUFFER_MODE: return MetadataType_SingleBufferMode; case QTI_PP_PARAM_INTERLACED: return MetadataType_PPParamInterlaced; case QTI_MAP_SECURE_BUFFER: return MetadataType_MapSecureBuffer; case QTI_COLOR_METADATA: return MetadataType_ColorMetadata; case QTI_GRAPHICS_METADATA: return MetadataType_GraphicsMetadata; case QTI_UBWC_CR_STATS_INFO: return MetadataType_UBWCCRStatsInfo; case QTI_REFRESH_RATE: return MetadataType_RefreshRate; case QTI_CVP_METADATA: return MetadataType_CVPMetadata; case QTI_VIDEO_HISTOGRAM_STATS: return MetadataType_VideoHistogramStats; case QTI_VIDEO_TS_INFO: return MetadataType_VideoTimestampInfo; case QTI_FD: return MetadataType_FD; case QTI_PRIVATE_FLAGS: return MetadataType_PrivateFlags; case QTI_ALIGNED_WIDTH_IN_PIXELS: return MetadataType_AlignedWidthInPixels; case QTI_ALIGNED_HEIGHT_IN_PIXELS: return MetadataType_AlignedHeightInPixels; case QTI_STANDARD_METADATA_STATUS: return MetadataType_StandardMetadataStatus; case QTI_VENDOR_METADATA_STATUS: return MetadataType_VendorMetadataStatus; case QTI_BUFFER_TYPE: return MetadataType_BufferType; case QTI_CUSTOM_DIMENSIONS_STRIDE: return MetadataType_CustomDimensionsStride; case QTI_CUSTOM_DIMENSIONS_HEIGHT: return MetadataType_CustomDimensionsHeight; case QTI_RGB_DATA_ADDRESS: return MetadataType_RgbDataAddress; case QTI_COLORSPACE: return MetadataType_ColorSpace; case QTI_YUV_PLANE_INFO: return MetadataType_YuvPlaneInfo; default: return MetadataType_Invalid; } } Error get(void *buffer, uint32_t type, void *param) { hidl_vec bytestream; sp mapper = getInstance(); MetadataType metadata_type = getMetadataType(type); if (metadata_type == MetadataType_Invalid) { param = nullptr; return Error::UNSUPPORTED; } auto err = Error::UNSUPPORTED; mapper->get(buffer, metadata_type, [&](const auto &tmpError, const auto &tmpByteStream) { err = tmpError; bytestream = tmpByteStream; }); if (err != Error::NONE) { return err; } switch (type) { case QTI_VT_TIMESTAMP: err = static_cast(android::gralloc4::decodeUint64(qtigralloc::MetadataType_VTTimestamp, bytestream, (uint64_t *)param)); break; case QTI_VIDEO_PERF_MODE: err = static_cast(android::gralloc4::decodeUint32( qtigralloc::MetadataType_VideoPerfMode, bytestream, (uint32_t *)param)); break; case QTI_LINEAR_FORMAT: err = static_cast(android::gralloc4::decodeUint32( qtigralloc::MetadataType_LinearFormat, bytestream, (uint32_t *)param)); break; case QTI_SINGLE_BUFFER_MODE: err = static_cast(android::gralloc4::decodeUint32( qtigralloc::MetadataType_SingleBufferMode, bytestream, (uint32_t *)param)); break; case QTI_PP_PARAM_INTERLACED: err = static_cast(android::gralloc4::decodeInt32( qtigralloc::MetadataType_PPParamInterlaced, bytestream, (int32_t *)param)); break; case QTI_MAP_SECURE_BUFFER: err = static_cast(android::gralloc4::decodeInt32( qtigralloc::MetadataType_MapSecureBuffer, bytestream, (int32_t *)param)); break; case QTI_COLOR_METADATA: err = decodeColorMetadata(bytestream, (ColorMetaData *)param); break; case QTI_GRAPHICS_METADATA: err = decodeGraphicsMetadataRaw(bytestream, param); break; case QTI_UBWC_CR_STATS_INFO: err = decodeUBWCStats(bytestream, (UBWCStats *)param); break; case QTI_REFRESH_RATE: err = static_cast(android::gralloc4::decodeFloat(qtigralloc::MetadataType_RefreshRate, bytestream, (float *)param)); break; case QTI_CVP_METADATA: err = decodeCVPMetadata(bytestream, (CVPMetadata *)param); break; case QTI_VIDEO_HISTOGRAM_STATS: err = decodeVideoHistogramMetadata(bytestream, (VideoHistogramMetadata *)param); break; case QTI_VIDEO_TS_INFO: err = decodeVideoTimestampInfo(bytestream, (VideoTimestampInfo *)param); break; case QTI_FD: err = static_cast(android::gralloc4::decodeInt32(qtigralloc::MetadataType_FD, bytestream, (int32_t *)param)); break; case QTI_PRIVATE_FLAGS: err = static_cast(android::gralloc4::decodeInt32(qtigralloc::MetadataType_PrivateFlags, bytestream, (int32_t *)param)); break; case QTI_ALIGNED_WIDTH_IN_PIXELS: err = static_cast(android::gralloc4::decodeUint32( qtigralloc::MetadataType_AlignedWidthInPixels, bytestream, (uint32_t *)param)); break; case QTI_ALIGNED_HEIGHT_IN_PIXELS: err = static_cast(android::gralloc4::decodeUint32( qtigralloc::MetadataType_AlignedHeightInPixels, bytestream, (uint32_t *)param)); break; case QTI_STANDARD_METADATA_STATUS: case QTI_VENDOR_METADATA_STATUS: err = decodeMetadataState(bytestream, (bool *)param); break; case QTI_BUFFER_TYPE: err = static_cast(android::gralloc4::decodeUint32( qtigralloc::MetadataType_BufferType, bytestream, (uint32_t *)param)); break; case QTI_CUSTOM_DIMENSIONS_STRIDE: err = static_cast(android::gralloc4::decodeUint32( qtigralloc::MetadataType_CustomDimensionsStride, bytestream, (uint32_t *)param)); break; case QTI_CUSTOM_DIMENSIONS_HEIGHT: err = static_cast(android::gralloc4::decodeUint32( qtigralloc::MetadataType_CustomDimensionsHeight, bytestream, (uint32_t *)param)); break; case QTI_RGB_DATA_ADDRESS: err = static_cast(android::gralloc4::decodeUint64( qtigralloc::MetadataType_RgbDataAddress, bytestream, (uint64_t *)param)); break; case QTI_COLORSPACE: err = static_cast(android::gralloc4::decodeUint32(qtigralloc::MetadataType_ColorSpace, bytestream, (uint32_t *)param)); break; case QTI_YUV_PLANE_INFO: err = decodeYUVPlaneInfoMetadata(bytestream, (qti_ycbcr *)param); break; default: param = nullptr; return Error::UNSUPPORTED; } return err; } Error set(void *buffer, uint32_t type, void *param) { hidl_vec bytestream; sp mapper = getInstance(); Error err = Error::UNSUPPORTED; MetadataType metadata_type = getMetadataType(type); if (metadata_type == MetadataType_Invalid) { return err; } switch (type) { case QTI_VT_TIMESTAMP: err = static_cast(android::gralloc4::encodeUint64(qtigralloc::MetadataType_VTTimestamp, *(uint64_t *)param, &bytestream)); break; case QTI_VIDEO_PERF_MODE: err = static_cast(android::gralloc4::encodeUint32( qtigralloc::MetadataType_VideoPerfMode, *(uint32_t *)param, &bytestream)); break; case QTI_LINEAR_FORMAT: err = static_cast(android::gralloc4::encodeUint32( qtigralloc::MetadataType_LinearFormat, *(uint32_t *)param, &bytestream)); break; case QTI_SINGLE_BUFFER_MODE: err = static_cast(android::gralloc4::encodeUint32( qtigralloc::MetadataType_SingleBufferMode, *(uint32_t *)param, &bytestream)); break; case QTI_PP_PARAM_INTERLACED: err = static_cast(android::gralloc4::encodeInt32( qtigralloc::MetadataType_PPParamInterlaced, *(int32_t *)param, &bytestream)); break; case QTI_MAP_SECURE_BUFFER: err = static_cast(android::gralloc4::encodeInt32( qtigralloc::MetadataType_MapSecureBuffer, *(int32_t *)param, &bytestream)); break; case QTI_COLOR_METADATA: err = encodeColorMetadata(*(ColorMetaData *)param, &bytestream); break; case QTI_GRAPHICS_METADATA: err = encodeGraphicsMetadataRaw(param, &bytestream); break; case QTI_UBWC_CR_STATS_INFO: err = encodeUBWCStats((UBWCStats *)param, &bytestream); break; case QTI_REFRESH_RATE: err = static_cast(android::gralloc4::encodeFloat(qtigralloc::MetadataType_RefreshRate, *(float *)param, &bytestream)); break; case QTI_CVP_METADATA: err = encodeCVPMetadata(*(CVPMetadata *)param, &bytestream); break; case QTI_VIDEO_HISTOGRAM_STATS: err = encodeVideoHistogramMetadata(*(VideoHistogramMetadata *)param, &bytestream); break; case QTI_VIDEO_TS_INFO: err = encodeVideoTimestampInfo(*(VideoTimestampInfo *)param, &bytestream); break; default: param = nullptr; return Error::UNSUPPORTED; } if (err != Error::NONE) { return err; } return mapper->set((void *)buffer, metadata_type, bytestream); } int getMetadataState(void *buffer, uint32_t type) { bool metadata_set[METADATA_SET_SIZE]; Error err; if (IS_VENDOR_METADATA_TYPE(type)) { err = get(buffer, QTI_VENDOR_METADATA_STATUS, &metadata_set); } else { err = get(buffer, QTI_STANDARD_METADATA_STATUS, &metadata_set); } if (err != Error::NONE) { ALOGE("Unable to get metadata state"); return -1; } if (IS_VENDOR_METADATA_TYPE(type)) { return metadata_set[GET_VENDOR_METADATA_STATUS_INDEX(type)]; } else if (GET_STANDARD_METADATA_STATUS_INDEX(type) < METADATA_SET_SIZE) { return metadata_set[GET_STANDARD_METADATA_STATUS_INDEX(type)]; } else { return -1; } } } // namespace qtigralloc