MC3302_SDK_V1.1.9_202507281.../media/sample/system/ipo/vpu.c
2025-11-11 12:08:31 +08:00

1184 lines
34 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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_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;
}
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 < 3) {
__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);
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;
}