在 Linux+RT SDK 中实现 VI 出图时叠加时间戳,需要通过以下步骤完成。核心是使用 MPP 的 OSD 模块 结合 Freetype 字体库 渲染时间字符串,并将位图叠加到视频帧上。以下是详细解决方案:
1. 核心步骤
1.1 初始化 OSD 区域
#include "hi_comm_region.h"
#include "hi_mpi_region.h"
RGN_HANDLE g_rgn_handle = 0; // 区域句柄
// 创建 OSD 区域
RGN_ATTR_S stRgnAttr = {
.enType = OVERLAY_RGN, // 叠加区域类型
.unAttr.stOverlay = {
.enPixelFmt = PIXEL_FORMAT_ARGB1555, // 透明格式
.stSize.u32Width = 320, // 区域宽度(根据字体调整)
.stSize.u32Height = 32, // 区域高度
}
};
HI_MPI_RGN_Create(g_rgn_handle, &stRgnAttr);
// 绑定到 VI 通道
RGN_CHN_ATTR_S stChnAttr = {
.bShow = HI_TRUE,
.enType = OVERLAY_RGN,
.unChnAttr.stOverlayChn = {
.stPoint.s32X = 10, // 左上角 X 坐标(右上角:屏幕宽-区域宽-10)
.stPoint.s32Y = 10, // 左上角 Y 坐标
.u32BgAlpha = 0, // 背景透明
.u32FgAlpha = 255, // 前景不透明
.u32Layer = 0, // 叠加层
}
};
MPP_CHN_S stChn = { .enModId = HI_ID_VI, .s32DevId = 0, .s32ChnId = 0 }; // VI 通道
HI_MPI_RGN_AttachToChn(g_rgn_handle, &stChn, &stChnAttr);
1.2 使用 Freetype 渲染时间戳
#include
#include FT_FREETYPE_H
FT_Library g_library;
FT_Face g_face;
// 初始化 Freetype
FT_Init_FreeType(&g_library);
FT_New_Face(g_library, "/usr/share/fonts/simhei.ttf", 0, &g_face); // 字体文件路径
FT_Set_Pixel_Sizes(g_face, 0, 24); // 设置字体大小(24像素高)
// 渲染时间字符串到位图
void render_timestamp(char* text, BITMAP_S* pBitmap) {
FT_GlyphSlot slot = g_face->glyph;
FT_Load_Char(g_face, text[i], FT_LOAD_RENDER);
pBitmap->u32Width = slot->bitmap.width;
pBitmap->u32Height = slot->bitmap.rows;
pBitmap->enPixelFormat = PIXEL_FORMAT_ARGB1555;
pBitmap->pData = malloc(pBitmap->u32Width * pBitmap->u32Height * 2);
// 将 FT_Bitmap 转换为 ARGB1555(示例伪代码)
for (int y = 0; y < slot->bitmap.rows; y++) {
for (int x = 0; x < slot->bitmap.width; x++) {
// 设置像素:透明度=0xFF,颜色=白色
*pixel = (0x80 << 8) | (0xFF << 1) | 0x1; // ARGB1555 格式
}
}
}
1.3 帧回调中更新 OSD
// 在 VI 输出帧的回调中更新时间戳
void vicap_frame_callback(VIDEO_FRAME_INFO_S* pstFrame) {
char timestr[64];
time_t now = time(NULL);
strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", localtime(&now));
BITMAP_S stBitmap;
render_timestamp(timestr, &stBitmap); // 渲染文字到位图
// 更新 OSD 区域内容
HI_MPI_RGN_SetBitMap(g_rgn_handle, &stBitmap);
free(stBitmap.pData); // 释放临时位图
}
2. 关键配置说明
字体来源
将字体文件(如 .ttf)放入嵌入式设备文件系统(如 /usr/share/fonts/),推荐使用等宽字体(如 simhei.ttf)。
字体大小调整
修改 FT_Set_Pixel_Sizes(g_face, 0, 24) 的第三个参数(高度像素值),根据客户需求调整。
叠加位置
透明效果
u32BgAlpha=0:背景完全透明
u32FgAlpha=255:文字完全不透明(可调为半透明)
3. 性能优化建议
避免每帧渲染
每秒更新一次时间戳(检测秒级变化),减少 Freetype 调用频率。
static int last_sec = -1;
time_t now = time(NULL);
if (last_sec != now % 60) {
last_sec = now % 60;
// 更新时间戳
}
预渲染常用字符
预先渲染 0-9、:、- 等字符,复用位图减少实时渲染开销。
硬件加速
若平台支持,使用 TDE(硬件加速模块)混合位图:
HI_MPI_TDE_BitmapMix(...); // 替代软件叠加
4. 完整流程总结
- 初始化:创建 OSD 区域并绑定到 VI 通道。
- 渲染字体:用 Freetype 将时间字符串转为位图。
- 帧回调:在 VI 输出帧时更新 OSD 位图。
- 释放资源:程序退出时销毁区域和 Freetype 对象。
注意事项
- 确保
MPP 和 Region 模块已初始化(参考 sample_vicap 中的 SAMPLE_COMM_SYS_Init())。
- 字体路径需绝对路径,嵌入式设备需提前部署字体文件。
- 调试时先用静态文本(如
"Test")验证叠加效果,再接入时间戳。
通过以上步骤,即可在 VI 输出图像的指定位置实时叠加时间戳,并根据客户需求调整字体大小和位置。