You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

435 lines
12 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2020. All rights reserved.
* Description : iapi hddec
* Author : sdk
* Create : 2019/11/21
*/
#include <string.h>
#include "soc_log.h"
#include "uapi_hddec.h"
#include "mpi_hddec_ext.h"
#include "securec.h"
static ext_hddec_video_format_convert g_hddec_vid_format[] = {
{ UAPI_FORMAT_YUV_SEMIPLANAR_422_VU, EXT_DRV_PIXEL_FMT_NV61_2X1 },
{ UAPI_FORMAT_YUV_SEMIPLANAR_420_VU, EXT_DRV_PIXEL_FMT_NV21 },
{ UAPI_FORMAT_YUV_SEMIPLANAR_400, EXT_DRV_PIXEL_FMT_NV80 },
{ UAPI_FORMAT_YUV_SEMIPLANAR_411_VU, EXT_DRV_PIXEL_FMT_NV12_411 },
{ UAPI_FORMAT_YUV_SEMIPLANAR_422_UV, EXT_DRV_PIXEL_FMT_NV61 },
{ UAPI_FORMAT_YUV_SEMIPLANAR_444_VU, EXT_DRV_PIXEL_FMT_NV42 },
{ UAPI_FORMAT_YUV_PACKAGE_UYVY, EXT_DRV_PIXEL_FMT_UYVY },
{ UAPI_FORMAT_YUV_PACKAGE_YUYV, EXT_DRV_PIXEL_FMT_YUYV },
{ UAPI_FORMAT_YUV_SEMIPLANAR_420_UV, EXT_DRV_PIXEL_FMT_NV12 },
{ UAPI_FORMAT_YUV_PLANAR_400, EXT_DRV_PIXEL_FMT_YUV400 },
{ UAPI_FORMAT_YUV_SEMIPLANAR_400, EXT_DRV_PIXEL_FMT_NV80 },
{ UAPI_FORMAT_YUV_PLANAR_411_VU, EXT_DRV_PIXEL_FMT_YUV411 },
{ UAPI_FORMAT_YUV_PLANAR_420_VU, EXT_DRV_PIXEL_FMT_YUV420P },
{ UAPI_FORMAT_YUV_PLANAR_422_UV, EXT_DRV_PIXEL_FMT_YUV422_1X2 },
{ UAPI_FORMAT_YUV_PLANAR_422_VU, EXT_DRV_PIXEL_FMT_YUV422_2X1 },
{ UAPI_FORMAT_YUV_PLANAR_444_UV, EXT_DRV_PIXEL_FMT_YUV_444 },
{ UAPI_FORMAT_YUV_PLANAR_410_VU, EXT_DRV_PIXEL_FMT_YUV410P },
{ UAPI_FORMAT_RGB888, EXT_DRV_PIXEL_FMT_RGB24 },
{ UAPI_FORMAT_ARGB8888, EXT_DRV_PIXEL_FMT_ARGB8888 },
{ UAPI_FORMAT_YUV_TILE_420_VU, EXT_DRV_PIXEL_FMT_NV21 },
{ UAPI_FORMAT_YUV_TILE_420_UV, EXT_DRV_PIXEL_FMT_NV12 },
{ UAPI_FORMAT_RGB_SEMIPLANAR_444, EXT_DRV_PIXEL_FMT_NV42_RGB },
};
/* HDDEC初始化 */
td_s32 uapi_hddec_init(td_void)
{
td_s32 ret;
ret = ext_mpi_hddec_init();
return ret;
}
/* HDDEC去初始化 */
td_s32 uapi_hddec_deinit(td_void)
{
td_s32 ret;
ret = ext_mpi_hddec_de_init();
return ret;
}
/* 信源连接 */
td_s32 uapi_hddec_connect(const uapi_hddec_src_attr *src_attr)
{
td_s32 ret;
ext_drv_hddec_src_attr source_att;
if (src_attr == NULL) {
soc_log_err("src_attr is NULL pointer!\n");
return TD_FAILURE;
}
if (src_attr->src_type != UAPI_VIDEO_SOURCE_VGA &&
src_attr->src_type != UAPI_VIDEO_SOURCE_YPBPR &&
src_attr->src_type != UAPI_VIDEO_SOURCE_SCART) {
soc_log_err("src_type is invalid!\n");
return TD_FAILURE;
}
source_att.index = src_attr->index;
switch (src_attr->src_type) {
case UAPI_VIDEO_SOURCE_VGA: {
source_att.src_type = EXT_DRV_HDDEC_SRC_VGA;
break;
}
case UAPI_VIDEO_SOURCE_YPBPR: {
source_att.src_type = EXT_DRV_HDDEC_SRC_YPBPR;
break;
}
case UAPI_VIDEO_SOURCE_SCART: {
source_att.src_type = EXT_DRV_HDDEC_SRC_SCART;
break;
}
default: {
soc_log_err("src_type is invalid!\n");
return TD_FAILURE;
}
}
ret = ext_mpi_hddec_connect(&source_att);
return ret;
}
/* 断开连接 */
td_s32 uapi_hddec_disconnect(td_void)
{
td_s32 ret;
ret = ext_mpi_hddec_dis_connect();
return ret;
}
/* 获取离线信源的信号是否存在,阻塞接口 */
td_s32 uapi_hddec_get_offline_status(const uapi_hddec_src_attr *src_attr, td_bool *exist)
{
td_s32 ret;
ext_drv_hddec_src_attr source_att;
if (src_attr == NULL || exist == NULL) {
soc_log_err("NULL pointer!\n");
return TD_FAILURE;
}
if (src_attr->src_type != UAPI_VIDEO_SOURCE_VGA &&
src_attr->src_type != UAPI_VIDEO_SOURCE_YPBPR &&
src_attr->src_type != UAPI_VIDEO_SOURCE_SCART) {
soc_log_err("src_type is invalid!\n");
return TD_FAILURE;
}
source_att.index = src_attr->index;
switch (src_attr->src_type) {
case UAPI_VIDEO_SOURCE_VGA: {
source_att.src_type = EXT_DRV_HDDEC_SRC_VGA;
break;
}
case UAPI_VIDEO_SOURCE_YPBPR: {
source_att.src_type = EXT_DRV_HDDEC_SRC_YPBPR;
break;
}
case UAPI_VIDEO_SOURCE_SCART: {
source_att.src_type = EXT_DRV_HDDEC_SRC_SCART;
break;
}
default: {
soc_log_err("src_type is invalid!\n");
return TD_FAILURE;
}
}
ret = ext_mpi_hddec_get_offline_status(&source_att, exist);
return ret;
}
/* 检测当前decode状态 */
td_s32 uapi_hddec_get_signal_status(uapi_sig_status *sig_status)
{
td_s32 ret;
ext_drv_hddec_signal_status signal_state;
if (sig_status == NULL) {
soc_log_err("sig_status is NULL pointer!\n");
return TD_FAILURE;
}
ret = ext_mpi_hddec_get_signal_status(&signal_state);
*sig_status = (uapi_sig_status)signal_state;
return ret;
}
/* 检测当前的decodeTiming信息 */
td_s32 uapi_hddec_get_timing_info(uapi_hddec_timing_info *timing_info)
{
td_s32 ret;
size_t max_index;
td_u32 index;
ext_drv_hddec_timing_info timing;
if (timing_info == NULL) {
soc_log_err("timing_info is NULL pointer!\n");
return TD_FAILURE;
}
ret = ext_mpi_hddec_get_timing_info(&timing);
timing_info->interlace = timing.interlace;
timing_info->frame_rate = timing.frame_rate;
timing_info->oversample = (uapi_oversample)timing.oversample;
timing_info->bit_depth = (uapi_pixel_bit_depth)timing.bit_width;
timing_info->timing_index = timing.timing_index;
timing_info->width = timing.width;
timing_info->height = timing.height;
timing_info->color_space.color_primary = (uapi_color_primary)timing.color_space.color_primary;
timing_info->color_space.color_space = (uapi_color_space)timing.color_space.color_space;
timing_info->color_space.quantify_range = (uapi_color_quantify_range)timing.color_space.quantify_range;
timing_info->color_space.matrix_coef = (uapi_color_matrix_coeffs)timing.color_space.matrix_coef;
timing_info->color_space.transfer_type = (uapi_color_transfer_curve)timing.color_space.transfer_type;
max_index = sizeof(g_hddec_vid_format) / sizeof(g_hddec_vid_format[0]);
for (index = 0; index < max_index; index++) {
if (timing.pix_fmt == g_hddec_vid_format[index].drv_video_format) {
timing_info->pix_fmt = (uapi_video_pixel_format)g_hddec_vid_format[index].iapi_video_format;
break;
}
}
return ret;
}
/* 检测当前的decode非标信息 */
td_s32 uapi_hddec_get_nonstd_info(uapi_video_nonstd_info *nonstd_info)
{
td_s32 ret;
ext_drv_hddec_nonstd_info nonstd;
if (nonstd_info == NULL) {
soc_log_err("nonstd_info is NULL pointer!\n");
return TD_FAILURE;
}
ret = ext_mpi_hddec_get_non_std_info(&nonstd);
nonstd_info->is_non_std = nonstd.non_std;
nonstd_info->v_freq = nonstd.v_freq;
nonstd_info->height = nonstd.height;
return ret;
}
/* 启动自动颜色校正 */
td_s32 uapi_hddec_calibrate_color(td_void)
{
td_s32 ret;
ret = ext_mpi_hddec_start_calibrate_color();
return ret;
}
/* 获取自动颜色校正状态 */
td_s32 uapi_hddec_get_calibration_status(uapi_hddec_color_calib_status *calib_status)
{
td_s32 ret;
ext_drv_hddec_color_calib_status calib_state;
if (calib_status == NULL) {
soc_log_err("calib_status is NULL pointer!\n");
return TD_FAILURE;
}
ret = ext_mpi_hddec_get_calibration_status(&calib_state);
*calib_status = (uapi_hddec_color_calib_status)calib_state;
return ret;
}
/* 获取手动设置自动颜色校正参数 */
td_s32 uapi_hddec_get_calibration_param(uapi_hddec_color_calib_param *calib_param)
{
td_s32 ret;
ext_drv_hddec_color_calib_param calibration_param;
if (calib_param == NULL) {
soc_log_err("calib_param is NULL pointer!\n");
return TD_FAILURE;
}
ret = ext_mpi_hddec_get_calibration_param(&calibration_param);
calib_param->r_gain = calibration_param.r_gain;
calib_param->g_gain = calibration_param.g_gain;
calib_param->b_gain = calibration_param.b_gain;
calib_param->r_offset = calibration_param.r_offset;
calib_param->g_offset = calibration_param.g_offset;
calib_param->b_offset = calibration_param.b_offset;
return ret;
}
/* 手动设置自动颜色校正 */
td_s32 uapi_hddec_set_calibration_param(const uapi_hddec_color_calib_param *calib_param)
{
td_s32 ret;
ext_drv_hddec_color_calib_param calibration_param;
if (calib_param == NULL) {
soc_log_err("calib_param is NULL pointer!\n");
return TD_FAILURE;
}
calibration_param.r_gain = calib_param->r_gain;
calibration_param.g_gain = calib_param->g_gain;
calibration_param.b_gain = calib_param->b_gain;
calibration_param.r_offset = calib_param->r_offset;
calibration_param.g_offset = calib_param->g_offset;
calibration_param.b_offset = calib_param->b_offset;
ret = ext_mpi_hddec_set_calibration_param(&calibration_param);
return ret;
}
/* 启动VGA图像自动调整 */
td_s32 uapi_hddec_adjust_image_param(td_void)
{
td_s32 ret;
ret = ext_mpi_hddec_start_adjust_image_param();
return ret;
}
/* 获取VGA图像自动调整状态 */
td_s32 uapi_hddec_get_adjust_status(uapi_hddec_adjust_status *adjust_status)
{
td_s32 ret;
ext_drv_hddec_adjust_status adjust_state;
if (adjust_status == NULL) {
soc_log_err("adjust_status is NULL pointer!\n");
return TD_FAILURE;
}
ret = ext_mpi_hddec_get_adjust_status(&adjust_state);
*adjust_status = (uapi_hddec_adjust_status)adjust_state;
return ret;
}
/* 获取手动调整可调范围 */
td_s32 uapi_hddec_get_adjust_range(uapi_hddec_adjust_type adjust_type, uapi_sys_range *range)
{
td_s32 ret;
ext_drv_hddec_adjust_type adjust;
ext_range range_info;
if (adjust_type >= UAPI_HDDEC_ADJUST_TYPE_MAX ||
adjust_type < UAPI_HDDEC_ADJUST_TYPE_HPOS) {
soc_log_err("adjust type is invalid.\n");
return TD_FAILURE;
}
if (range == NULL) {
soc_log_err("range is NULL pointer!\n");
return TD_FAILURE;
}
adjust = (ext_drv_hddec_adjust_type)adjust_type;
ret = ext_mpi_hddec_get_adjust_range(adjust, &range_info);
range->min = range_info.min;
range->max = range_info.max;
return ret;
}
/* 获取调整参数 */
td_s32 uapi_hddec_get_adjust_param(uapi_hddec_adjust_type adjust_type, td_u32 *param)
{
td_s32 ret;
ext_drv_hddec_adjust_type adjust;
if (adjust_type >= UAPI_HDDEC_ADJUST_TYPE_MAX ||
adjust_type < UAPI_HDDEC_ADJUST_TYPE_HPOS) {
soc_log_err("adjust type is invalid.\n");
return TD_FAILURE;
}
if (param == NULL) {
soc_log_err("param is NULL pointer!\n");
return TD_FAILURE;
}
adjust = (ext_drv_hddec_adjust_type)adjust_type;
ret = ext_mpi_hddec_get_adjust_param(adjust, param);
return ret;
}
/* 设置手动调整参数 */
td_s32 uapi_hddec_set_adjust_param(uapi_hddec_adjust_type adjust_type, td_u32 param)
{
td_s32 ret;
ext_drv_hddec_adjust_type adjust;
if (adjust_type >= UAPI_HDDEC_ADJUST_TYPE_MAX ||
adjust_type < UAPI_HDDEC_ADJUST_TYPE_HPOS) {
soc_log_err("adjust type is invalid!\n");
return TD_FAILURE;
}
adjust = (ext_drv_hddec_adjust_type)adjust_type;
ret = ext_mpi_hddec_set_adjust_param(adjust, param);
return ret;
}
/* 更新edid */
td_s32 uapi_hddec_update_edid(const uapi_hddec_edid *edid)
{
td_s32 ret;
ext_drv_hddec_edid edid_info;
if (edid == NULL) {
soc_log_err("edid is NULL pointer!\n");
return TD_FAILURE;
}
errno_t err_ret = memcpy_s(edid_info.edid_data, sizeof(edid_info.edid_data),
edid, UAPI_HDDEC_EDID_SIZE * sizeof(td_u8));
if (err_ret != EOK) {
soc_log_err("secure func call error\n");
return err_ret;
}
ret = ext_mpi_hddec_update_edid(&edid_info);
return ret;
}
/* 获取hddec能力 */
td_s32 uapi_hddec_get_capability(uapi_hddec_capability *capability)
{
td_s32 ret;
ext_drv_hddec_capability cap;
if (capability == NULL) {
soc_log_err("capability is NULL pointer!\n");
return TD_FAILURE;
}
ret = ext_mpi_hddec_get_capability(&cap);
capability->vga_max = cap.vga_max;
capability->ypbpr_max = cap.ypbpr_max;
capability->scart_max = cap.scart_max;
return ret;
}