summaryrefslogtreecommitdiff
path: root/libqdmetadata
diff options
context:
space:
mode:
Diffstat (limited to 'libqdmetadata')
-rw-r--r--libqdmetadata/Android.bp21
-rw-r--r--libqdmetadata/Makefile.am16
-rw-r--r--libqdmetadata/qdMetaData.cpp642
-rw-r--r--libqdmetadata/qd_utils.cpp279
4 files changed, 958 insertions, 0 deletions
diff --git a/libqdmetadata/Android.bp b/libqdmetadata/Android.bp
new file mode 100644
index 00000000..235fe653
--- /dev/null
+++ b/libqdmetadata/Android.bp
@@ -0,0 +1,21 @@
+cc_library_shared {
+ name: "libqdMetaData",
+ vendor: true,
+ cflags: [
+ "-Wno-sign-conversion",
+ "-DLOG_TAG=\"qdmetadata\"",
+ "-D__QTI_DISPLAY_GRALLOC__",
+ ],
+ shared_libs: [
+ "liblog",
+ "libcutils",
+ "libutils",
+ "libhidlbase",
+ "libgralloc.qti",
+ "libgralloctypes",
+ ],
+ header_libs: ["libhardware_headers", "display_intf_headers"],
+ srcs: ["qdMetaData.cpp", "qd_utils.cpp"],
+ export_header_lib_headers: ["display_intf_headers"],
+}
+
diff --git a/libqdmetadata/Makefile.am b/libqdmetadata/Makefile.am
new file mode 100644
index 00000000..1fa7e644
--- /dev/null
+++ b/libqdmetadata/Makefile.am
@@ -0,0 +1,16 @@
+h_sources = qdMetaData.h
+
+cpp_sources = qdMetaData.cpp
+
+AM_CPPFLAGS += -D__QTI_NO_GRALLOC4__
+
+qdMetaData_includedir = $(pkgincludedir)/display
+qdMetaData_include_HEADERS = $(h_sources)
+
+lib_LTLIBRARIES = libqdMetaData.la
+libqdMetaData_la_CC = @CC@
+libqdMetaData_la_SOURCES = $(cpp_sources)
+libqdMetaData_la_CFLAGS = $(AM_CFLAGS) -DLOG_TAG=\"DisplayMetaData\"
+libqdMetaData_la_CPPFLAGS = $(AM_CPPFLAGS)
+libqdMetaData_LDADD = -lcutils -llog
+libqdMetaData_la_LDFLAGS = -shared -avoid-version \ No newline at end of file
diff --git a/libqdmetadata/qdMetaData.cpp b/libqdmetadata/qdMetaData.cpp
new file mode 100644
index 00000000..228a634c
--- /dev/null
+++ b/libqdmetadata/qdMetaData.cpp
@@ -0,0 +1,642 @@
+/*
+ * Copyright (c) 2012-2021, 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 "qdMetaData.h"
+
+#include <QtiGrallocPriv.h>
+#include <errno.h>
+#include <gralloc_priv.h>
+#ifndef __QTI_NO_GRALLOC4__
+#include <gralloctypes/Gralloc4.h>
+#endif
+#include <log/log.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include <cinttypes>
+
+static int colorMetaDataToColorSpace(ColorMetaData in, ColorSpace_t *out) {
+ if (in.colorPrimaries == ColorPrimaries_BT601_6_525 ||
+ in.colorPrimaries == ColorPrimaries_BT601_6_625) {
+ if (in.range == Range_Full) {
+ *out = ITU_R_601_FR;
+ } else {
+ *out = ITU_R_601;
+ }
+ } else if (in.colorPrimaries == ColorPrimaries_BT2020) {
+ if (in.range == Range_Full) {
+ *out = ITU_R_2020_FR;
+ } else {
+ *out = ITU_R_2020;
+ }
+ } else if (in.colorPrimaries == ColorPrimaries_BT709_5) {
+ if (in.range == Range_Full) {
+ *out = ITU_R_709_FR;
+ } else {
+ *out = ITU_R_709;
+ }
+ } else {
+ ALOGE(
+ "Cannot convert ColorMetaData to ColorSpace_t. "
+ "Primaries = %d, Range = %d",
+ in.colorPrimaries, in.range);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int colorSpaceToColorMetadata(ColorSpace_t in, ColorMetaData *out) {
+ out->transfer = Transfer_sRGB;
+ switch (in) {
+ case ITU_R_601:
+ out->colorPrimaries = ColorPrimaries_BT601_6_525;
+ out->range = Range_Limited;
+ break;
+ case ITU_R_601_FR:
+ out->colorPrimaries = ColorPrimaries_BT601_6_525;
+ out->range = Range_Full;
+ break;
+ case ITU_R_709:
+ out->colorPrimaries = ColorPrimaries_BT709_5;
+ out->range = Range_Limited;
+ break;
+ case ITU_R_709_FR:
+ out->colorPrimaries = ColorPrimaries_BT709_5;
+ out->range = Range_Full;
+ break;
+ case ITU_R_2020:
+ out->colorPrimaries = ColorPrimaries_BT2020;
+ out->range = Range_Limited;
+ break;
+ case ITU_R_2020_FR:
+ out->colorPrimaries = ColorPrimaries_BT2020;
+ out->range = Range_Full;
+ break;
+ default:
+ ALOGE("Cannot convert ColorSpace_t %d to ColorMetaData", in);
+ return -1;
+ break;
+ }
+
+ return 0;
+}
+
+#ifndef __QTI_NO_GRALLOC4__
+static bool getGralloc4Array(MetaData_t *metadata, int32_t paramType) {
+ switch (paramType) {
+ case SET_VT_TIMESTAMP:
+ return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VT_TIMESTAMP)];
+ case COLOR_METADATA:
+ return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)];
+ case PP_PARAM_INTERLACED:
+ return metadata
+ ->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_PP_PARAM_INTERLACED)];
+ case SET_VIDEO_PERF_MODE:
+ return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_PERF_MODE)];
+ case SET_GRAPHICS_METADATA:
+ return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_GRAPHICS_METADATA)];
+ case SET_UBWC_CR_STATS_INFO:
+ return metadata
+ ->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_UBWC_CR_STATS_INFO)];
+ case UPDATE_BUFFER_GEOMETRY:
+ return metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(
+ ::android::gralloc4::MetadataType_Crop.value)];
+ case UPDATE_REFRESH_RATE:
+ return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_REFRESH_RATE)];
+ case UPDATE_COLOR_SPACE:
+ return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)];
+ case MAP_SECURE_BUFFER:
+ return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_MAP_SECURE_BUFFER)];
+ case LINEAR_FORMAT:
+ return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_LINEAR_FORMAT)];
+ case SET_SINGLE_BUFFER_MODE:
+ return metadata
+ ->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_SINGLE_BUFFER_MODE)];
+ case SET_CVP_METADATA:
+ return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_CVP_METADATA)];
+ case SET_VIDEO_HISTOGRAM_STATS:
+ return metadata
+ ->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_HISTOGRAM_STATS)];
+ case SET_VIDEO_TS_INFO:
+ return metadata
+ ->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_TS_INFO)];
+ case GET_S3D_FORMAT:
+ return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_S3D_FORMAT)];
+ default:
+ ALOGE("paramType %d not supported", paramType);
+ return false;
+ }
+}
+
+static void setGralloc4Array(MetaData_t *metadata, int32_t paramType, bool isSet) {
+ switch (paramType) {
+ case SET_VT_TIMESTAMP:
+ metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VT_TIMESTAMP)] = isSet;
+ break;
+ case COLOR_METADATA:
+ metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)] = isSet;
+ break;
+ case PP_PARAM_INTERLACED:
+ metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_PP_PARAM_INTERLACED)] =
+ isSet;
+ break;
+ case SET_VIDEO_PERF_MODE:
+ metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_PERF_MODE)] = isSet;
+ break;
+ case SET_GRAPHICS_METADATA:
+ metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_GRAPHICS_METADATA)] =
+ isSet;
+ break;
+ case SET_UBWC_CR_STATS_INFO:
+ metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_UBWC_CR_STATS_INFO)] =
+ isSet;
+ break;
+ case UPDATE_BUFFER_GEOMETRY:
+ metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(
+ ::android::gralloc4::MetadataType_Crop.value)] = isSet;
+ break;
+ case UPDATE_REFRESH_RATE:
+ metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_REFRESH_RATE)] = isSet;
+ break;
+ case UPDATE_COLOR_SPACE:
+ metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)] = isSet;
+ break;
+ case MAP_SECURE_BUFFER:
+ metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_MAP_SECURE_BUFFER)] =
+ isSet;
+ break;
+ case LINEAR_FORMAT:
+ metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_LINEAR_FORMAT)] = isSet;
+ break;
+ case SET_SINGLE_BUFFER_MODE:
+ metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_SINGLE_BUFFER_MODE)] =
+ isSet;
+ break;
+ case SET_CVP_METADATA:
+ metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_CVP_METADATA)] = isSet;
+ break;
+ case SET_VIDEO_HISTOGRAM_STATS:
+ metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_HISTOGRAM_STATS)] =
+ isSet;
+ break;
+ case SET_VIDEO_TS_INFO:
+ metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_TS_INFO)] =
+ isSet;
+ break;
+ case S3D_FORMAT:
+ metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_S3D_FORMAT)] = isSet;
+ break;
+ default:
+ ALOGE("paramType %d not supported in Gralloc4", paramType);
+ }
+}
+#else
+static bool getGralloc4Array(MetaData_t *metadata, int32_t paramType) {
+ return true;
+}
+
+static void setGralloc4Array(MetaData_t *metadata, int32_t paramType, bool isSet) {
+}
+#endif
+
+
+unsigned long getMetaDataSize() {
+ return static_cast<unsigned long>(ROUND_UP_PAGESIZE(sizeof(MetaData_t)));
+}
+
+// Cannot add default argument to existing function
+unsigned long getMetaDataSizeWithReservedRegion(uint64_t reserved_size) {
+ return static_cast<unsigned long>(ROUND_UP_PAGESIZE(sizeof(MetaData_t) + reserved_size));
+}
+
+static int validateAndMap(private_handle_t* handle) {
+ if (private_handle_t::validate(handle)) {
+ ALOGE("%s: Private handle is invalid - handle:%p", __func__, handle);
+ return -1;
+ }
+ if (handle->fd_metadata < 0) {
+ // Metadata cannot be used
+ return -1;
+ }
+
+ if (!handle->base_metadata) {
+ auto size = getMetaDataSize();
+ void *base = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
+ handle->fd_metadata, 0);
+ if (base == reinterpret_cast<void*>(MAP_FAILED)) {
+ ALOGE("%s: metadata mmap failed - handle:%p fd: %d err: %s",
+ __func__, handle, handle->fd_metadata, strerror(errno));
+ return -1;
+ }
+ handle->base_metadata = (uintptr_t) base;
+ auto metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
+ if (metadata->reservedSize) {
+ auto reserved_size = metadata->reservedSize;
+ munmap(reinterpret_cast<void *>(handle->base_metadata), getMetaDataSize());
+ handle->base_metadata = 0;
+ size = getMetaDataSizeWithReservedRegion(reserved_size);
+ void *new_base =
+ mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd_metadata, 0);
+ if (new_base == reinterpret_cast<void *>(MAP_FAILED)) {
+ ALOGE("%s: metadata mmap failed - handle:%p fd: %d err: %s", __func__, handle,
+ handle->fd_metadata, strerror(errno));
+ return -1;
+ }
+ handle->base_metadata = (uintptr_t)new_base;
+ }
+ }
+ return 0;
+}
+
+static void unmapAndReset(private_handle_t *handle) {
+ if (private_handle_t::validate(handle) == 0 && handle->base_metadata) {
+ // If reservedSize is 0, the return value will be the same as getMetaDataSize
+ auto metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
+ auto size = getMetaDataSizeWithReservedRegion(metadata->reservedSize);
+ munmap(reinterpret_cast<void *>(handle->base_metadata), size);
+ handle->base_metadata = 0;
+ }
+}
+
+int setMetaData(private_handle_t *handle, DispParamType paramType,
+ void *param) {
+ auto err = validateAndMap(handle);
+ if (err != 0)
+ return err;
+ return setMetaDataVa(reinterpret_cast<MetaData_t*>(handle->base_metadata),
+ paramType, param);
+}
+
+int setMetaDataVa(MetaData_t *data, DispParamType paramType,
+ void *param) {
+ if (data == nullptr)
+ return -EINVAL;
+ // If parameter is NULL reset the specific MetaData Key
+ if (!param) {
+ setGralloc4Array(data, paramType, false);
+ switch (paramType) {
+ case SET_VIDEO_PERF_MODE:
+ data->isVideoPerfMode = 0;
+ break;
+ case SET_CVP_METADATA:
+ data->cvpMetadata.size = 0;
+ break;
+ case SET_VIDEO_HISTOGRAM_STATS:
+ data->video_histogram_stats.stat_len = 0;
+ break;
+ default:
+ ALOGE("Unknown paramType %d", paramType);
+ break;
+ }
+ // param unset
+ return 0;
+ }
+
+ setGralloc4Array(data, paramType, true);
+ switch (paramType) {
+ case PP_PARAM_INTERLACED:
+ data->interlaced = *((int32_t *)param);
+ break;
+ case UPDATE_BUFFER_GEOMETRY: {
+ BufferDim_t in = *((BufferDim_t *)param);
+ data->crop = {0, 0, in.sliceWidth, in.sliceHeight};
+ break;
+ }
+ case UPDATE_REFRESH_RATE:
+ data->refreshrate = *((float *)param);
+ break;
+ case UPDATE_COLOR_SPACE: {
+ ColorMetaData color = {};
+ if (!colorSpaceToColorMetadata(*((ColorSpace_t *)param), &color)) {
+ data->color = color;
+ break;
+ }
+ return -EINVAL;
+ }
+ case MAP_SECURE_BUFFER:
+ data->mapSecureBuffer = *((int32_t *)param);
+ break;
+ case S3D_FORMAT:
+ data->s3dFormat = *((uint32_t *)param);
+ break;
+ case LINEAR_FORMAT:
+ data->linearFormat = *((uint32_t *)param);
+ break;
+ case SET_SINGLE_BUFFER_MODE:
+ data->isSingleBufferMode = *((uint32_t *)param);
+ break;
+ case SET_VT_TIMESTAMP:
+ data->vtTimeStamp = *((uint64_t *)param);
+ break;
+ case COLOR_METADATA:
+ data->color = *((ColorMetaData *)param);
+ break;
+ case SET_UBWC_CR_STATS_INFO: {
+ struct UBWCStats *stats = (struct UBWCStats *)param;
+ int numelems = sizeof(data->ubwcCRStats) / sizeof(struct UBWCStats);
+ for (int i = 0; i < numelems; i++) {
+ data->ubwcCRStats[i] = stats[i];
+ }
+ break;
+ }
+ case SET_VIDEO_PERF_MODE:
+ data->isVideoPerfMode = *((uint32_t *)param);
+ break;
+ case SET_GRAPHICS_METADATA: {
+ GraphicsMetadata payload = *((GraphicsMetadata*)(param));
+ data->graphics_metadata.size = payload.size;
+ memcpy(data->graphics_metadata.data, payload.data,
+ sizeof(data->graphics_metadata.data));
+ break;
+ }
+ case SET_CVP_METADATA: {
+ struct CVPMetadata *cvpMetadata = (struct CVPMetadata *)param;
+ if (cvpMetadata->size <= CVP_METADATA_SIZE) {
+ data->cvpMetadata.size = cvpMetadata->size;
+ memcpy(data->cvpMetadata.payload, cvpMetadata->payload,
+ cvpMetadata->size);
+ data->cvpMetadata.capture_frame_rate = cvpMetadata->capture_frame_rate;
+ data->cvpMetadata.cvp_frame_rate = cvpMetadata->cvp_frame_rate;
+ data->cvpMetadata.flags = cvpMetadata->flags;
+ memcpy(data->cvpMetadata.reserved, cvpMetadata->reserved,
+ (8 * sizeof(uint32_t)));
+ } else {
+ setGralloc4Array(data, paramType, false);
+ ALOGE("%s: cvp metadata length %d is more than max size %d", __func__,
+ cvpMetadata->size, CVP_METADATA_SIZE);
+ return -EINVAL;
+ }
+ break;
+ }
+ case SET_VIDEO_HISTOGRAM_STATS: {
+ struct VideoHistogramMetadata *vidstats = (struct VideoHistogramMetadata *)param;
+ if (vidstats->stat_len <= VIDEO_HISTOGRAM_STATS_SIZE) {
+ memcpy(data->video_histogram_stats.stats_info,
+ vidstats->stats_info, VIDEO_HISTOGRAM_STATS_SIZE);
+ data->video_histogram_stats.stat_len = vidstats->stat_len;
+ data->video_histogram_stats.frame_type = vidstats->frame_type;
+ data->video_histogram_stats.display_width = vidstats->display_width;
+ data->video_histogram_stats.display_height = vidstats->display_height;
+ data->video_histogram_stats.decode_width = vidstats->decode_width;
+ data->video_histogram_stats.decode_height = vidstats->decode_height;
+ } else {
+ setGralloc4Array(data, paramType, false);
+ ALOGE("%s: video stats length %u is more than max size %u", __func__,
+ vidstats->stat_len, VIDEO_HISTOGRAM_STATS_SIZE);
+ return -EINVAL;
+ }
+ break;
+ }
+ case SET_VIDEO_TS_INFO:
+ data->videoTsInfo = *((VideoTimestampInfo *)param);
+ break;
+ default:
+ ALOGE("Unknown paramType %d", paramType);
+ break;
+ }
+ return 0;
+}
+
+int clearMetaData(private_handle_t *handle, DispParamType paramType) {
+ auto err = validateAndMap(handle);
+ if (err != 0)
+ return err;
+ return clearMetaDataVa(reinterpret_cast<MetaData_t *>(handle->base_metadata),
+ paramType);
+}
+
+int clearMetaDataVa(MetaData_t *data, DispParamType paramType) {
+ if (data == nullptr)
+ return -EINVAL;
+ data->operation &= ~paramType;
+ switch (paramType) {
+ case SET_VIDEO_PERF_MODE:
+ data->isVideoPerfMode = 0;
+ break;
+ case SET_CVP_METADATA:
+ data->cvpMetadata.size = 0;
+ break;
+ case SET_VIDEO_HISTOGRAM_STATS:
+ data->video_histogram_stats.stat_len = 0;
+ break;
+ default:
+ ALOGE("Unknown paramType %d", paramType);
+ break;
+ }
+ return 0;
+}
+
+int getMetaData(private_handle_t *handle, DispFetchParamType paramType,
+ void *param) {
+ int ret = validateAndMap(handle);
+ if (ret != 0)
+ return ret;
+ return getMetaDataVa(reinterpret_cast<MetaData_t *>(handle->base_metadata),
+ paramType, param);
+}
+
+int getMetaDataVa(MetaData_t *data, DispFetchParamType paramType,
+ void *param) {
+ // Make sure we send 0 only if the operation queried is present
+ int ret = -EINVAL;
+ if (data == nullptr)
+ return ret;
+ if (param == nullptr)
+ return ret;
+
+ if (!getGralloc4Array(data, paramType)) {
+ return ret;
+ }
+
+ ret = 0;
+
+ switch (paramType) {
+ case GET_PP_PARAM_INTERLACED:
+ *((int32_t *)param) = data->interlaced;
+ break;
+ case GET_BUFFER_GEOMETRY:
+ *((BufferDim_t *)param) = {data->crop.right, data->crop.bottom};
+ break;
+ case GET_REFRESH_RATE:
+ *((float *)param) = data->refreshrate;
+ break;
+ case GET_COLOR_SPACE: {
+ ColorSpace_t color_space;
+ if (!colorMetaDataToColorSpace(data->color, &color_space)) {
+ *((ColorSpace_t *)param) = color_space;
+ } else {
+ ret = -EINVAL;
+ }
+ break;
+ }
+ case GET_MAP_SECURE_BUFFER:
+ *((int32_t *)param) = data->mapSecureBuffer;
+ break;
+ case GET_S3D_FORMAT:
+ *((uint32_t *)param) = data->s3dFormat;
+ break;
+ case GET_LINEAR_FORMAT:
+ *((uint32_t *)param) = data->linearFormat;
+ break;
+ case GET_SINGLE_BUFFER_MODE:
+ *((uint32_t *)param) = data->isSingleBufferMode;
+ break;
+ case GET_VT_TIMESTAMP:
+ *((uint64_t *)param) = data->vtTimeStamp;
+ break;
+ case GET_COLOR_METADATA:
+ *((ColorMetaData *)param) = data->color;
+ break;
+ case GET_UBWC_CR_STATS_INFO: {
+ struct UBWCStats *stats = (struct UBWCStats *)param;
+ int numelems = sizeof(data->ubwcCRStats) / sizeof(struct UBWCStats);
+ for (int i = 0; i < numelems; i++) {
+ stats[i] = data->ubwcCRStats[i];
+ }
+ break;
+ }
+ case GET_VIDEO_PERF_MODE:
+ *((uint32_t *)param) = data->isVideoPerfMode;
+ break;
+ case GET_GRAPHICS_METADATA:
+ memcpy(param, data->graphics_metadata.data, sizeof(data->graphics_metadata.data));
+ break;
+ case GET_CVP_METADATA: {
+ struct CVPMetadata *cvpMetadata = (struct CVPMetadata *)param;
+ cvpMetadata->size = 0;
+ if (data->cvpMetadata.size <= CVP_METADATA_SIZE) {
+ cvpMetadata->size = data->cvpMetadata.size;
+ memcpy(cvpMetadata->payload, data->cvpMetadata.payload, data->cvpMetadata.size);
+ cvpMetadata->capture_frame_rate = data->cvpMetadata.capture_frame_rate;
+ cvpMetadata->cvp_frame_rate = data->cvpMetadata.cvp_frame_rate;
+ cvpMetadata->flags = data->cvpMetadata.flags;
+ memcpy(cvpMetadata->reserved, data->cvpMetadata.reserved, (8 * sizeof(uint32_t)));
+ } else {
+ ret = -EINVAL;
+ }
+ break;
+ }
+ case GET_VIDEO_HISTOGRAM_STATS: {
+ struct VideoHistogramMetadata *vidstats = (struct VideoHistogramMetadata *)param;
+ vidstats->stat_len = 0;
+ if (data->video_histogram_stats.stat_len <= VIDEO_HISTOGRAM_STATS_SIZE) {
+ memcpy(vidstats->stats_info, data->video_histogram_stats.stats_info,
+ VIDEO_HISTOGRAM_STATS_SIZE);
+ vidstats->stat_len = data->video_histogram_stats.stat_len;
+ vidstats->frame_type = data->video_histogram_stats.frame_type;
+ vidstats->display_width = data->video_histogram_stats.display_width;
+ vidstats->display_height = data->video_histogram_stats.display_height;
+ vidstats->decode_width = data->video_histogram_stats.decode_width;
+ vidstats->decode_height = data->video_histogram_stats.decode_height;
+ } else {
+ ret = -EINVAL;
+ }
+ break;
+ }
+ case GET_VIDEO_TS_INFO:
+ *((VideoTimestampInfo *)param) = data->videoTsInfo;
+ break;
+ default:
+ ALOGE("Unknown paramType %d", paramType);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+int copyMetaData(struct private_handle_t *src, struct private_handle_t *dst) {
+ auto err = validateAndMap(src);
+ if (err != 0)
+ return err;
+
+ err = validateAndMap(dst);
+ if (err != 0)
+ return err;
+
+ MetaData_t *src_data = reinterpret_cast <MetaData_t *>(src->base_metadata);
+ MetaData_t *dst_data = reinterpret_cast <MetaData_t *>(dst->base_metadata);
+ *dst_data = *src_data;
+ return 0;
+}
+
+int copyMetaDataVaToHandle(MetaData_t *src_data, struct private_handle_t *dst) {
+ int err = -EINVAL;
+ if (src_data == nullptr)
+ return err;
+
+ err = validateAndMap(dst);
+ if (err != 0)
+ return err;
+
+ MetaData_t *dst_data = reinterpret_cast <MetaData_t *>(dst->base_metadata);
+ *dst_data = *src_data;
+ return 0;
+}
+
+int copyMetaDataHandleToVa(struct private_handle_t *src, MetaData_t *dst_data) {
+ int err = -EINVAL;
+ if (dst_data == nullptr)
+ return err;
+
+ err = validateAndMap(src);
+ if (err != 0)
+ return err;
+
+ MetaData_t *src_data = reinterpret_cast <MetaData_t *>(src->base_metadata);
+ *dst_data = *src_data;
+ return 0;
+}
+
+int copyMetaDataVaToVa(MetaData_t *src_data, MetaData_t *dst_data) {
+ int err = -EINVAL;
+ if (src_data == nullptr)
+ return err;
+
+ if (dst_data == nullptr)
+ return err;
+
+ *dst_data = *src_data;
+ return 0;
+}
+
+int setMetaDataAndUnmap(struct private_handle_t *handle, enum DispParamType paramType,
+ void *param) {
+ auto ret = setMetaData(handle, paramType, param);
+ unmapAndReset(handle);
+ return ret;
+}
+
+int getMetaDataAndUnmap(struct private_handle_t *handle,
+ enum DispFetchParamType paramType,
+ void *param) {
+ auto ret = getMetaData(handle, paramType, param);
+ unmapAndReset(handle);
+ return ret;
+}
diff --git a/libqdmetadata/qd_utils.cpp b/libqdmetadata/qd_utils.cpp
new file mode 100644
index 00000000..ac5d094b
--- /dev/null
+++ b/libqdmetadata/qd_utils.cpp
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2013, 2018, 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 <unistd.h>
+#include <gralloc_priv.h>
+#include "qd_utils.h"
+
+static const int kFBNodeMax = 4;
+namespace qdutils {
+
+static int parseLine(char *input, char *tokens[], const uint32_t maxToken, uint32_t *count) {
+ char *tmpToken = NULL;
+ char *tmpPtr;
+ uint32_t index = 0;
+ const char *delim = ", =\n";
+ if (!input) {
+ return -1;
+ }
+ tmpToken = strtok_r(input, delim, &tmpPtr);
+ while (tmpToken && index < maxToken) {
+ tokens[index++] = tmpToken;
+ tmpToken = strtok_r(NULL, delim, &tmpPtr);
+ }
+ *count = index;
+
+ return 0;
+}
+
+static int getExternalNode(const char *type) {
+ FILE *displayDeviceFP = NULL;
+ char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
+ char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
+ int j = 0;
+
+ for(j = 0; j < kFBNodeMax; j++) {
+ snprintf (msmFbTypePath, sizeof(msmFbTypePath),
+ "/sys/devices/virtual/graphics/fb%d/msm_fb_type", j);
+ displayDeviceFP = fopen(msmFbTypePath, "r");
+ if(displayDeviceFP) {
+ fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
+ displayDeviceFP);
+ if(strncmp(fbType, type, strlen(type)) == 0) {
+ ALOGD("%s: %s is at fb%d", __func__, type, j);
+ fclose(displayDeviceFP);
+ break;
+ }
+ fclose(displayDeviceFP);
+ } else {
+ ALOGE("%s: Failed to open fb node %s", __func__, msmFbTypePath);
+ }
+ }
+
+ if (j < kFBNodeMax)
+ return j;
+ else
+ ALOGE("%s: Failed to find %s node", __func__, type);
+
+ return -1;
+}
+
+int getHDMINode(void) {
+ return getExternalNode("dtv panel");
+}
+
+int getEdidRawData(char *buffer)
+{
+ int size;
+ int edidFile;
+ char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
+ int node_id = getHDMINode();
+
+ if (node_id < 0) {
+ ALOGE("%s no HDMI node found", __func__);
+ return 0;
+ }
+
+ snprintf(msmFbTypePath, sizeof(msmFbTypePath),
+ "/sys/devices/virtual/graphics/fb%d/edid_raw_data", node_id);
+
+ edidFile = open(msmFbTypePath, O_RDONLY, 0);
+
+ if (edidFile < 0) {
+ ALOGE("%s no edid raw data found %s", __func__,msmFbTypePath);
+ return 0;
+ }
+
+ size = (int)read(edidFile, (char*)buffer, EDID_RAW_DATA_SIZE);
+ close(edidFile);
+ return size;
+}
+
+bool isDPConnected() {
+ char connectPath[MAX_FRAME_BUFFER_NAME_SIZE];
+ FILE *connectFile = NULL;
+ size_t len = MAX_STRING_LENGTH;
+ char stringBuffer[MAX_STRING_LENGTH];
+ char *line = stringBuffer;
+
+ int nodeId = getExternalNode("dp panel");
+ if (nodeId < 0) {
+ ALOGE("%s no DP node found", __func__);
+ return false;
+ }
+
+ snprintf(connectPath, sizeof(connectPath),
+ "/sys/devices/virtual/graphics/fb%d/connected", nodeId);
+
+ connectFile = fopen(connectPath, "rb");
+ if (!connectFile) {
+ ALOGW("Failed to open connect node for device node %s", connectPath);
+ return false;
+ }
+
+ if (getline(&line, &len, connectFile) < 0) {
+ fclose(connectFile);
+ return false;
+ }
+
+ fclose(connectFile);
+
+ return atoi(line);
+}
+
+int getDPTestConfig(uint32_t *panelBpp, uint32_t *patternType) {
+ if (!panelBpp || !patternType) {
+ return -1;
+ }
+
+ char configPath[MAX_FRAME_BUFFER_NAME_SIZE];
+ FILE *configFile = NULL;
+ uint32_t tokenCount = 0;
+ const uint32_t maxCount = 10;
+ char *tokens[maxCount] = { NULL };
+ size_t len = MAX_STRING_LENGTH;
+ char stringBuffer[MAX_STRING_LENGTH];
+ char *line = stringBuffer;
+
+ int nodeId = getExternalNode("dp panel");
+ if (nodeId < 0) {
+ ALOGE("%s no DP node found", __func__);
+ return -EINVAL;
+ }
+
+ snprintf(configPath, sizeof(configPath),
+ "/sys/devices/virtual/graphics/fb%d/config", nodeId);
+
+ configFile = fopen(configPath, "rb");
+ if (!configFile) {
+ ALOGW("Failed to open config node for device node %s", configPath);
+ return -EINVAL;
+ }
+
+ while (getline(&line, &len, configFile) != -1) {
+ if (!parseLine(line, tokens, maxCount, &tokenCount)) {
+ if (tokens[0] != NULL) {
+ if (!strncmp(tokens[0], "bpp", strlen("bpp"))) {
+ *panelBpp = static_cast<uint32_t>(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "pattern", strlen("pattern"))) {
+ *patternType = static_cast<uint32_t>(atoi(tokens[1]));
+ }
+ }
+ }
+ }
+
+ fclose(configFile);
+
+ return 0;
+}
+
+DriverType getDriverType() {
+ const char *fb_caps = "/sys/devices/virtual/graphics/fb0/mdp/caps";
+ // 0 - File exists
+ return access(fb_caps, F_OK) ? DriverType::DRM : DriverType::FB;
+}
+
+const char *GetHALPixelFormatString(int format) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ return "RGBA_8888";
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ return "RGBX_8888";
+ case HAL_PIXEL_FORMAT_RGB_888:
+ return "RGB_888";
+ case HAL_PIXEL_FORMAT_RGB_565:
+ return "RGB_565";
+ case HAL_PIXEL_FORMAT_BGR_565:
+ return "BGR_565";
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ return "BGRA_8888";
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ return "RGBA_5551";
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ return "RGBA_4444";
+ case HAL_PIXEL_FORMAT_YV12:
+ return "YV12";
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ return "YCbCr_422_SP_NV16";
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ return "YCrCb_420_SP_NV21";
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ return "YCbCr_422_I_YUY2";
+ case HAL_PIXEL_FORMAT_YCrCb_422_I:
+ return "YCrCb_422_I_YVYU";
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ return "NV12_ENCODEABLE";
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+ return "YCbCr_420_SP_TILED_TILE_4x2";
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ return "YCbCr_420_SP";
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+ return "YCrCb_420_SP_ADRENO";
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ return "YCrCb_422_SP";
+ case HAL_PIXEL_FORMAT_R_8:
+ return "R_8";
+ case HAL_PIXEL_FORMAT_RG_88:
+ return "RG_88";
+ case HAL_PIXEL_FORMAT_INTERLACE:
+ return "INTERLACE";
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ return "YCbCr_420_SP_VENUS";
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+ return "YCrCb_420_SP_VENUS";
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ return "YCbCr_420_SP_VENUS_UBWC";
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ return "RGBA_1010102";
+ case HAL_PIXEL_FORMAT_ARGB_2101010:
+ return "ARGB_2101010";
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ return "RGBX_1010102";
+ case HAL_PIXEL_FORMAT_XRGB_2101010:
+ return "XRGB_2101010";
+ case HAL_PIXEL_FORMAT_BGRA_1010102:
+ return "BGRA_1010102";
+ case HAL_PIXEL_FORMAT_ABGR_2101010:
+ return "ABGR_2101010";
+ case HAL_PIXEL_FORMAT_BGRX_1010102:
+ return "BGRX_1010102";
+ case HAL_PIXEL_FORMAT_XBGR_2101010:
+ return "XBGR_2101010";
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+ return "YCbCr_420_P010";
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ return "YCbCr_420_TP10_UBWC";
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_VENUS:
+ return "YCbCr_420_P010_VENUS";
+ default:
+ return "Unknown_format";
+ }
+}
+
+}; //namespace qdutils