/* ******************************************************************************* * INCLUDE ******************************************************************************* */ #include "IVE.h" #include "Logger.h" #include "util/Math.h" #include #include 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(); } } }