嘉楠科技
直播中

刘燕

8年用户 1467经验值
私信 关注
[问答]

请问Linux+RT sdk怎么在大核vi出图的时候左上角或右上角osd叠加时间戳?

vi出图就马上进行叠加,已看 /src/big/mpp/userapps/sample/sample_vicap/sample_vicap.c出图例程
总结:需要解决叠加字体的来源,字体大小(先出样品,还不知道客户想要多大的),然后怎么叠加。

回帖(1)

刘艳

2025-8-20 16:59:59

在 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) 的第三个参数(高度像素值),根据客户需求调整。




  • 叠加位置  



    • 左上角stPoint.s32X = 10, stPoint.s32Y = 10  

    • 右上角:  
      stPoint.s32X = SCREEN_WIDTH - stRgnAttr.unAttr.stOverlay.stSize.u32Width - 10;
      stPoint.s32Y = 10;




  • 透明效果  



    • u32BgAlpha=0:背景完全透明  

    • u32FgAlpha=255:文字完全不透明(可调为半透明)






3. 性能优化建议




  1. 避免每帧渲染

    每秒更新一次时间戳(检测秒级变化),减少 Freetype 调用频率。


    static int last_sec = -1;
    time_t now = time(NULL);
    if (last_sec != now % 60) {
       last_sec = now % 60;
       // 更新时间戳
    }



  2. 预渲染常用字符

    预先渲染 0-9:- 等字符,复用位图减少实时渲染开销。




  3. 硬件加速

    若平台支持,使用 TDE(硬件加速模块)混合位图:


    HI_MPI_TDE_BitmapMix(...); // 替代软件叠加





4. 完整流程总结



  1. 初始化:创建 OSD 区域并绑定到 VI 通道。

  2. 渲染字体:用 Freetype 将时间字符串转为位图。

  3. 帧回调:在 VI 输出帧时更新 OSD 位图。

  4. 释放资源:程序退出时销毁区域和 Freetype 对象。



注意事项  



  • 确保 MPPRegion 模块已初始化(参考 sample_vicap 中的 SAMPLE_COMM_SYS_Init())。  

  • 字体路径需绝对路径,嵌入式设备需提前部署字体文件。  

  • 调试时先用静态文本(如 "Test")验证叠加效果,再接入时间戳。



通过以上步骤,即可在 VI 输出图像的指定位置实时叠加时间戳,并根据客户需求调整字体大小和位置。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分