p26001-store-acs-soc-fw-app/video/hisi/mpp5/IVE.cpp
2026-09-28 21:33:04 +08:00

498 lines
15 KiB
C++

/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "IVE.h"
#include "Logger.h"
#include "util/Math.h"
#include <hi_mpi_sys.h>
#include <hi_mpi_vb.h>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CONSTANTS
*******************************************************************************
*/
#define HI__IVE_IMAGE_CHN_ONE 1
#define HI__IVE_IMAGE_CHN_TWO 2
#define HI__IVE_IMAGE_CHN_THREE 3
#define HI__IVE_IMAGE_CHN_FOUR 4
#define HI__IVE_MAX_CCL_REGION_NUM 254
#define HI__IVE_DIV_TWO 2
#define HI_SAMPLE_POINT_IDX_ZERO 0
#define HI_SAMPLE_POINT_IDX_ONE 1
#define HI_SAMPLE_POINT_IDX_TWO 2
#define HI_SAMPLE_POINT_IDX_THREE 3
#define HI_SAMPLE_RESIZE_MAX_TILE_METRIC_8BIT 2032
#define HI_SAMPLE_RESIZE_MAX_TILE_METRIC_16BIT 1016
#define HI_SAMPLE_RESIZE_TILE_ADJUST 2
#define HI_SAMPLE_RESIZE_ASSIST_UNIT_SIZE 48
#define HI_SAMPLE_RESIZE_CBCR_NUM_2 2
#define HI_SAMPLE_RESIZE_CBCR_NUM_3 3
#define HI_IVE_ALIGN 16
/*
*******************************************************************************
* MACROS
*******************************************************************************
*/
#define _convert_ptr_to_addr(type, addr) ((type)(hi_uintptr_t)(addr))
#define _convert_addr_to_ptr(type, addr) ((type*)(hi_uintptr_t)(addr))
/*
*******************************************************************************
* TYPEDEFS
*******************************************************************************
*/
struct _img_loop_info
{
uint32_t ele_size;
uint32_t loop_c;
uint32_t loop_h[HI_SVP_IMG_ADDR_NUM];
};
typedef struct _img_loop_info _img_loop_info_t;
/*
*******************************************************************************
* LOCAL FUNCTIONS
*******************************************************************************
*/
static void _ive_get_loop_info(const hi_svp_img* img, _img_loop_info_t* loop_info)
{
loop_info->ele_size = 1;
loop_info->loop_c = 1;
loop_info->loop_h[0] = img->height;
switch (img->type)
{
case HI_SVP_IMG_TYPE_U8C1:
case HI_SVP_IMG_TYPE_S8C1:
break;
case HI_SVP_IMG_TYPE_YUV420SP:
loop_info->ele_size = 1;
loop_info->loop_c = HI__IVE_IMAGE_CHN_TWO;
loop_info->loop_h[1] = img->height / HI__IVE_DIV_TWO;
break;
case HI_SVP_IMG_TYPE_YUV422SP:
loop_info->loop_c = HI__IVE_IMAGE_CHN_TWO;
loop_info->loop_h[1] = img->height;
break;
case HI_SVP_IMG_TYPE_U8C3_PACKAGE:
loop_info->ele_size = (uint32_t)(sizeof(uint8_t) + sizeof(uint16_t));
break;
case HI_SVP_IMG_TYPE_U8C3_PLANAR:
loop_info->loop_c = HI__IVE_IMAGE_CHN_THREE;
loop_info->loop_h[1] = img->height;
loop_info->loop_h[HI__IVE_IMAGE_CHN_TWO] = img->height;
break;
case HI_SVP_IMG_TYPE_S16C1:
case HI_SVP_IMG_TYPE_U16C1:
loop_info->ele_size = (uint32_t)sizeof(uint16_t);
break;
case HI_SVP_IMG_TYPE_U32C1:
case HI_SVP_IMG_TYPE_S32C1:
loop_info->ele_size = (uint32_t)sizeof(uint32_t);
break;
case HI_SVP_IMG_TYPE_S64C1:
case HI_SVP_IMG_TYPE_U64C1:
loop_info->ele_size = (uint32_t)sizeof(uint64_t);
break;
default:
break;
}
}
#define HI_SAMPLE_ADDR_IDX_ZERO 0
#define HI_SAMPLE_ADDR_IDX_ONE 1
#define HI_SAMPLE_ADDR_IDX_TWO 2
#define HI_MAX_LOOP_IMG_H 3
static int _ive_set_image_addr(hi_svp_img* img, const _img_loop_info_t* loop_info, hi_bool is_mmz_cached)
{
uint32_t c;
int size = 0;
int rc;
hi_void* virt_addr = HI_NULL;
for (c = 0; (c < loop_info->loop_c) && (c < HI_MAX_LOOP_IMG_H) && (c < HI_SVP_IMG_STRIDE_NUM); c++)
{
size += img->stride[0] * loop_info->loop_h[c] * loop_info->ele_size;
img->stride[c] = img->stride[0];
}
if (is_mmz_cached)
{
rc = hi_mpi_sys_mmz_alloc_cached((hi_phys_addr_t*)&img->phys_addr[0], (hi_void**)&virt_addr, HI_NULL, HI_NULL,
size);
}
else
{
rc = hi_mpi_sys_mmz_alloc((hi_phys_addr_t*)&img->phys_addr[0], (hi_void**)&virt_addr, HI_NULL, HI_NULL, size);
}
if (rc != HI_SUCCESS)
{
logger().error("IVE: mmz malloc FAIL: %d(%08X)", rc, (uint32_t)rc);
return rc;
}
img->virt_addr[HI_SAMPLE_ADDR_IDX_ZERO] = _convert_ptr_to_addr(uint64_t, virt_addr);
if (img->type != HI_SVP_IMG_TYPE_U8C3_PACKAGE)
{
for (c = 1; (c < loop_info->loop_c) && (c < HI_MAX_LOOP_IMG_H) && (c < HI_SVP_IMG_STRIDE_NUM); c++)
{
img->phys_addr[c] = img->phys_addr[c - 1] + img->stride[c - 1] * img->height;
img->virt_addr[c] = img->virt_addr[c - 1] + img->stride[c - 1] * img->height;
}
}
else
{
img->virt_addr[HI_SAMPLE_ADDR_IDX_ONE] = img->virt_addr[HI_SAMPLE_ADDR_IDX_ZERO] + 1;
img->virt_addr[HI_SAMPLE_ADDR_IDX_TWO] = img->virt_addr[HI_SAMPLE_ADDR_IDX_ONE] + 1;
img->phys_addr[HI_SAMPLE_ADDR_IDX_ONE] = img->phys_addr[HI_SAMPLE_ADDR_IDX_ZERO] + 1;
img->phys_addr[HI_SAMPLE_ADDR_IDX_TWO] = img->phys_addr[HI_SAMPLE_ADDR_IDX_ONE] + 1;
}
return size;
}
static int _ive_img_init(hi_svp_img* img, hi_svp_img_type type, uint32_t width, uint32_t height)
{
int rc = 0;
_img_loop_info_t loop_info;
img->type = type;
img->width = width;
img->height = height;
img->stride[0] = Util::Math::alignup(width, HI_IVE_ALIGN);
switch (type)
{
case HI_SVP_IMG_TYPE_U8C1:
case HI_SVP_IMG_TYPE_S8C1:
case HI_SVP_IMG_TYPE_YUV420SP:
case HI_SVP_IMG_TYPE_YUV422SP:
case HI_SVP_IMG_TYPE_S16C1:
case HI_SVP_IMG_TYPE_U16C1:
case HI_SVP_IMG_TYPE_U8C3_PACKAGE:
case HI_SVP_IMG_TYPE_S32C1:
case HI_SVP_IMG_TYPE_U32C1:
case HI_SVP_IMG_TYPE_S64C1:
case HI_SVP_IMG_TYPE_U64C1:
_ive_get_loop_info(img, &loop_info);
rc = _ive_set_image_addr(img, &loop_info, HI_FALSE);
break;
case HI_SVP_IMG_TYPE_YUV420P:
break;
case HI_SVP_IMG_TYPE_YUV422P:
break;
case HI_SVP_IMG_TYPE_S8C2_PACKAGE:
break;
case HI_SVP_IMG_TYPE_S8C2_PLANAR:
break;
case HI_SVP_IMG_TYPE_U8C3_PLANAR:
break;
default:
break;
}
return rc;
}
static uint32_t _ive_resize_get_tile_metric(uint32_t src_metric, uint32_t dst_metric, hi_svp_img_type img_type)
{
int tmp_metric = HI_SAMPLE_RESIZE_MAX_TILE_METRIC_8BIT;
uint32_t src_tile_num, scale, dst_tmp_tile, src_tmp_tile, tile_remainder;
switch (img_type)
{
case HI_SVP_IMG_TYPE_YUV420SP:
case HI_SVP_IMG_TYPE_YUV422SP:
case HI_SVP_IMG_TYPE_U8C3_PLANAR:
case HI_SVP_IMG_TYPE_U8C1:
case HI_SVP_IMG_TYPE_S8C1:
tmp_metric = HI_SAMPLE_RESIZE_MAX_TILE_METRIC_8BIT;
break;
case HI_SVP_IMG_TYPE_U16C1:
case HI_SVP_IMG_TYPE_S16C1:
tmp_metric = HI_SAMPLE_RESIZE_MAX_TILE_METRIC_16BIT;
break;
default:
break;
}
scale = (src_metric / dst_metric) + ((src_metric % dst_metric == 0) ? 0 : 1);
if (dst_metric < src_metric)
{
src_tile_num = (src_metric / tmp_metric) + ((src_metric % tmp_metric == 0) ? 0 : 1);
dst_tmp_tile = dst_metric / src_tile_num;
src_tmp_tile = src_metric / src_tile_num + ((src_metric % src_tile_num == 0) ? 0 : 1);
tile_remainder = (tmp_metric - src_tmp_tile) / scale;
tmp_metric = (dst_tmp_tile + tile_remainder) & ~0x1;
if (tile_remainder == 0)
{
tmp_metric -= HI_SAMPLE_RESIZE_TILE_ADJUST;
}
}
else if (dst_metric == src_metric || scale == 1)
{
tmp_metric -= HI_SAMPLE_RESIZE_TILE_ADJUST;
}
return (uint32_t)tmp_metric;
}
static uint32_t _ive_resize_get_tile_num(uint32_t width, uint32_t height, uint32_t tile_w, uint32_t tile_h)
{
uint32_t x_num, y_num;
if ((tile_w == 0) || (tile_h == 0))
return 0;
x_num = (width / tile_w) + ((width % tile_w) == 0 ? 0 : 1);
y_num = (height / tile_h) + ((height % tile_h) == 0 ? 0 : 1);
return (x_num * y_num);
}
#define HI_SAMPLE_RESIZE_CBCR_NUM_2 2
static uint32_t _ive_resize_get_yuv420sp_tile_num(uint32_t src_width, uint32_t dst_width, uint32_t src_height,
uint32_t dst_height)
{
uint32_t j, tile_width, tile_height;
uint32_t num = 0;
tile_width = _ive_resize_get_tile_metric(src_width, dst_width, HI_SVP_IMG_TYPE_YUV420SP);
for (j = 0; j < HI_SAMPLE_RESIZE_CBCR_NUM_2; j++)
{
tile_height = _ive_resize_get_tile_metric(src_height >> j, dst_height >> j, HI_SVP_IMG_TYPE_YUV420SP);
num += _ive_resize_get_tile_num(dst_width, dst_height >> j, tile_width, tile_height);
}
return num;
}
static uint32_t _ive_resize_get_yuv422sp_tile_num(uint32_t src_width, uint32_t dst_width, uint32_t src_height,
uint32_t dst_height)
{
uint32_t j, tile_width, tile_height;
uint32_t num = 0;
tile_width = _ive_resize_get_tile_metric(src_width, dst_width, HI_SVP_IMG_TYPE_YUV422SP);
tile_height = _ive_resize_get_tile_metric(src_height, dst_height, HI_SVP_IMG_TYPE_YUV422SP);
for (j = 0; j < HI_SAMPLE_RESIZE_CBCR_NUM_2; j++)
num += _ive_resize_get_tile_num(dst_width, dst_height, tile_width, tile_height);
return num;
}
static uint32_t _ive_resize_get_u8c3_planar_tile_num(uint32_t src_width, uint32_t dst_width, uint32_t src_height,
uint32_t dst_height)
{
uint32_t j, tile_width, tile_height;
uint32_t num = 0;
tile_width = _ive_resize_get_tile_metric(src_width, dst_width, HI_SVP_IMG_TYPE_U8C3_PLANAR);
tile_height = _ive_resize_get_tile_metric(src_height, dst_height, HI_SVP_IMG_TYPE_U8C3_PLANAR);
for (j = 0; j < HI_SAMPLE_RESIZE_CBCR_NUM_3; j++)
num += _ive_resize_get_tile_num(dst_width, dst_height, tile_width, tile_height);
return num;
}
static uint32_t _ive_resize_get_u8c1_tile_num(uint32_t src_width, uint32_t dst_width, uint32_t src_height,
uint32_t dst_height)
{
uint32_t tile_width, tile_height;
uint32_t num = 0;
tile_width = _ive_resize_get_tile_metric(src_width, dst_width, HI_SVP_IMG_TYPE_U8C1);
tile_height = _ive_resize_get_tile_metric(src_height, dst_height, HI_SVP_IMG_TYPE_U8C1);
num = _ive_resize_get_tile_num(dst_width, dst_height, tile_width, tile_height);
return num;
}
static uint32_t _ive_resize_get_u16c1_tile_num(uint32_t src_width, uint32_t dst_width, uint32_t src_height,
uint32_t dst_height)
{
uint32_t tile_width, tile_height;
uint32_t num = 0;
tile_width = _ive_resize_get_tile_metric(src_width, dst_width, HI_SVP_IMG_TYPE_U16C1);
tile_height = _ive_resize_get_tile_metric(src_height, dst_height, HI_SVP_IMG_TYPE_U16C1);
num = _ive_resize_get_tile_num(dst_width, dst_height, tile_width, tile_height);
return num;
}
static int _ive_resize_get_assist_buf_size(const hi_svp_src_img src[], const hi_svp_dst_img dst[], int count)
{
int i;
int num = 0;
for (i = 0; i < count; i++)
{
switch (src[i].type)
{
case HI_SVP_IMG_TYPE_YUV420SP:
num += _ive_resize_get_yuv420sp_tile_num(src[i].width, dst[i].width, src[i].height, dst[i].height);
break;
case HI_SVP_IMG_TYPE_YUV422SP:
num += _ive_resize_get_yuv422sp_tile_num(src[i].width, dst[i].width, src[i].height, dst[i].height);
break;
case HI_SVP_IMG_TYPE_U8C3_PLANAR:
num += _ive_resize_get_u8c3_planar_tile_num(src[i].width, dst[i].width, src[i].height, dst[i].height);
break;
case HI_SVP_IMG_TYPE_U8C1:
case HI_SVP_IMG_TYPE_S8C1:
num += _ive_resize_get_u8c1_tile_num(src[i].width, dst[i].width, src[i].height, dst[i].height);
break;
case HI_SVP_IMG_TYPE_U16C1:
case HI_SVP_IMG_TYPE_S16C1:
num += _ive_resize_get_u16c1_tile_num(src[i].width, dst[i].width, src[i].height, dst[i].height);
break;
default:
break;
}
}
return num * HI_SAMPLE_RESIZE_ASSIST_UNIT_SIZE;
}
static int _ive_mem_info_init(hi_svp_mem_info* mem_info, hi_u32 size)
{
int rc = HI_ERR_IVE_NULL_PTR;
hi_void* virt_addr = HI_NULL;
mem_info->size = size;
rc = hi_mpi_sys_mmz_alloc((hi_phys_addr_t*)&mem_info->phys_addr, (hi_void**)&virt_addr, HI_NULL, HI_NULL, size);
if (rc != HI_SUCCESS)
return rc;
mem_info->virt_addr = _convert_ptr_to_addr(uint64_t, virt_addr);
return rc;
}
static int _ive_img_load(hi_svp_img* img, uint8_t* pData)
{
uint8_t* ptr_tmp = HI_NULL;
uint16_t c, h;
int rc = 0;
_img_loop_info_t loop_info = {0};
int index = 0;
_ive_get_loop_info(img, &loop_info);
for (c = 0; (c < loop_info.loop_c) && (c < HI_SVP_IMG_STRIDE_NUM) && (c < HI_SVP_IMG_ADDR_NUM); c++)
{
ptr_tmp = _convert_addr_to_ptr(uint8_t, img->virt_addr[c]);
if (!ptr_tmp)
{
rc = HI_ERR_IVE_BAD_ADDR;
goto exit;
}
for (h = 0; h < loop_info.loop_h[c]; h++)
{
int bytes = img->width * loop_info.ele_size;
memcpy(ptr_tmp, &pData[index], bytes);
index += bytes;
ptr_tmp += img->stride[c] * loop_info.ele_size;
}
}
exit:
return rc;
}
static int _ive_img_store(hi_svp_img* img, uint8_t* pBuffer)
{
uint16_t c, h;
uint8_t* ptr_tmp = HI_NULL;
int rc = 0;
_img_loop_info_t loop_info = {0};
int index = 0;
if (img->phys_addr == 0 || img->virt_addr == 0)
return HI_ERR_BAD_ADDR;
_ive_get_loop_info(img, &loop_info);
for (c = 0; (c < loop_info.loop_c) && (c < HI_SVP_IMG_STRIDE_NUM) && (c < HI_SVP_IMG_ADDR_NUM); c++)
{
ptr_tmp = _convert_addr_to_ptr(uint8_t, img->virt_addr[c]);
if (!ptr_tmp)
{
rc = HI_ERR_IVE_BAD_ADDR;
goto exit;
}
for (h = 0; h < loop_info.loop_h[c]; h++)
{
int bytes = img->width * loop_info.ele_size;
memcpy(&pBuffer[index], ptr_tmp, bytes);
index += bytes;
ptr_tmp += img->stride[c] * loop_info.ele_size;
}
}
exit:
return rc;
}
#define _mmz_free(phys, virt) \
do \
{ \
if (((phys) != 0) && ((virt) != 0)) \
{ \
hi_mpi_sys_mmz_free((hi_phys_addr_t)(phys), (hi_void*)(hi_uintptr_t)(virt)); \
(phys) = 0; \
(virt) = 0; \
} \
} while (0)
static void _ive_img_free(hi_svp_img* img)
{
_mmz_free(img->phys_addr[0], img->virt_addr[0]);
}
static void _ive_mem_info_free(hi_svp_mem_info* info)
{
_mmz_free(info->phys_addr, info->virt_addr);
}
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
VideoFrame::Ptr MPP5::IVE::resize(VideoFrame::Ptr from, uint32_t width, uint32_t height)
{
return VideoFrame::Ptr();
}
}
}