/* * 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 #include "color_extensions.h" 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 decodeVideoTranscodeStatsMetadata(hidl_vec &in, VideoTranscodeStatsMetadata *out) { if (!in.size() || !out) { return Error::BAD_VALUE; } memcpy(out, in.data(), sizeof(VideoTranscodeStatsMetadata)); return Error::NONE; } Error encodeVideoTranscodeStatsMetadata(VideoTranscodeStatsMetadata &in, hidl_vec *out) { if (!out) { return Error::BAD_VALUE; } out->resize(sizeof(VideoTranscodeStatsMetadata)); memcpy(out->data(), &in, sizeof(VideoTranscodeStatsMetadata)); 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; } Error decodeCustomContentMetadata(hidl_vec &in, void *out) { static size_t target_size = sizeof(CustomContentMetadata); if (in.size() != target_size || !out) { return Error::BAD_VALUE; } CustomContentMetadata *c_md_in = reinterpret_cast(in.data()); CustomContentMetadata *c_md_out = reinterpret_cast(out); if (c_md_in->size > CUSTOM_METADATA_SIZE_BYTES) { return Error::BAD_VALUE; } c_md_out->size = c_md_in->size; memcpy(c_md_out->metadataPayload, c_md_in->metadataPayload, c_md_in->size); return Error::NONE; } Error encodeCustomContentMetadata(const void *in, hidl_vec *out) { static size_t target_size = sizeof(CustomContentMetadata); if (!in || !out) { return Error::BAD_VALUE; } out->resize(target_size); memcpy(out->data(), in, target_size); 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_TRANSCODE_STATS: return MetadataType_VideoTranscodeStats; 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; case QTI_TIMED_RENDERING: return MetadataType_TimedRendering; case QTI_CUSTOM_CONTENT_METADATA: return MetadataType_CustomContentMetadata; 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, reinterpret_cast(param))); break; case QTI_VIDEO_PERF_MODE: err = static_cast(android::gralloc4::decodeUint32( qtigralloc::MetadataType_VideoPerfMode, bytestream, reinterpret_cast(param))); break; case QTI_LINEAR_FORMAT: err = static_cast(android::gralloc4::decodeUint32( qtigralloc::MetadataType_LinearFormat, bytestream, reinterpret_cast(param))); break; case QTI_SINGLE_BUFFER_MODE: err = static_cast( android::gralloc4::decodeUint32(qtigralloc::MetadataType_SingleBufferMode, bytestream, reinterpret_cast(param))); break; case QTI_PP_PARAM_INTERLACED: err = static_cast( android::gralloc4::decodeInt32(qtigralloc::MetadataType_PPParamInterlaced, bytestream, reinterpret_cast(param))); break; case QTI_MAP_SECURE_BUFFER: err = static_cast( android::gralloc4::decodeInt32(qtigralloc::MetadataType_MapSecureBuffer, bytestream, reinterpret_cast(param))); break; case QTI_COLOR_METADATA: err = decodeColorMetadata(bytestream, reinterpret_cast(param)); break; case QTI_GRAPHICS_METADATA: err = decodeGraphicsMetadataRaw(bytestream, param); break; case QTI_UBWC_CR_STATS_INFO: err = decodeUBWCStats(bytestream, reinterpret_cast(param)); break; case QTI_REFRESH_RATE: err = static_cast(android::gralloc4::decodeFloat( qtigralloc::MetadataType_RefreshRate, bytestream, reinterpret_cast(param))); break; case QTI_CVP_METADATA: err = decodeCVPMetadata(bytestream, reinterpret_cast(param)); break; case QTI_VIDEO_HISTOGRAM_STATS: err = decodeVideoHistogramMetadata(bytestream, reinterpret_cast(param)); break; case QTI_VIDEO_TRANSCODE_STATS: err = decodeVideoTranscodeStatsMetadata(bytestream, reinterpret_cast(param)); break; case QTI_VIDEO_TS_INFO: err = decodeVideoTimestampInfo(bytestream, reinterpret_cast(param)); break; case QTI_FD: err = static_cast(android::gralloc4::decodeInt32( qtigralloc::MetadataType_FD, bytestream, reinterpret_cast(param))); break; case QTI_PRIVATE_FLAGS: err = static_cast(android::gralloc4::decodeInt32( qtigralloc::MetadataType_PrivateFlags, bytestream, reinterpret_cast(param))); break; case QTI_ALIGNED_WIDTH_IN_PIXELS: err = static_cast( android::gralloc4::decodeUint32(qtigralloc::MetadataType_AlignedWidthInPixels, bytestream, reinterpret_cast(param))); break; case QTI_ALIGNED_HEIGHT_IN_PIXELS: err = static_cast( android::gralloc4::decodeUint32(qtigralloc::MetadataType_AlignedHeightInPixels, bytestream, reinterpret_cast(param))); break; case QTI_STANDARD_METADATA_STATUS: case QTI_VENDOR_METADATA_STATUS: err = decodeMetadataState(bytestream, reinterpret_cast(param)); break; case QTI_BUFFER_TYPE: err = static_cast(android::gralloc4::decodeUint32( qtigralloc::MetadataType_BufferType, bytestream, reinterpret_cast(param))); break; case QTI_CUSTOM_DIMENSIONS_STRIDE: err = static_cast( android::gralloc4::decodeUint32(qtigralloc::MetadataType_CustomDimensionsStride, bytestream, reinterpret_cast(param))); break; case QTI_CUSTOM_DIMENSIONS_HEIGHT: err = static_cast( android::gralloc4::decodeUint32(qtigralloc::MetadataType_CustomDimensionsHeight, bytestream, reinterpret_cast(param))); break; case QTI_RGB_DATA_ADDRESS: err = static_cast( android::gralloc4::decodeUint64(qtigralloc::MetadataType_RgbDataAddress, bytestream, reinterpret_cast(param))); break; case QTI_COLORSPACE: err = static_cast(android::gralloc4::decodeUint32( qtigralloc::MetadataType_ColorSpace, bytestream, reinterpret_cast(param))); break; case QTI_YUV_PLANE_INFO: err = decodeYUVPlaneInfoMetadata(bytestream, reinterpret_cast(param)); break; case QTI_TIMED_RENDERING: err = static_cast(android::gralloc4::decodeUint32( qtigralloc::MetadataType_TimedRendering, bytestream, reinterpret_cast(param))); break; case QTI_CUSTOM_CONTENT_METADATA: err = decodeCustomContentMetadata(bytestream, 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, *reinterpret_cast(param), &bytestream)); break; case QTI_VIDEO_PERF_MODE: err = static_cast( android::gralloc4::encodeUint32(qtigralloc::MetadataType_VideoPerfMode, *reinterpret_cast(param), &bytestream)); break; case QTI_LINEAR_FORMAT: err = static_cast( android::gralloc4::encodeUint32(qtigralloc::MetadataType_LinearFormat, *reinterpret_cast(param), &bytestream)); break; case QTI_SINGLE_BUFFER_MODE: err = static_cast( android::gralloc4::encodeUint32(qtigralloc::MetadataType_SingleBufferMode, *reinterpret_cast(param), &bytestream)); break; case QTI_PP_PARAM_INTERLACED: err = static_cast( android::gralloc4::encodeInt32(qtigralloc::MetadataType_PPParamInterlaced, *reinterpret_cast(param), &bytestream)); break; case QTI_MAP_SECURE_BUFFER: err = static_cast( android::gralloc4::encodeInt32(qtigralloc::MetadataType_MapSecureBuffer, *reinterpret_cast(param), &bytestream)); break; case QTI_COLOR_METADATA: err = encodeColorMetadata(*reinterpret_cast(param), &bytestream); break; case QTI_GRAPHICS_METADATA: err = encodeGraphicsMetadataRaw(param, &bytestream); break; case QTI_UBWC_CR_STATS_INFO: err = encodeUBWCStats(reinterpret_cast(param), &bytestream); break; case QTI_REFRESH_RATE: err = static_cast(android::gralloc4::encodeFloat( qtigralloc::MetadataType_RefreshRate, *reinterpret_cast(param), &bytestream)); break; case QTI_CVP_METADATA: err = encodeCVPMetadata(*reinterpret_cast(param), &bytestream); break; case QTI_VIDEO_HISTOGRAM_STATS: err = encodeVideoHistogramMetadata(*reinterpret_cast(param), &bytestream); break; case QTI_VIDEO_TRANSCODE_STATS: err = encodeVideoTranscodeStatsMetadata( *reinterpret_cast(param), &bytestream); break; case QTI_VIDEO_TS_INFO: err = encodeVideoTimestampInfo(*reinterpret_cast(param), &bytestream); break; case QTI_TIMED_RENDERING: err = static_cast( android::gralloc4::encodeUint32(qtigralloc::MetadataType_TimedRendering, *reinterpret_cast(param), &bytestream)); break; case QTI_CUSTOM_CONTENT_METADATA: err = encodeCustomContentMetadata(param, &bytestream); break; default: param = nullptr; return Error::UNSUPPORTED; } if (err != Error::NONE) { return err; } return mapper->set(reinterpret_cast(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