Files
2026-08-24 10:03:24 +08:00

532 lines
15 KiB
C++

/*
* Copyright (c) 2014 Amlogic, Inc. All rights reserved.
*
* This source code is subject to the terms and conditions defined in the
* file 'LICENSE' which is part of this source code package.
*
* Description: c++ file
*/
#define LOG_MODULE_TAG "PQ"
#define LOG_CLASS_TAG "CDolbyVision"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include "CPQLog.h"
#include "CAmdolbyVision.h"
CDolbyVision::CDolbyVision(const char *binFilePath, const char *cfgFilePath) {
//open dolby vision module
mDVDevFd = DV_OpenModule();
//load dv cfg file
SetAmdolbyDvCfg(cfgFilePath);
SetAmdolbyDvCfgBin(binFilePath);
}
CDolbyVision::~CDolbyVision() {
DV_CloseModule();
}
int CDolbyVision::ReadSysfs(const char *path, char *buf, int count)
{
int fd, len;
if ( NULL == buf ) {
LOGE("%s buf is NULL.\n", __FUNCTION__);
return -1;
}
if ((fd = open(path, O_RDONLY)) < 0) {
LOGE("%s open %s error(%s).\n", __FUNCTION__, path, strerror (errno));
return -1;
}
len = read(fd, buf, count);
if (len < 0) {
LOGE("%s read %s error(%s).\n", __FUNCTION__, path, strerror(errno));
close(fd);
return len;
}
int i , j;
for (i = 0, j = 0; i <= len -1; i++) {
//change '\0' to 0x20(spacing), otherwise the string buffer will be cut off ,if the last char is '\0' should not replace it
if (0x0 == buf[i] && i < len - 1) {
buf[i] = 0x20;
}
/* delete all the character of '\n' */
if (0x0a != buf[i]) {
buf[j++] = buf[i];
}
}
buf[j] = 0x0;
close(fd);
return len;
}
int CDolbyVision::ReadFile(unsigned char **result, const char *fileName)
{
if (fileName == NULL) {
LOGE("%s fileName %s is null!\n", __FUNCTION__, fileName);
return 0;
}
if (result == NULL) {
LOGE("%s result pointer is null!\n", __FUNCTION__);
return 0;
}
FILE *filePointer = fopen(fileName, "rb");
if (!filePointer) {
LOGE("%s fopen %s failed: %s\n", __FUNCTION__, fileName, strerror(errno));
return 0;
}
struct stat fileInfo;
if (stat(fileName, &fileInfo) != 0) {
LOGE("%s stat %s failed: %s\n", __FUNCTION__, fileName, strerror(errno));
fclose(filePointer);
return 0;
}
if (fileInfo.st_size <= 0) {
LOGE("%s invalid file size: %ld\n", __FUNCTION__, fileInfo.st_size);
fclose(filePointer);
return 0;
}
unsigned char *fileData = (unsigned char*)malloc(fileInfo.st_size);
if (fileData == NULL) {
LOGE("%s malloc failed for size %ld\n", __FUNCTION__, fileInfo.st_size);
fclose(filePointer);
return 0;
}
size_t bytesRead = fread(fileData, 1, fileInfo.st_size, filePointer);
if (bytesRead != (size_t)fileInfo.st_size) {
LOGE("%s fread failed: expected %ld bytes, got %zu bytes\n", __FUNCTION__, fileInfo.st_size, bytesRead);
free(fileData);
fclose(filePointer);
return 0;
}
fclose(filePointer);
*result = fileData;
LOGD("%s fileInfo.st_size %ld\n", __FUNCTION__, fileInfo.st_size);
return (int)fileInfo.st_size;
}
int CDolbyVision::DV_OpenModule()
{
int fd = open(DV_DEV_PATH, O_RDWR);
if ( fd < 0 ) {
LOGE("Open %s error(%s)!\n", DV_DEV_PATH, strerror(errno));
return -1;
} else {
LOGD("Open amdolby_vision module success!\n");
}
return fd;
}
int CDolbyVision::DV_CloseModule()
{
if (mDVDevFd != -1) {
close ( mDVDevFd );
mDVDevFd = -1;
}
return 0;
}
int CDolbyVision::DV_DeviceIOCtl( int request, ... )
{
int ret = -1;
va_list ap;
void *arg;
if (mDVDevFd < 0) {
mDVDevFd = DV_OpenModule();
}
if (mDVDevFd >= 0) {
va_start(ap, request);
arg = va_arg(ap, void *);
va_end(ap);
ret = ioctl(mDVDevFd, request, arg );
if (ret < 0) {
LOGD("%s failed(%s)!\n", __FUNCTION__, strerror(errno));
} else {
LOGD("%s success!\n", __FUNCTION__);
}
}
return ret;
}
int CDolbyVision::SetAmdolbyCfgFile(const char *binFilePath, const char *cfgFilePath) {
struct dv_config_file_s amdolbyCfgFile;
memset(&amdolbyCfgFile, 0, sizeof(struct dv_config_file_s));
if ((binFilePath == NULL) || (cfgFilePath == NULL)) {
LOGD("%s: file path invalid\n", __FUNCTION__);
return -1;
} else {
strncpy((char*)amdolbyCfgFile.bin_name, binFilePath, 255);
strncpy((char*)amdolbyCfgFile.cfg_name, cfgFilePath, 255);
}
LOGD("%s: bin_name=%s, cfg_name=%s.\n", __FUNCTION__, amdolbyCfgFile.bin_name, amdolbyCfgFile.cfg_name);
int ret = DV_DeviceIOCtl(DV_IOC_SET_DV_CONFIG_FILE, &amdolbyCfgFile);
if (ret < 0) {
LOGD("%s failed!\n", __FUNCTION__);
} else {
LOGD("%s success!\n", __FUNCTION__);
}
return ret;
}
int CDolbyVision::SetAmdolbyPQMode(dolby_pq_mode_t mode) {
LOGD("%s mode is %d\n", __FUNCTION__, mode);
int ret = DV_DeviceIOCtl(DV_IOC_SET_DV_PIC_MODE_ID, &mode);
if (ret < 0) {
LOGD("%s failed!\n", __FUNCTION__);
} else {
LOGD("%s success!\n", __FUNCTION__);
}
return ret;
}
dolby_pq_mode_t CDolbyVision::GetAmdolbyPQMode(void) {
dolby_pq_mode_t amdolbyPQmode = DOLBY_PQ_MODE_BRIGHT_DV;
int ret = DV_DeviceIOCtl(DV_IOC_GET_DV_PIC_MODE_ID, &amdolbyPQmode);
if (ret < 0) {
LOGD("%s failed!\n", __FUNCTION__);
amdolbyPQmode = DOLBY_PQ_MODE_BRIGHT_DV;
} else {
LOGD("%s success, mode is %d!\n", __FUNCTION__, amdolbyPQmode);
}
return amdolbyPQmode;
}
int CDolbyVision::SetAmdolbyPQParam(dolby_pq_mode_t mode, enum pq_item_e iteamID, int value) {
struct dv_pq_info_s amdolbyPQInfo;
memset(&amdolbyPQInfo, 0, sizeof(amdolbyPQInfo));
amdolbyPQInfo.pic_mode_id = mode;
amdolbyPQInfo.item = iteamID;
amdolbyPQInfo.value = value;
int ret = DV_DeviceIOCtl(DV_IOC_SET_DV_SINGLE_PQ_VALUE, &amdolbyPQInfo);
if (ret < 0) {
LOGD("%s failed!\n", __FUNCTION__);
} else {
LOGD("%s success!\n", __FUNCTION__);
}
return ret;
}
int CDolbyVision::GetAmdolbyPQParam(dolby_pq_mode_t mode, enum pq_item_e iteamID) {
struct dv_pq_info_s amdolbyPQInfo;
memset(&amdolbyPQInfo, 0, sizeof(amdolbyPQInfo));
amdolbyPQInfo.pic_mode_id = mode;
amdolbyPQInfo.item = iteamID;
int ret = DV_DeviceIOCtl(DV_IOC_GET_DV_SINGLE_PQ_VALUE, &amdolbyPQInfo);
if (ret < 0) {
LOGD("%s failed!\n", __FUNCTION__);
} else {
LOGD("%s success!\n", __FUNCTION__);
}
return ret;
}
int CDolbyVision::SetAmdolbyPQFullParam(struct dv_full_pq_info_s fullInfo) {
int ret = DV_DeviceIOCtl(DV_IOC_GET_DV_FULL_PQ_VALUE, &fullInfo);
if (ret < 0) {
LOGD("%s failed!\n", __FUNCTION__);
} else {
LOGD("%s success!\n", __FUNCTION__);
}
return ret;
}
int CDolbyVision::GetAmdolbyPQFullParam(struct dv_full_pq_info_s *fullInfo) {
int ret = 0;
struct dv_full_pq_info_s amdolbyPQFullInfo;
memset(&amdolbyPQFullInfo, 0, sizeof(amdolbyPQFullInfo));
amdolbyPQFullInfo.pic_mode_id = fullInfo->pic_mode_id;
ret = DV_DeviceIOCtl(DV_IOC_GET_DV_FULL_PQ_VALUE, &amdolbyPQFullInfo);
if (ret < 0) {
LOGD("%s failed!\n", __FUNCTION__);
} else {
LOGD("%s success, brightness:%d, contrast:%d, saturation:%d, hue:%d.\n",
__FUNCTION__,
amdolbyPQFullInfo.brightness,
amdolbyPQFullInfo.contrast,
amdolbyPQFullInfo.saturation,
amdolbyPQFullInfo.colorshift);
}
memcpy(fullInfo, &amdolbyPQFullInfo, sizeof(amdolbyPQFullInfo));
return ret;
}
bool CDolbyVision::isSourceCallAmdolbyCore(enum hdr_type_e hdrType)
{
bool ret = false;
char temp[8];
memset(temp, 0, sizeof(temp));
int readRet = ReadSysfs(HDR10_POLICY_PATH, temp, sizeof(temp));
LOGD("%s: hdr10PolicyValue is %s.\n", __FUNCTION__, temp);
if (readRet > 0) {
int hdr10PolicyValue = atoi(temp);
switch (hdrType) {
case HDRTYPE_HDR10:
if (((hdr10PolicyValue & HDR_BY_DV_F_SINK) == HDR_BY_DV_F_SINK)
|| ((hdr10PolicyValue & HDR_BY_DV_F_SRC) == HDR_BY_DV_F_SRC)) {
ret = true;
}
break;
case HDRTYPE_HDR10PLUS:
if ((hdr10PolicyValue & HDRP_BY_DV) == HDRP_BY_DV) {
ret = true;
}
break;
case HDRTYPE_HLG:
if (((hdr10PolicyValue & HLG_BY_DV_F_SINK) == HLG_BY_DV_F_SINK)
|| ((hdr10PolicyValue & HLG_BY_DV_F_SRC) == HLG_BY_DV_F_SRC)) {
ret = true;
}
break;
case HDRTYPE_DOVI:
ret = true;
break;
case HDRTYPE_SDR:
if ((hdr10PolicyValue & SDR_BY_DV) == SDR_BY_DV) {
ret = true;
}
break;
case HDRTYPE_MVC:
case HDRTYPE_PRIMESL:
case HDRTYPE_NONE:
default:
ret = false;
break;
}
} else {
LOGD("%s: read %s failed!\n", __FUNCTION__, HDR10_POLICY_PATH);
ret = false;
}
return ret;
}
dolby_pq_mode_t CDolbyVision::MappingPQModeToAmdolbyVisionPQMode(enum hdr_type_e hdrType, vpp_picture_mode_t pq_mode)
{
dolby_pq_mode_t amdolbyMode = DOLBY_PQ_MODE_INVALID;
/*
switch (hdrType) {
case HDRTYPE_SDR:
if (pq_mode == VPP_PICTURE_MODE_DYNAMIC) {
amdolbyMode = DOLBY_PQ_MODE_DYNAMIC_SDR;
} else if (pq_mode == VPP_PICTURE_MODE_STANDARD) {
amdolbyMode = DOLBY_PQ_MODE_STANDARD_SDR;
} else if (pq_mode == VPP_PICTURE_MODE_HDR) {
amdolbyMode = DOLBY_PQ_MODE_DARK_SDR;
} else if (pq_mode == VPP_PICTURE_MODE_NORMAL) {
amdolbyMode = DOLBY_PQ_MODE_BRIGHT_SDR;
} else if (pq_mode == VPP_PICTURE_MODE_PC) {
amdolbyMode = DOLBY_PQ_MODE_PC_SDR;
} else if (pq_mode == VPP_PICTURE_MODE_CUSTOMER) {
amdolbyMode = DOLBY_PQ_MODE_CUSTOMER_SDR;
} else if (pq_mode == VPP_PICTURE_MODE_STORE) {
amdolbyMode = DOLBY_PQ_MODE_STORE_SDR;
} else {
LOGD("%s: not supported mode.\n", __FUNCTION__);
amdolbyMode = DOLBY_PQ_MODE_MAX;
}
break;
case HDRTYPE_HDR10:
if (pq_mode == VPP_PICTURE_MODE_DYNAMIC) {
amdolbyMode = DOLBY_PQ_MODE_DYNAMIC_HDR10;
} else if (pq_mode == VPP_PICTURE_MODE_STANDARD) {
amdolbyMode = DOLBY_PQ_MODE_STANDARD_HDR10;
} else if (pq_mode == VPP_PICTURE_MODE_HDR) {
amdolbyMode = DOLBY_PQ_MODE_DARK_HDR10;
} else if (pq_mode == VPP_PICTURE_MODE_NORMAL) {
amdolbyMode = DOLBY_PQ_MODE_BRIGHT_HDR10;
} else if (pq_mode == VPP_PICTURE_MODE_PC) {
amdolbyMode = DOLBY_PQ_MODE_PC_HDR10;
} else if (pq_mode == VPP_PICTURE_MODE_CUSTOMER) {
amdolbyMode = DOLBY_PQ_MODE_CUSTOMER_HDR10;
} else if (pq_mode == VPP_PICTURE_MODE_STORE) {
amdolbyMode = DOLBY_PQ_MODE_STORE_HDR10;
} else {
LOGD("%s: not supported mode.\n", __FUNCTION__);
amdolbyMode = DOLBY_PQ_MODE_MAX;
}
break;
case HDRTYPE_HLG:
if (pq_mode == VPP_PICTURE_MODE_DYNAMIC) {
amdolbyMode = DOLBY_PQ_MODE_DYNAMIC_HLG;
} else if (pq_mode == VPP_PICTURE_MODE_STANDARD) {
amdolbyMode = DOLBY_PQ_MODE_STANDARD_HLG;
} else if (pq_mode == VPP_PICTURE_MODE_HDR) {
amdolbyMode = DOLBY_PQ_MODE_DARK_HLG;
} else if (pq_mode == VPP_PICTURE_MODE_NORMAL) {
amdolbyMode = DOLBY_PQ_MODE_BRIGHT_HLG;
} else if (pq_mode == VPP_PICTURE_MODE_PC) {
amdolbyMode = DOLBY_PQ_MODE_PC_HLG;
} else if (pq_mode == VPP_PICTURE_MODE_CUSTOMER) {
amdolbyMode = DOLBY_PQ_MODE_CUSTOMER_HLG;
} else if (pq_mode == VPP_PICTURE_MODE_STORE) {
amdolbyMode = DOLBY_PQ_MODE_STORE_HLG;
} else {
LOGD("%s: not supported mode.\n", __FUNCTION__);
amdolbyMode = DOLBY_PQ_MODE_MAX;
}
break;
case HDRTYPE_DOVI:
if (pq_mode == VPP_PICTURE_MODE_DYNAMIC) {
amdolbyMode = DOLBY_PQ_MODE_DYNAMIC_DV;
} else if (pq_mode == VPP_PICTURE_MODE_STANDARD) {
amdolbyMode = DOLBY_PQ_MODE_STANDARD_DV;
} else if (pq_mode == VPP_PICTURE_MODE_HDR) {
amdolbyMode = DOLBY_PQ_MODE_DARK_DV;
} else if (pq_mode == VPP_PICTURE_MODE_NORMAL) {
amdolbyMode = DOLBY_PQ_MODE_BRIGHT_DV;
} else if (pq_mode == VPP_PICTURE_MODE_PC) {
amdolbyMode = DOLBY_PQ_MODE_PC_DV;
} else if (pq_mode == VPP_PICTURE_MODE_CUSTOMER) {
amdolbyMode = DOLBY_PQ_MODE_CUSTOMER_DV;
} else if (pq_mode == VPP_PICTURE_MODE_STORE) {
amdolbyMode = DOLBY_PQ_MODE_STORE_DV;
} else {
LOGD("%s: not supported mode.\n", __FUNCTION__);
amdolbyMode = DOLBY_PQ_MODE_MAX;
}
break;
case HDRTYPE_HDR10PLUS:
case HDRTYPE_MVC:
case HDRTYPE_PRIMESL:
case HDRTYPE_NONE:
default:
LOGD("%s: not supported mode.\n", __FUNCTION__);
amdolbyMode = DOLBY_PQ_MODE_MAX;
break;
}
LOGD("%s: current hdr type is %d, PQmode is %d, amdolby PQmode is %d.\n",
__FUNCTION__, hdrType, pq_mode, amdolbyMode);
*/
return amdolbyMode;
}
int CDolbyVision::SetAmdolbyPQDarkDetail(int mode) {
int ret = DV_DeviceIOCtl(DV_IOC_SET_DV_DARK_DETAIL, &mode);
if (ret < 0) {
LOGD("%s failed!\n", __FUNCTION__);
} else {
LOGD("%s success!\n", __FUNCTION__);
}
return ret;
}
int CDolbyVision::SetAmdolbyDvCfg(const char *path) {
int ret = -1;
int dataSize = 0;
unsigned char *dataBuff = NULL;
if (path == NULL) {
LOGE("%s: path invalid\n", __FUNCTION__);
return ret;
}
dataSize = ReadFile(&dataBuff, path);
if (dataSize == 0) {
LOGE("%s open %s failed!\n", __FUNCTION__, path);
} else {
struct dv_config_data_s data;
memset(&data, 0x0, sizeof(struct dv_config_data_s));
data.file_name = 0; //cfg
data.file_size = dataSize;
data.file_data = (void *)dataBuff;
ret = DV_DeviceIOCtl(DV_IOC_SET_DV_CONFIG_DATA, &data);
}
free(dataBuff);
if (ret < 0) {
LOGE("%s failed!\n", __FUNCTION__);
} else {
LOGD("%s success!\n", __FUNCTION__);
}
return ret;
}
int CDolbyVision::SetAmdolbyDvCfgBin(const char *path) {
int ret = -1;
int dataSize = 0;
unsigned char *dataBuff = NULL;
if (path == NULL) {
LOGE("%s: path invalid\n", __FUNCTION__);
return ret;
}
dataSize = ReadFile(&dataBuff, path);
if (dataSize == 0) {
LOGE("%s open %s failed!\n", __FUNCTION__, path);
} else {
struct dv_config_data_s data;
memset(&data, 0x0, sizeof(struct dv_config_data_s));
data.file_name = 1; //bin
data.file_size = dataSize;
data.file_data = (void *)dataBuff;
ret = DV_DeviceIOCtl(DV_IOC_SET_DV_CONFIG_DATA, &data);
}
free(dataBuff);
if (ret < 0) {
LOGE("%s failed!\n", __FUNCTION__);
} else {
LOGD("%s success!\n", __FUNCTION__);
}
return ret;
}