以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。
一、代码框架分析
在第8季2:OSD实验演示与代码分析中,我们分析了SAMPLE_RGN_CreateVideoRegion函数,该函数完成了左下角的logo区域显示、右下角的时间区域显示,基于直接的bmp图片来显示。
接下来我们将分析左上角、右上角的区域,这两个区域都是利用字库字符来实现显示的。其本质是目前没有现成的bmp图片,需要先通过字库,生成对应文字内容的bmp文件(新的内容),然后再将bmp文件在区域里显示(这和之前的一样)。
这涉及HH_OSD_Init、while循环与HH_OSD_All_Refresh函数,它们的调用关系如下。
HH_OSD_Init//初始化
HH_OSD_SetOsdPosDefault//设置区域的坐标
HH_OSD_GetOrg//获取显示的坐标
HH_OSD_GetColor//获取颜色
HH_OSD_GetTitle//获取要显示的内容
HI_Create_Osd//实例化一个HH_OSD_LOGO结构体变量,并填充其成员变量
HI_OSD_Build//创建区域 、创建位图、直接显示
HI_OSD_Parse_OsdTitle //解析osd的字符,更新字符相关属性
HI_OSD_Get_BmpSize //根据视频源的大小来配置区域的字模宽高、xy坐标等
HI_OSD_Get_ImaSize//获取视频源的宽与高,这个值在ipc_conf全局变量中配置
HI_Create_Osd_Reg //创建区域
HI_MPI_RGN_Create
HI_MPI_RGN_AttachToChn
HI_OSD_Create_Bitmap //根据pOsdlogo记录的要显示的内容,创建bmp文件,然后调用HI_MPI_RGN_SetBitMap来显示
HI_OSD_CreateBMP //用字库来生成bmp文件
HI_MPI_RGN_SetBitMap //真正设置osd显示的API,另外的一种方法见本季1博文
HI_OSD_Set_Show //根据传参来决定osd区域的显示或者关闭
HI_MPI_RGN_GetDisplayAttr
HI_MPI_RGN_SetDisplayAttr
while{
HH_OSD_All_Refresh
HH_OSD_AllTime_Refresh//刷新右上角的内容显示
HH_OSD_ChnTime_Refresh
HH_OSD_ChName_Refresh
HH_OSD_GetLogoHandle
HH_OSD_GetTitle
HI_OSD_Parse_OsdTitle
HI_OSD_Get_BmpSize
HI_OSD_Create_Bitmap
HI_OSD_CreateBMP
HI_MPI_RGN_SetBitMap
HH_OSD_Show_Refresh
HH_OSD_GetLogoHandle
HH_OSD_GetShow
HI_OSD_Set_Show
HH_OSD_AllName_Refresh//刷新左上角的内容显示
HH_OSD_ChnAllName_Refresh
HH_OSD_ChName_Refresh
//和上面的一样
}
从调用函数关系可知,如果只把while循环部分注释掉,由于HH_OSD_Init完成了一些区域显示相关的设置,此时左上角、右上角依然存在区域内容,但是因为没有while循环刷新,因此右上角的区域内容不会刷新。如下图所示。
二、利用字库字符实现区域显示的源码解析
1、相关文件概述
在mpp/sample/osd目录下有许多文件:
root@ubuntu:/home/xjh/iot/hisi_development/Hi3518E_SDK/Hi3518E_SDK_V1.0.3.0/mpp/sample/osd# ls
hh_hz16lib.c hh_hz16lib.h hh_osd_api.c hh_osd_api.h hh_osd.c hh_osd.h
root@ubuntu:/home/xjh/iot/hisi_development/Hi3518E_SDK/Hi3518E_SDK_V1.0.3.0/mpp/sample/osd#
(1)hh_hz16lib.c 文件
该文件是字库文件,如下所示。可知其包括16点阵的字库、12点阵的字库、8点阵的字库,这些不同点阵(这里表现为字体大小不同)的字库,主要为了适应不同尺寸的屏幕。比如屏幕是1080的,那么区域的文字可以大一些,因为太小的话看起来就不清晰;如果屏幕是320*240的,那么区域的文字就应该小一些,因为文字太大的话看起来比例就不协调了。另外,这些字库与字体类型(楷体、黑体等)也有关,不同字体类型的字符文件是不一样的。
(2)hh_osd.c 文件、hh_osd_api.c 文件
其中 hh_osd.c 文件是上层文件,比如HH_OSD_Init函数位于该文件中。而 hh_osd_api.c 文件是下层文件,比如HH_OSD_Init函数所调用的、以HI开头的函数就位于该文件中。
(3)hh_osd_api.h 文件
该文件定义了一些数据结构与函数声明。其中比较重要结构体有:
typedef struct _HH_OSD_LOGO
{
VENC_GRP vencGroup ; //osd 区域叠加到的编码组
HI_U8 nStatus ; //1显示,0隐藏
HI_U8 nOsdLine ; //osd 字幕的行数
HI_U8 nOsdFontH ;
HI_U8 nOsdFontW ;
HI_U16 nWidth ; //osd 区域的宽度
HI_U16 nHeight ; //osd 区域的高度
HI_U16 nImageWidth;
HI_U16 nImageHeight;
HI_S16 nFontInt ; //osd 字符间隔
HI_U16 nVencFeild;
HI_U8 nOsdTitleMaxLen; //标记最长的一行字符的个数
HI_U8 nOsdTitleFlag[HH_MAX_TITLE_LINE]; //osd最大支持8行,标记每一行osd第一个字符在osdtitle中的位置
HI_U8 nOsdTitleLen[HH_MAX_TITLE_LINE]; //标记每一行osd 的长度
char szOsdTitle[HH_MAX_TITLE_NUM]; //osd 叠加字幕信息
HI_OSD_ORG osdPos ;
HI_OSD_COLOR osdColor ;
HI_U8 *pBmpBuf;
int regHdl ; //osd区域句柄
int nSelLine ; //标记当前行为选中行
}HH_OSD_LOGO, *PHH_OSD_LOGO;
2、分析hh_osd_api.c文件
(1)各函数的作用分析
(2)“ 汉字区位码 ” 的概念
汉字区位码,即为每个汉字编一个唯一的代码,以便计算机辨认、接收和处理。汉字区位码由区码和位码组成,有些类似于xy坐标系,区码是x轴,位码是y轴,两者确定一个汉字。