MC3302_SDK_V1.1.9_202507281.../media/sample/system/ipon/vpu.c

1253 lines
36 KiB
C
Raw Normal View History

2025-11-11 04:08:31 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "fh_common.h"
#include "fh_system_mpi.h"
#include "fh_system_mpi.h"
#include "fh_vb_mpi.h"
#include "fh_defines.h"
#include "vmm_api.h"
#include "fh_vpu_mpi.h"
#include "fh_tde_mpi.h"
#include "fh_vpu_mpi.h"
#include "fh_vgs2_mpi.h"
#include "fh_vgs_mpi.h"
#include "types/bufCtrl.h"
#include "common.h"
#include "xconfig.h"
#include "font.h"
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"
/* global variables */
static stbtt_fontinfo gst_infoFont;
extern bool g_bRunning;
/* functions */
static int __maybe_unused __gosd_font_init(void)
{
/* 初始化字体 */
if (!stbtt_InitFont(&gst_infoFont, g_fontBuffer, 0)) {
printf("stb init font failed\n");
return -1;
}
return 0;
}
static void __maybe_unused __gosd_font_cleanup(void)
{
}
static int __maybe_unused __vpu_set_user_pic(int group, int chn, int width, int height, int type, char* fname)
{
int ret = 0;
FILE *fp = NULL;
if (NULL == fname) {
return -1;
} else {
fp = fopen(fname, "rb");
if (NULL == fp) {
printf("ERR: file: %s open failed!\n", fname);
return -1;
}
}
{
FH_UINT32 u32Size = width * height * 2;
VB_BLK VbBlk;
FH_UINT32 u32PhyAddr;
FH_UINT8 *pVirAddr;
FH_VPU_USER_PIC userPic;
int file_size = 0;
int fpos = 0;
memset(&userPic, 0, sizeof(userPic));
if (type == VPU_VOMODE_SCAN) {
u32Size = width * height * 3 / 2;
} else if (type == VPU_VOMODE_10BIT_NV12) {
u32Size = width * height * 3 / 2;
u32Size = u32Size * 10 >> 3;
}
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
fpos = 0;
while (fpos < file_size) {
/* get video buffer block form common pool */
VbBlk = FH_VB_GetBlock(VB_INVALID_POOLID, u32Size, NULL);
if (VB_INVALID_HANDLE == VbBlk) {
printf("ERR: SetUserPic FH_VB_GetBlock failed!\n");
ret = -__LINE__;
goto exit_set_pic;
}
/* get physical address*/
u32PhyAddr = FH_VB_Handle2PhysAddr(VbBlk);
if (0 == u32PhyAddr) {
printf("ERR: SetUserPic FH_VB_Handle2PhysAddr failed!\n");
ret = -__LINE__;
goto exit_set_pic;
}
pVirAddr = FH_SYS_Mmap(u32PhyAddr, u32Size);
if (NULL == pVirAddr) {
printf("ERR: SetUserPic FH_SYS_MmapCache failed!\n");
FH_VB_ReleaseBlock(VbBlk);
ret = -__LINE__;
goto exit_set_pic;
}
//read the yuv data from the file
fseek(fp, fpos, SEEK_SET);
fread(pVirAddr, 1, u32Size, fp);
FH_SYS_Munmap(pVirAddr, u32Size);
userPic.pic_size.u32Width = width;
userPic.pic_size.u32Height = height;
userPic.yluma = u32PhyAddr;
userPic.chroma = u32PhyAddr + width * height;
if (type == VPU_VOMODE_10BIT_NV12) {
userPic.chroma = u32PhyAddr + (width * height * 10 >> 3);
}
if ((type == VPU_VOMODE_SCAN) || (VPU_VOMODE_NV16 == type)) {
userPic.ystride = width;
userPic.cstride = width;
} else if (type == VPU_VOMODE_10BIT_NV12) {
userPic.ystride = width * 10 >> 3;
userPic.cstride = userPic.ystride;
} else {
userPic.ystride = width * 2;
userPic.cstride = width * 2;
}
userPic.time_stamp = 0;
userPic.data_format = type;
userPic.work_mode = VPU_MODE_MEM;
if (type == VPU_VOMODE_10BIT_NV12) {
userPic.work_mode = VPU_MODE_OFFLINE_2DLUT;
}
userPic.pool_id = FH_VB_Handle2PoolId(VbBlk);
FH_SYS_GetCurPts(&userPic.time_stamp );
if (0 == fpos) {
printf("userpic: yluma = 0x%x, chroma = 0x%x\n", userPic.yluma , userPic.chroma);
ret = FH_VPSS_SendUserPic(group, &userPic);
//FY_MPI_VB_SubUserCnt(VbBlk);
break;
}
}
}
exit_set_pic:
if (fp) {
fclose(fp);
}
return ret;
}
static int __maybe_unused __load_user_pic(int width, int height, int type, char* fname, FH_VPU_USER_PIC* pUsrPic)
{
int ret = 0;
FILE *fp = NULL;
if (NULL == fname) {
return -1;
} else {
fp = fopen(fname, "rb");
if (NULL == fp) {
printf("ERR: file: %s open failed!\n", fname);
return -1;
}
}
{
FH_UINT32 u32Size = width * height * 2;
VB_BLK VbBlk;
FH_UINT32 u32PhyAddr;
FH_UINT8 *pVirAddr;
FH_VPU_USER_PIC userPic;
int file_size = 0;
int fpos = 0;
memset(&userPic, 0, sizeof(userPic));
if (type == VPU_VOMODE_SCAN) {
u32Size = width * height * 3 / 2;
} else if (type == VPU_VOMODE_10BIT_NV12) {
u32Size = width * height * 3 / 2;
u32Size = u32Size * 2;
}
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
fpos = 0;
while (fpos < file_size) {
/* get video buffer block form common pool */
VbBlk = FH_VB_GetBlock(VB_INVALID_POOLID, u32Size, NULL);
if (VB_INVALID_HANDLE == VbBlk) {
printf("ERR: SetUserPic FH_VB_GetBlock failed!\n");
ret = -__LINE__;
goto exit_set_pic;
}
/* get physical address*/
u32PhyAddr = FH_VB_Handle2PhysAddr(VbBlk);
if (0 == u32PhyAddr) {
printf("ERR: SetUserPic FH_VB_Handle2PhysAddr failed!\n");
ret = -__LINE__;
goto exit_set_pic;
}
pVirAddr = FH_SYS_Mmap(u32PhyAddr, u32Size);
if (NULL == pVirAddr) {
printf("ERR: SetUserPic FH_SYS_MmapCache failed!\n");
FH_VB_ReleaseBlock(VbBlk);
ret = -__LINE__;
goto exit_set_pic;
}
//read the yuv data from the file
fseek(fp, fpos, SEEK_SET);
fread(pVirAddr, 1, u32Size, fp);
FH_SYS_Munmap(pVirAddr, u32Size);
userPic.pic_size.u32Width = width;
userPic.pic_size.u32Height = height;
userPic.yluma = u32PhyAddr;
userPic.chroma = u32PhyAddr + width * height;
if (type == VPU_VOMODE_10BIT_NV12) {
userPic.chroma = u32PhyAddr + (width * height * 2);
}
if ((type == VPU_VOMODE_SCAN) || (VPU_VOMODE_NV16 == type)) {
userPic.ystride = width;
userPic.cstride = width;
} else if (type == VPU_VOMODE_10BIT_NV12) {
userPic.ystride = width * 2;
userPic.cstride = userPic.ystride;
} else {
userPic.ystride = width * 2;
userPic.cstride = width * 2;
}
userPic.time_stamp = 0;
userPic.data_format = type;
userPic.work_mode = VPU_MODE_MEM;
if (type == VPU_VOMODE_10BIT_NV12) {
userPic.work_mode = VPU_MODE_OFFLINE_2DLUT;
}
userPic.pool_id = FH_VB_Handle2PoolId(VbBlk);
FH_SYS_GetCurPts(&userPic.time_stamp );
if (0 == fpos) {
printf("userpic: yluma = 0x%x, chroma = 0x%x\n", userPic.yluma , userPic.chroma);
memcpy(pUsrPic, &userPic, sizeof(userPic));
break;
}
}
}
exit_set_pic:
if (fp) {
fclose(fp);
}
return ret;
}
static int __generate_user_pic(int width, int height, int type, FH_VPU_USER_PIC* pUsrPic)
{
int ret = 0;
FH_UINT32 u32Size = width * height * 2;
FH_UINT32 vgstype = 0;
//for user pic
VB_BLK VbBlk;
FH_UINT32 u32YUVPhyAddr = 0;
if (type == VPU_VOMODE_SCAN) {
u32Size = width * height * 3 / 2;
vgstype = PIXEL_FMT_YUV_SEMIPLANAR_420;
} else if (type == VPU_VOMODE_NV16) {
u32Size = width * height * 2;
vgstype = PIXEL_FMT_YUV_SEMIPLANAR_422;
} else {
printf("only support NV12/NV16! type = %d\n", type);
return -1;
}
//generate a color bar graph with VGS
/* get video buffer block form common pool */
VbBlk = FH_VB_GetBlock(VB_INVALID_POOLID, u32Size, NULL);
if (VB_INVALID_HANDLE == VbBlk) {
printf("ERR: SetUserPic FH_VB_GetBlock failed!\n");
ret = -__LINE__;
goto exit0;
}
/* get physical address*/
u32YUVPhyAddr = FH_VB_Handle2PhysAddr(VbBlk);
if (0 == u32YUVPhyAddr) {
printf("ERR: SetUserPic FH_VB_Handle2PhysAddr failed!\n");
ret = -__LINE__;
goto exit0;
}
VIDEO_FRAME_INFO_S frmYUV;
memset(&frmYUV, 0, sizeof(frmYUV));
frmYUV.stVFrame.u32PhyAddr[0] = u32YUVPhyAddr;
frmYUV.stVFrame.u32PhyAddr[1] = u32YUVPhyAddr + width * height;
frmYUV.stVFrame.u32Width = width;
frmYUV.stVFrame.u32Height = height;
frmYUV.stVFrame.u32Stride[0] = width;
frmYUV.stVFrame.u32Stride[1] = width;
frmYUV.stVFrame.enPixelFormat = vgstype;
frmYUV.stVFrame.u32Field = VIDEO_FIELD_FRAME;
frmYUV.stVFrame.enVideoFormat = VIDEO_FORMAT_LINEAR;
frmYUV.u32PoolId = VB_INVALID_POOLID;
FH_UINT32 rgbs[] = {0xFFFF0000, 0xFFED9121, 0xFFFFFF00, 0xFF00C957, 0xFF00FFFF, 0xFF1E90FF, 0xFF8A2BE2, 0xff000000};
int cnt = sizeof(rgbs) / sizeof(FH_UINT32);
for (int i = 0; i < cnt; i++) {
RECT_S rect;
rect.s32X = i * width / cnt;
rect.s32Y = 0;
rect.u32Width = width / cnt;
rect.u32Height = height * 7 / 8;
FH_VGS_DoFillColor(&frmYUV, &rect, rgbs[i]);
}
cnt = 0x10;
for (int i = 0; i < cnt; i++) {
RECT_S rect;
rect.s32X = i * width / cnt;
rect.s32Y = height * 7 / 8;
rect.u32Width = width / cnt;
rect.u32Height = height / 8;
FH_UINT32 rgb = 0xff | i | i << 4 | i << 8 | i << 12 | i << 16 | i << 20 ;
FH_VGS_DoFillColor(&frmYUV, &rect, rgb);
}
//convert to user frame
memset(pUsrPic, 0, sizeof(FH_VPU_USER_PIC));
pUsrPic->pic_size.u32Width = width;
pUsrPic->pic_size.u32Height = height;
pUsrPic->yluma = u32YUVPhyAddr;
pUsrPic->chroma = u32YUVPhyAddr + width * height;
pUsrPic->ystride = width;
pUsrPic->cstride = width;
pUsrPic->data_format = type;
pUsrPic->work_mode = VPU_MODE_MEM;
pUsrPic->pool_id = FH_VB_Handle2PoolId(VbBlk);
FH_SYS_GetCurPts(&pUsrPic->time_stamp );
exit0:
return ret;
}
static int __vpu_gosd_draw_text(unsigned char *bitmap, int width, int height, char *word)
{
int ascent = 0;
int descent = 0;
int lineGap = 0;
/* 计算字体缩放 */
float pixels = 32.0;
float scale = stbtt_ScaleForPixelHeight(&gst_infoFont, pixels); /* scale = pixels / (ascent - descent) */
/**
*
* ascent线
* descent线
* lineGap
* ascent - descent + lineGap
*/
stbtt_GetFontVMetrics(&gst_infoFont, &ascent, &descent, &lineGap);
/* 根据缩放调整字高 */
ascent = roundf(ascent * scale);
descent = roundf(descent * scale);
int x = 0; /*位图的x*/
/* 循环加载word中每个字符 */
for (int i = 0; i < strlen(word); ++i) {
/**
*
* advanceWidth
* leftSideBearing
*/
int advanceWidth = 0;
int leftSideBearing = 0;
stbtt_GetCodepointHMetrics(&gst_infoFont, word[i], &advanceWidth, &leftSideBearing);
/* 获取字符的边框(边界) */
int c_x1, c_y1, c_x2, c_y2;
stbtt_GetCodepointBitmapBox(&gst_infoFont, word[i], scale, scale, &c_x1, &c_y1, &c_x2, &c_y2);
/* 计算位图的y (不同字符的高度不同) */
int y = ascent + c_y1 + 8; //+8 add y offset
/* 渲染字符 */
int byteOffset = x + roundf(leftSideBearing * scale) + (y * width);
stbtt_MakeCodepointBitmap(&gst_infoFont, bitmap + byteOffset, c_x2 - c_x1, c_y2 - c_y1, width, scale, scale, word[i]);
/* 调整x */
x += roundf(advanceWidth * scale);
/* 调整字距 */
int kern;
kern = stbtt_GetCodepointKernAdvance(&gst_infoFont, word[i], word[i + 1]);
x += roundf(kern * scale);
}
return 0;
}
static int __vpu_gosd_draw_chn_info(int grpid, int chn, int width, int height, int type, VB_BLK *pVbBlk)
{
int ret = 0;
char chntilte[64];
char chntype[16];
switch (type) {
case VPU_VOMODE_SCAN:
strcpy(chntype, "NV12");
break;
case VPU_VOMODE_NV16:
strcpy(chntype, "NV16");
break;
case VPU_VOMODE_YUYV:
strcpy(chntype, "YUYV");
break;
case VPU_VOMODE_BLK :
strcpy(chntype, "BLK");
break;
case VPU_VOMODE_RGB888:
strcpy(chntype, "RGB888");
break;
case VPU_VOMODE_TILE192:
strcpy(chntype, "TILE192");
break;
case VPU_VOMODE_TILE224:
strcpy(chntype, "TILE224");
break;
case VPU_VOMODE_TILE256:
strcpy(chntype, "TILE256");
break;
case VPU_VOMODE_RRGGBB:
strcpy(chntype, "RRGGBB");
break;
default:
sprintf(chntype, "T%d", type);
}
sprintf(chntilte, "CH%d: %dx%d %s", chn, width, height, chntype);
//allocate the memory, generate the bitmap
int bitmap_w = ALIGNTO(width / 2 , 16); /* 位图的宽 */
int bitmap_h = 48; /* 位图的高 */
VB_BLK VbBlk;
FH_UINT32 u32PhyAddr;
FH_UINT8 *pVirAddr;
int size = bitmap_w * bitmap_h;
/* get video buffer block form common pool */
VbBlk = FH_VB_GetBlock(VB_INVALID_POOLID, size, NULL);
if (VB_INVALID_HANDLE == VbBlk) {
printf("ERR: SetUserPic FY_MPI_VB_GetBlock failed!\n");
ret = -__LINE__;
goto exit;
}
/* get physical address*/
u32PhyAddr = FH_VB_Handle2PhysAddr(VbBlk);
if (0 == u32PhyAddr) {
printf("ERR: SetUserPic FY_MPI_VB_Handle2PhysAddr failed!\n");
ret = -__LINE__;
goto exit;
}
pVirAddr = FH_SYS_Mmap(u32PhyAddr, size);
if (NULL == pVirAddr) {
printf("ERR: SetUserPic FY_MPI_SYS_MmapCache failed!\n");
FH_VB_ReleaseBlock(VbBlk);
ret = -__LINE__;
goto exit;
}
memset(pVirAddr, 0, size);
__vpu_gosd_draw_text(pVirAddr, bitmap_w, bitmap_h, chntilte);
for (int i = 0; i < size; i++) {
pVirAddr[i] = pVirAddr[i] >> 4;
}
FH_SYS_Munmap(pVirAddr, size);
//set the gosd
FH_VPU_LOGOV2 logo;
memset(&logo, 0, sizeof(logo));
logo.logo_enable = 1;
logo.logo_idx = 0;
logo.logo_pixdepth = 8;
logo.logo_startpos.u32X = 32;
logo.logo_startpos.u32Y = 32;
logo.stride_value = bitmap_w;
logo.logo_addr = u32PhyAddr;
logo.logo_cfg.global_alpha_en = 1;
logo.logo_cfg.global_alpha = 80;
logo.logo_cfg.rgb16_type = 1;
logo.logo_cfg.logo_size.u32Width = bitmap_w;
logo.logo_cfg.logo_size.u32Height = bitmap_h;
for (int i = 0; i < 16; i++) {
FH_UINT32 v = ((i == 0) ? 0 : i * 16 + 1);
logo.color[i] = ((0xff << 24) | (v << 16) | (v << 8) | v );
}
ret = FH_VPSS_SetChnGraphV2(grpid, chn, &logo);
if (ret) {
printf("FH_VPSS_SetChnGraphV2 fsailed! ret = 0x%x\n", ret);
}
if(pVbBlk) {
*pVbBlk = VbBlk;
}
exit:
//FH_VB_ReleaseBlock(VbBlk);
return ret;
}
static int __gosd_load_logo(char* fname, VB_BLK* pVB)
{
int ret = 0;
FILE *fp = NULL;
*pVB = VB_INVALID_HANDLE;
if (NULL == fname) {
return -1;
} else {
fp = fopen(fname, "rb");
if (NULL == fp) {
printf("ERR: file: %s open failed!\n", fname);
return -1;
}
}
{
VB_BLK VbBlk;
FH_UINT32 u32PhyAddr;
FH_UINT8 *pVirAddr;
FH_VPU_USER_PIC userPic;
int file_size = 0;
int fpos = 0;
memset(&userPic, 0, sizeof(userPic));
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
fpos = 0;
while (fpos < file_size) {
/* get video buffer block form common pool */
VbBlk = FH_VB_GetBlock(VB_INVALID_POOLID, file_size, NULL);
if (VB_INVALID_HANDLE == VbBlk) {
printf("ERR: SetUserPic FH_VB_GetBlock failed!\n");
ret = -__LINE__;
goto exit_set_pic;
}
/* get physical address*/
u32PhyAddr = FH_VB_Handle2PhysAddr(VbBlk);
if (0 == u32PhyAddr) {
printf("ERR: SetUserPic FH_VB_Handle2PhysAddr failed!\n");
ret = -__LINE__;
goto exit_set_pic;
}
pVirAddr = FH_SYS_Mmap(u32PhyAddr, file_size);
if (NULL == pVirAddr) {
printf("ERR: SetUserPic FH_SYS_MmapCache failed!\n");
FH_VB_ReleaseBlock(VbBlk);
ret = -__LINE__;
goto exit_set_pic;
}
//read the yuv data from the file
fread(pVirAddr, 1, file_size, fp);
FH_SYS_Munmap(pVirAddr, file_size);
*pVB = VbBlk;
break;
}
}
exit_set_pic:
if (fp) {
fclose(fp);
}
return ret;
}
static int __vpu_gosd_group(int grpid)
{
int ret = 0;
FH_VPU_LOGOV2 logo;
VB_BLK vb = VB_INVALID_HANDLE;
ret = __gosd_load_logo("res/logo_565.rgb", &vb);
if (!ret) {
memset(&logo, 0, sizeof(logo));
logo.logo_enable = 1;
logo.logo_idx = 1;
logo.logo_pixdepth = 16; //16bit
logo.logo_startpos.u32X = 32;
logo.logo_startpos.u32Y = 512;
logo.stride_value = 720 * 2;
logo.logo_addr = FH_VB_Handle2PhysAddr(vb);
logo.logo_cfg.global_alpha_en = 1;
logo.logo_cfg.global_alpha = 128;
logo.logo_cfg.rgb16_type = 1;
logo.logo_cfg.logo_size.u32Width = 720;
logo.logo_cfg.logo_size.u32Height = 42;
ret = FH_VPSS_SetGlbGraphV2(grpid, &logo);
if (ret) {
printf("FH_VPSS_SetGlbGraphV2 fsailed! ret = 0x%x\n", ret);
}
}
return ret;
}
#if 0
static int __gosd_fill_rect(unsigned char *bitmap, int mw, int mh, RECT_S rect)
{
int base_y = rect.s32Y * mw;
for(int i=0; i<rect.u32Width; i++)
{
for(int j; j<rect.u32Height; j++)
{
bitmap[base_y + i + mw*j] = 0x01;
}
}
return 0;
}
static int __vpu_gosd_draw_rect(unsigned char *bitmap, int mw, int mh,RECT_S *box, int box_num)
{
int num = 0;
FH_UINT32 line_width = 4;
RECT_S rect;
for(; num<box_num; num++)
{
// draw up
rect.s32X = box[num].s32X - line_width / 2;
rect.s32Y = box[num].s32Y - line_width / 2;
rect.u32Width = box[num].u32Width;
rect.u32Height = line_width;
__gosd_fill_rect(bitmap, mw, mh, rect);
printf("*******x=%d y=%d w=%d h=%d *********\n", rect.s32X, rect.s32Y, rect.u32Width, rect.u32Height);
// draw_down
rect.s32X = box[num].s32X - line_width / 2;
rect.s32Y = box[num].s32Y - line_width / 2 + box[num].u32Height;
rect.u32Width = box[num].u32Width;
rect.u32Height = line_width;
__gosd_fill_rect(bitmap, mw, mh, rect);
// printf("******* after __gosd_fill_rect 2*********\n");
printf("*******x=%d y=%d w=%d h=%d *********\n", rect.s32X, rect.s32Y, rect.u32Width, rect.u32Height);
// draw_left
rect.s32X = box[num].s32X - line_width / 2;
rect.s32Y = box[num].s32Y - line_width / 2;
rect.u32Width = line_width;
rect.u32Height = box[num].u32Height;
__gosd_fill_rect(bitmap, mw, mh, rect);
printf("*******x=%d y=%d w=%d h=%d *********\n", rect.s32X, rect.s32Y, rect.u32Width, rect.u32Height);
// draw_right
rect.s32X = box[num].s32X - line_width / 2 + box[num].u32Width;
rect.s32Y = box[num].s32Y - line_width / 2;
rect.u32Width = line_width;
rect.u32Height = box[num].u32Height;
__gosd_fill_rect(bitmap, mw, mh, rect);
printf("*******x=%d y=%d w=%d h=%d *********\n", rect.s32X, rect.s32Y, rect.u32Width, rect.u32Height);
}
return 0;
}
#endif
static int __vpu_gosd_draw_title(int grpid, int chn, int x, int y, int index, char* chntilte, VB_BLK *pVbBlk)
{
int ret = 0;
FH_VPU_CHN_CONFIG stChnAttr;
ret = FH_VPSS_GetChnAttr(grpid, chn, &stChnAttr);
//allocate the memory, generate the bitmap
int bitmap_w = ALIGNTO(stChnAttr.vpu_chn_size.u32Width / 2 , 16); /* 位图的宽 */
int bitmap_h = 48; /* 位图的高 */
VB_BLK VbBlk;
FH_UINT32 u32PhyAddr;
FH_UINT8 *pVirAddr;
int size = bitmap_w * bitmap_h;
/* get video buffer block form common pool */
VbBlk = FH_VB_GetBlock(VB_INVALID_POOLID, size, NULL);
if (VB_INVALID_HANDLE == VbBlk) {
printf("ERR: SetUserPic FY_MPI_VB_GetBlock failed!\n");
ret = -__LINE__;
goto exit;
}
/* get physical address*/
u32PhyAddr = FH_VB_Handle2PhysAddr(VbBlk);
if (0 == u32PhyAddr) {
printf("ERR: SetUserPic FY_MPI_VB_Handle2PhysAddr failed!\n");
ret = -__LINE__;
goto exit;
}
pVirAddr = FH_SYS_Mmap(u32PhyAddr, size);
if (NULL == pVirAddr) {
printf("ERR: SetUserPic FY_MPI_SYS_MmapCache failed!\n");
FH_VB_ReleaseBlock(VbBlk);
ret = -__LINE__;
goto exit;
}
memset(pVirAddr, 0, size);
__vpu_gosd_draw_text(pVirAddr, bitmap_w, bitmap_h, chntilte);
for (int i = 0; i < size; i++) {
pVirAddr[i] = pVirAddr[i] >> 4;
}
FH_SYS_Munmap(pVirAddr, size);
//set the gosd
FH_VPU_LOGOV2 logo;
memset(&logo, 0, sizeof(logo));
logo.logo_enable = 1;
logo.logo_idx = index;
logo.logo_pixdepth = 8;
logo.logo_startpos.u32X = x;
logo.logo_startpos.u32Y = y;
logo.stride_value = bitmap_w;
logo.logo_addr = u32PhyAddr;
logo.logo_cfg.global_alpha_en = 1;
logo.logo_cfg.global_alpha = 80;
logo.logo_cfg.rgb16_type = 1;
logo.logo_cfg.logo_size.u32Width = bitmap_w;
logo.logo_cfg.logo_size.u32Height = bitmap_h;
for (int i = 0; i < 16; i++) {
FH_UINT32 v = ((i == 0) ? 0 : i * 16 + 1);
logo.color[i] = ((0xff << 24) | (v << 16) | (v << 8) | v );
}
ret = FH_VPSS_SetChnGraphV2(grpid, chn, &logo);
if (ret) {
printf("FH_VPSS_SetChnGraphV2 fsailed! ret = 0x%x\n", ret);
}
if(pVbBlk) {
*pVbBlk = VbBlk;
}
exit:
//FH_VB_ReleaseBlock(VbBlk);
return ret;
}
static int __vpu_gosd_update_title(int grpid, int chn, int index, char* chntilte)
{
int ret = 0;
//get the current osd
FH_VPU_LOGOV2 logo;
memset(&logo, 0, sizeof(logo));
logo.logo_idx = index;
ret = FH_VPSS_GetChnGraphV2(grpid, chn, &logo);
IPO_LOG_CHECK_GOTO(ret, exit, "FH_VPSS_GetChnGraphV2 failed! ret = 0x%x", ret);
//allocate the memory, generate the bitmap
int bitmap_w = logo.logo_cfg.logo_size.u32Width; /* 位图的宽 */
int bitmap_h = logo.logo_cfg.logo_size.u32Height; /* 位图的高 */
FH_UINT32 u32PhyAddr;
FH_UINT8 *pVirAddr;
int size = bitmap_w * bitmap_h;
/* get video buffer block form common pool */
u32PhyAddr = logo.logo_addr;
pVirAddr = FH_SYS_Mmap(u32PhyAddr, size);
if (NULL == pVirAddr) {
printf("ERR: SetUserPic FY_MPI_SYS_MmapCache failed!\n");
ret = -__LINE__;
goto exit;
}
memset(pVirAddr, 0, size);
__vpu_gosd_draw_text(pVirAddr, bitmap_w, bitmap_h, chntilte);
for (int i = 0; i < size; i++) {
pVirAddr[i] = pVirAddr[i] >> 4;
}
FH_SYS_Munmap(pVirAddr, size);
exit:
return ret;
}
static int __vpu_set_mask(int grpid, int src_width, int src_height, const char* prefix)
{
int i;
FH_VPU_MASK mask;
memset(&mask, 0, sizeof(mask));
mask.masaic.masaic_enable = config_get_int(prefix, "mask.masaic.enable", 0);
mask.masaic.masaic_size = config_get_int(prefix, "mask.masaic.size", 0);
mask.color = config_get_int(prefix, "mask.color", 0);;
for (i = 0; i < MAX_MASK_AREA; i++) {
mask.mask_enable[i] = 1;
mask.area_value[i].u32X = rand() % src_width;
mask.area_value[i].u32Y = rand() % src_height;
mask.area_value[i].u32Width = rand() % (src_width - mask.area_value[i].u32X);
mask.area_value[i].u32Height = rand() % (src_height - mask.area_value[i].u32Y);
}
FH_VPSS_SetMask(grpid, &mask);
return 0;
}
int vpu_group_init_by_config(const char* node)
{
FH_SINT32 ret = 0;
FH_VPU_SET_GRP_INFO grp_info;
FH_UINT32 grpid = 0;
FH_UINT32 chan_vpu = 0;
FH_VPU_SIZE vi_pic;
//fill the group info
memset(&grp_info, 0, sizeof(grp_info));
grp_info.vi_max_size.u32Width = config_get_int(node, "group.vi_max_size.u32Width", -1);
grp_info.vi_max_size.u32Height = config_get_int(node, "group.vi_max_size.u32Height", -1);
grp_info.ycmean_en = config_get_int(node, "group.ycmean_en", 0);
grp_info.ycmean_ds = config_get_int(node, "group.ycmean_ds", 0);
ret = FH_VPSS_CreateGrp(grpid, &grp_info);
if (ret) {
printf("Error(%d - %x): FH_VPSS_CreateGrp (grp):(%d)!\n", ret, ret, grpid);
return ret;
}
//set vi attr
vi_pic.vi_size.u32Width = config_get_int(node, "group.vi_max_size.u32Width", -1);
vi_pic.vi_size.u32Height = config_get_int(node, "group.vi_max_size.u32Height", -1);
vi_pic.crop_area.crop_en = 0;
vi_pic.crop_area.vpu_crop_area.u32X = 0;
vi_pic.crop_area.vpu_crop_area.u32Y = 0;
vi_pic.crop_area.vpu_crop_area.u32Width = 0;
vi_pic.crop_area.vpu_crop_area.u32Height = 0;
ret = FH_VPSS_SetViAttr(grpid, &vi_pic);
if (ret != 0) {
printf("Error(%d - %x): FH_VPSS_SetViAttr (grp):(%d)!\n", ret, ret, grpid);
return ret;
}
int vimode = config_get_int(node, "group.vimode", VPU_MODE_MEM);
FH_VPSS_Enable(grpid, vimode);
//set group osd
__vpu_gosd_group(grpid);
//get channel info
for (int i = 0; i < 5; i++) {
char chnode[32];
if (0 == config_has_index(node, "channels", i)) {
continue;
}
sprintf(chnode, "%s.channels[%d]", node, i);
FH_VPU_CHN_INFO chn_info;
FH_VPU_CHN_CONFIG chn_attr;
int chn_width, chn_height, chn_type;
chan_vpu = i;
memset(&chn_info, 0, sizeof(chn_info));
chn_info.bgm_enable = config_get_int(chnode, "info.bgm_enable", 0);
chn_info.cpy_enable = config_get_int(chnode, "info.cpy_enable", 0);
chn_info.sad_enable = config_get_int(chnode, "info.sad_enable", 0);
chn_info.bgm_ds = config_get_int(chnode, "info.bgm_ds", 0);
chn_info.chn_max_size.u32Width = config_get_int(chnode, "info.chn_max_size.u32Width", -1);
chn_info.chn_max_size.u32Height = config_get_int(chnode, "info.chn_max_size.u32Height", -1);
chn_info.out_mode = config_get_int(chnode, "info.out_mode", -1);
chn_info.support_mode = config_get_int(chnode, "info.support_mode", -1);
chn_info.bufnum = config_get_int(chnode, "info.bufnum", 0);
chn_info.max_stride = config_get_int(chnode, "info.max_stride", 0);
ret = FH_VPSS_CreateChn(grpid, chan_vpu, &chn_info);
if (ret != 0) {
printf("Error(%d - %x): FH_VPSS_CreateChn (grp-chn):(%d-%d)!\n", ret, ret, grpid, chan_vpu);
return ret;
}
if(config_has_key(chnode, "info", "visel")) {
int visel = config_get_int(chnode, "info.visel", 1);
if(0 == visel) {
ret = FH_VPSS_SetChnViSel(grpid, chan_vpu, visel);
IPO_LOG_PRT("Set visel to %d for CHN %d, ret = 0x%x\n", visel, chan_vpu, ret);
}
}
if (0 == config_has_key(chnode, NULL, "config")) {
continue;
}
memset(&chn_attr, 0, sizeof(chn_attr));
chn_width = config_get_int(chnode, "config.vpu_chn_size.u32Width", -1);
chn_height = config_get_int(chnode, "config.vpu_chn_size.u32Height", -1);
chn_attr.vpu_chn_size.u32Width = chn_width;
chn_attr.vpu_chn_size.u32Height = chn_height;
chn_attr.stride = config_get_int(chnode, "config.stride", 0);
chn_attr.offset = config_get_int(chnode, "config.offset", 0);
chn_attr.depth = config_get_int(chnode, "config.depth", -1);
ret = FH_VPSS_SetChnAttr(grpid, chan_vpu, &chn_attr);
if (ret != 0) {
printf("Error(%d - %x): FH_VPSS_SetChnAttr (grp-chn):(%d-%d)!\n", ret, ret, grpid, chan_vpu);
return ret;
}
chn_type = config_get_int(chnode, "vomode", -1);
ret = FH_VPSS_SetVOMode(grpid, chan_vpu, chn_type);
if (ret != 0) {
printf("Error(%d - %x): FH_VPSS_SetVOMode (grp-chn):(%d-%d)!\n", ret, ret, grpid, chan_vpu);
return ret;
}
ret = FH_VPSS_SetVORotate(grpid, chan_vpu, 0);
if (ret != 0) {
printf("Error(%d - %x): FH_VPSS_SetVORotate (grp-chn):(%d-%d)!\n", ret, ret, grpid, chan_vpu);
return ret;
}
ret = FH_VPSS_OpenChn(grpid, chan_vpu);
if (ret != 0) {
printf("Error(%d - %x): FH_VPSS_OpenChn (grp-chn):(%d-%d)!\n", ret, ret, grpid, chan_vpu);
return ret;
}
//draw osd for channel
if (chan_vpu < 0) {
__vpu_gosd_draw_chn_info(grpid, chan_vpu, chn_width, chn_height, chn_type, NULL);
FH_UINT64 tick = 0;
FH_SYS_GetCurPts(&tick);
char osdtime[64];
sprintf(osdtime, "Tick: %lld\n", tick);
__vpu_gosd_draw_title(grpid, chan_vpu, 32, 100, 1, osdtime, NULL);
}
}
//set the mask
if(config_has_key(node, NULL, "mask")) {
__vpu_set_mask(grpid, vi_pic.vi_size.u32Width, vi_pic.vi_size.u32Height, node);
}
return ret;
}
int vpu_update_gosd(int grpid, int chn, int index)
{
FH_UINT64 tick = 0;
FH_SYS_GetCurPts(&tick);
char osdtime[64];
sprintf(osdtime, "Tick: %lld\n", tick);
__vpu_gosd_update_title(grpid, chn, 1, osdtime);
return 0;
}
void vpu_send_offline_pic(void* param)
{
int ret = 0;
int vi_mode = 0;
FH_UINT32 grpid = 0;
FH_UINT32 cnt = 0;
char *node = (char*)param;
IPO_LOG_PRT("node = %s!\n", node);
vi_mode = config_get_int(node, "group.vimode", VPU_MODE_MEM);
IPO_LOG_PRT("vi_mode = %d\n", vi_mode);
if ((VPU_MODE_MEM == vi_mode) || (VPU_MODE_OFFLINE_2DLUT == vi_mode)) {
int src_width = config_get_int(node, "src.width", 0);
int src_height = config_get_int(node, "src.height", 0);
int mode = config_get_int(node, "src.mode", VPU_VOMODE_SCAN);
FH_VPU_USER_PIC userpic;
const char *fname = config_get_string(node, "src.filename", NULL);
// const char *fname = 0;
if (NULL == fname) {
IPO_LOG_PRT("no src file must be given!generate it\n");
__generate_user_pic(src_width, src_height, mode, &userpic);
} else {
IPO_LOG_PRT("yuv file = %s\n", fname);
__load_user_pic(src_width, src_height, mode, (char*)fname, &userpic);
}
while (g_bRunning) {
ret = FH_VPSS_SendUserPic(grpid, &userpic);
if (0 == ret) {
++cnt;
}
{
usleep(500 * 1000);
}
}
}
}
int vpu_test_case(int tcase)
{
FH_SINT32 ret;
//FH_UINT32 grpid = 0;
FH_UINT64 duration = 0;
FH_UINT32 intval = 0;
char node[64];
char cases[64];
sprintf(cases, "test_cases[%d]", tcase);
sprintf(node, "test_cases[%d].vpu", tcase);
//get test param
duration = config_get_int(cases, "param.duration", 2000);
intval = config_get_int(cases, "param.interval", 0);
printf("case[%d: duration = %lld, intval = %d\n", tcase, duration, intval);
duration = duration * 1000;
ret = vpu_group_init_by_config(node);
if (0 != ret) {
printf("vpu_group_chn_init failed!\n");
return ret;
}
return ret;
}
void vpu_test_channels(void *param)
{
FH_SIZE sizes[] = {
{352, 288},
{640, 480},
{720, 576},
{1280, 720},
{1920, 1088},
{2560, 1440},
{3840, 2160},
{4096, 2160},
};
int vomodes[] = {VPU_VOMODE_BLK, VPU_VOMODE_SCAN, VPU_VOMODE_TILE192, VPU_VOMODE_TILE224, VPU_VOMODE_TILE256};
int ret = 0;
int szz[] = {8, 5, 4};
int mods[] = {5, 5, 2};
int grpid = 0;
int channels = 3;
int chan_vpu;
VB_BLK blk = VB_INVALID_HANDLE, blk2 = VB_INVALID_HANDLE;
for (chan_vpu = 0; chan_vpu < channels; chan_vpu++) {
int szs = szz[chan_vpu];
int z = 0;
for (z = 0; z < szs; z++) {
if(!g_bRunning) {
goto exit;
}
int fmts = mods[chan_vpu];
int f = 0;
for (f = 0; f < fmts; f++) {
FH_VPU_CHN_CONFIG chn_attr;
memset(&chn_attr, 0, sizeof(chn_attr));
chn_attr.vpu_chn_size.u32Width = sizes[z].u32Width;
chn_attr.vpu_chn_size.u32Height = sizes[z].u32Height;
chn_attr.stride = sizes[z].u32Width;
chn_attr.offset = 0;
chn_attr.depth = 1;
ret = FH_VPSS_SetChnAttr(grpid, chan_vpu, &chn_attr);
if (ret != 0) {
printf("Error(%d - %x): FH_VPSS_SetChnAttr (grp-chn):(%d-%d)!\n", ret, ret, grpid, chan_vpu);
goto exit;
}
ret = FH_VPSS_SetVOMode(grpid, chan_vpu, vomodes[f]);
if (ret != 0) {
printf("Error(%d - %x): FH_VPSS_SetVOMode (grp-chn):(%d-%d)!\n", ret, ret, grpid, chan_vpu);
goto exit;
}
ret = FH_VPSS_SetVORotate(grpid, chan_vpu, 0);
if (ret != 0) {
printf("Error(%d - %x): FH_VPSS_SetVORotate (grp-chn):(%d-%d)!\n", ret, ret, grpid, chan_vpu);
goto exit;
}
ret = FH_VPSS_OpenChn(grpid, chan_vpu);
if (ret != 0) {
printf("Error(%d - %x): FH_VPSS_OpenChn (grp-chn):(%d-%d)!\n", ret, ret, grpid, chan_vpu);
goto exit;
}
//draw osd for channel
if (chan_vpu < 3) {
__vpu_gosd_draw_chn_info(grpid, chan_vpu, sizes[z].u32Width, sizes[z].u32Height, vomodes[f], &blk);
/*
FH_UINT64 tick = 0;
FH_SYS_GetCurPts(&tick);
char osdtime[64];
sprintf(osdtime, "Tick: %lld\n", tick);
__vpu_gosd_draw_title(grpid, chan_vpu, 32, 100, 1, osdtime, &blk2);
*/
}
sleep(3);
ret = FH_VPSS_CloseChn(grpid, chan_vpu);
if (ret != 0) {
printf("Error(%d - %x): FH_VPSS_CloseChn (grp-chn):(%d-%d)!\n", ret, ret, grpid, chan_vpu);
goto exit;
}
if(VB_INVALID_HANDLE != blk) {
FH_VB_ReleaseBlock(blk);
}
if(VB_INVALID_HANDLE != blk2) {
FH_VB_ReleaseBlock(blk2);
}
}
}
}
exit:
g_bRunning = 0;
}
int vpu_test_case_format()
{
FH_SINT32 ret;
int tcase = 1;
char node[64];
char cases[64];
sprintf(cases, "test_cases[%d]", tcase);
sprintf(node, "test_cases[%d].vpu", tcase);
ret = vpu_group_init_by_config(node);
if (0 != ret) {
printf("vpu_group_chn_init failed!\n");
return ret;
}
return 0;
}
FH_SINT32 fh_vpu_init(FH_VOID);
FH_SINT32 fh_vpu_close(FH_VOID);
int vpu_test_init()
{
int ret = 0;
ret = __gosd_font_init();
ret = fh_vpu_init();
return ret;
}
int vpu_test_exit()
{
int ret = 0;
__gosd_font_cleanup();
ret = fh_vpu_close();
return ret;
}