朱老师,3518系列,第八季
第一节, osd 理论。
区域 与 通道的绑定函数, HI_MPI_RGN_AttachToChn
一个区域 可以同多个 通道进行绑定。
两个功能 重叠。
关于 区域的重叠。
然后 开始 解释 一下 这几句话。
这是 关于 位图填充的,主要说的是 ,填充 区域。
总结:
1 、位图填充就是 对 区域 进行填充。
2 、 填充的大小与 区域的关系。
3、有两种填充方式,一种是 直接填充 画面的 framebuffer , 还有一种是填充 备份的 framebuffer.
这是再说区域的共同属性。
这是再说 区域的特性。
区域反色 指的是, 当背影与区域 颜色一致时, 区域颜色改变
区域保护,指的是,区域的编码可以与视频的编码不一致。
这里他使用的是 overlay , 只是 venc 支持这个模式, 这里 venc 有一个 device, 但是有好几个 通道, 这里 就不是很理解了。
这里的 像素格式 , Argb1555 , 后面的数字 代表的是 占的字节数, 这里一共是 16位, 2个字节。
第二节课, 依然是 osd 的一些原理。
这是使用的大致流程。
注意: 在别人的框架里 ,写程序,就要遵循他人的 定义。这些定义 对于使用框架的人来说, 是没有理由的。我好像 理解了什么。
然后来看一些一些 API。
注意:
1、 venc 的通道的概念。
2、 然后是 这里的 区域画布,指的是 区域的framebuffer.
========
来看一下 关于 RGB 的透明度的问题。
例子。
总结: alpha ,其实 是 做了运算, 本质上 还是RGB 。
==========
第三节: OSD的 代码 框架 分析。
他的演示 。
总结:
1 、 他这里一个是 静态的图片, 一个是 动态的时间。
2 、 一个是 图片信息,一个是 文字信息。
3 、 他这里 直接解压的 OSD 的压缩包 替换的 mpp , 如果是我使用的话,肯定不能是这种方式。
我已经将全部的 代码 上传到虚拟机 了, 用于解压。
代码的逻辑是这样的。
前两句 是 在 进行 固定的 图片的添加。
后面的while 循环 是在 进行 动态的时间,就是在不断的添加图片。
我的疑问:
1 、 这个循环 是不是说, 就是 不能 使用两下 空格 退出了。
2、 他这里的添加 OSD jing然不是 在 RTSP发送的函数中实现的,也就是说 海思的 ko 库, 应该是开的 线程获进程。
3、 也就是说 我这里 只要配置好就行了, 它会自动的执行。
第四节 , 代码分析一。
这个函数需要注意的是 它 对于 宽高的计算。
它的原图,是 24位的 , 320x320 的图片。
但是 osd 是 argb 1555 , 的格式的。
纵坐标都是320 这个好理解。
关键是横坐标, 原图,是 320x3 个字节。
它这里 使用 320 x3 又除以 2 明显是 计算出了,原图那么打的 数据,如果是 osd 的话,假设是多少的 像素,我觉得 以后它 还会做 像素的转化。这么做 实际上像素是增加了的。
然后接下来就是 这个 handle 了, 这个handle 是自己分配的,只要不是 重复的就行,一个 region 一个 handle .
然后就是 这个函数, 在创造 overlay .
这里 首先是 绑定了 venc , 然后是 绑定了 device ,只有一个, 然后是绑定了 channel ,也是只有一个。
stChn , 是一个 配置 channel 的结构体。
这里 是在 设置 region 的属性, 这里有一个 设置region 的背景色。
这里 就是 调用函数 ,创建了一个region.
这里是在 设置 channnel 的属性。
然后调用函数 将channel 与 region 绑定起来。
第五节, osd 代码分析 2 .
首先就是构建一个 函数的调用关系。
2 SAMPLE_RGN_CreateOverlayForVenc1 HI_MPI_RGN_Create3 HI_MPI_RGN_AttachToChn1 SAMPLE_RGN_Add2 HI_MPI_RGN_GetAttr3 HI_MPI_RGN_GetCanvasInfo4 SAMPLE_RGN_CreateSurfaceByCanvas5 SAMPLE_RGN_LoadCanvasEx6 SAMPLE_RGN_LoadBMP7 fopen8 SAMPLE_RGN_UpdateCanvas9 HI_MPI_RGN_UpdateCanvas10 SAMPLE_RGN_CreateOverlayForVenc11 SAMPLE_RGN_AddVideoTimestamp
~
这里 通过 前景色+背景色 + 前景透明度+ 背景透明度 的 组合,可以 实现 region的 透明的效果,
具体的原理不清楚。
第六节, OSD 代码 分析 3 .
他 主要在分析 这个函数。
接下来 好好分析一下 , 这个
SAMPLE_RGN_Add( Handle, VENC_RECORD_LOGO_OSD_HANDLE); 函数。
先来进入这个函数看一下。
38 HI_S32 SAMPLE_RGN_Add(unsigned int Handle,int Type)37 {36 //printf("-------------------%s add rgn %d --------------------\n",__func__,Type);3534 HI_S32 s32Ret = HI_SUCCESS;33 RGN_ATTR_S stRgnAttrSet;32 RGN_CANVAS_INFO_S stCanvasInfo;31 BITMAP_S stBitmap;30 SIZE_S stSize;2928 /* Photo logo */27 s32Ret = HI_MPI_RGN_GetAttr(Handle/*VencOsdHandle*/, &stRgnAttrSet);26 if (HI_SUCCESS != s32Ret)25 {24 printf("HI_MPI_RGN_GetAttr failed! s32Ret: 0x%x.\n", s32Ret);23 return s32Ret;22 }2120 s32Ret = HI_MPI_RGN_GetCanvasInfo(Handle/*VencOsdHandle*/, &stCanvasInfo);19 if (HI_SUCCESS != s32Ret)18 {17 printf("HI_MPI_RGN_GetCanvasInfo failed! s32Ret: 0x%x.\n", s32Ret);16 return s32Ret;15 }1413 stBitmap.pData = (void*)stCanvasInfo.u32VirtAddr;12 stSize.u32Width = stCanvasInfo.stSize.u32Width;11 stSize.u32Height = stCanvasInfo.stSize.u32Height;10 s32Ret = SAMPLE_RGN_UpdateCanvas(Type, &stBitmap, HI_TRUE , 0x0000, &stSize, stCanvasInfo.u32Stride,stRgnAttrSet.unAttr.stOverlayEx.enPixelFmt);9 if (HI_SUCCESS != s32Ret)8 {7 printf("SAMPLE_RGN_UpdateCanvas failed! s32Ret: 0x%x.\n", s32Ret);6 return s32Ret;5 }43 s32Ret = HI_MPI_RGN_UpdateCanvas(Handle/*VencOsdHandle*/);2 if (HI_SUCCESS != s32Ret)1 {794 printf("HI_MPI_RGN_UpdateCanvas failed! s32Ret: 0x%x.\n", s32Ret);1 return s32Ret;2 }34 return HI_SUCCESS;5 }
首先是定义了 几个结构体。
我觉得 这里的 stcanvasinfo , 与 stbitmap 是重复的。
stCanvasinfo 实际上是 对 logo 的抽象。
stbitmap 指向的是 canvas .
接下来进入这个函数。
接下来看看这个函数。 这是在根据 logo 原图, 创建图片。 Pdata 指向的就是 源logo 的地址。
这里 stlogo 实际上 又 复制了一份。 然后开始 加载 canvas
然后就是 加载 bmp 图片了。
这里 就是 处理 bmp 图片了,但是我没有找到 输出 在哪里。
他这里 真正输出的是 PRGBBuf.
但是 我并没有看到 怎么导出去的,那 这个函数执行完 不久 消失了吗?
欧 , 关键在 这一句。
他使用的是 pRGBBuf 但是 实际上 就是 pVideoLogo , 这个是 传进来了。
这里 是在 调整组合方式。
pDst 指的是 输出的。
pStart 指的是 原来的图片。
组合方式 由 bmp ---> canvas.
这个跟 图像 的 翻转 是一样的。
这个函数 实在 做 888 到 555 的转换。
多余的三位 直接扔掉了。
并且 最后 重新组合。
到这里 就开始 往回 走了。
这里的作用是,如果图片中,有白色, 或者 黑色, 那么我就把它的颜色 变成透明的,也就是所谓的背景色。
但是 到这里 我就看不下去了。
并没有将 stlogo 与 pstsurface 结合起来。
也就是说, 处理完了之后,函数退出之后,指针丢了。
这里 不是很理解。
这里 为什么要加上一个 线程呢?
那是因为 这个 函数里面会有一个 while 循环,这是在 打上 时间的 sod.
这里 才是 动态的画框, 之前的理解是错的。
这里 ,由于 cpu 运行的很快, 所以当发现 时间没到 一秒的时候, 会停一段时间。
然后就是 rgn_add 函数了,这个 跟图片的分析是一样的。
到这里 会做出区分,是加载图片还是 加载 时间戳。
从这里 可以看到 ,其实 时间也是由一张一张的图片组成的。
这里就是将 18 张图片 拼接成了 一张图片。
第九节, 使用字库 的方式 来实现 。
字库的显示 是这两个函数 结合再一起的 功能。
来分析 一下 函数的调用。
109 HH_OSD_Init8 HH_OSD_SetOsdPosDefault7 HH_OSD_GetOrg6 HH_OSD_GetColor5 HH_OSD_GetTitle4 HI_Create_Osd3 HI_OSD_Build2 HI_OSD_Parse_OsdTitle1 HI_OSD_Get_BmpSize28 HI_Create_Osd_Reg1 HI_OSD_Create_Bitmap2 HI_OSD_Set_Show34
总结:
1 、 字库的本质 就是 根据文字生成 bmp 图片,然后显示。
2、 之前的显示 也是 bmp 图片, 只是源文件 就是 bmp 图片。
显示 OSD 的话, 一共有两种方式。
这是 另外 一种方式。
总结:
1 OSD_init 已经可以显示了。
2 、 all_fresh 只是再刷新, 如果没有这个的话, 那么 右上角+ 左上角的 图片不会变化。
第十节 ,分析 OSD 显示的源码。
主要是在 分析这里。
这个字库的文件 很大, 但是我也没看懂。
这里的字库 ,也是 他 从别的地方移植 过来的。
这里的前景色的 边缘色 有意思,这是 来区分出 前景色+ 背景色 的。
这个函数是一个 解析字符串的函数。
这里 主要是 tileflag 与 titlelen 在做标记。
titile 存放的就是 整个的字符串。
第11节, osd 字符源码解析。
这个 show 函数 就是 显示的一种方式。
这个 函数就是在根据 字母的多少, 来计算 region 的大小
这个函数的作用 是,
1、 创建 Bmp 图片的 buffer内存。
2、 然后就是 通过海思的API, 来初始化 rgn 。
这个 函数 是真正的 在 根据 字符, 来创造 bmp 图片。
但是 这里 不继续 追进去看 他 怎么 创建的 bmp 的了。
第12节, OSD的源码 解析。
这个函数的作用是:
1 、 查看一下 视频流的大小。
2、 根据视频流的大小 调整logo 的大小。
这个函数 是一个 总览 性的函数。
这个函数的作用是:
1 、 首先 根据 区+ 位, 找到 这个汉字的位置。
2、 然后 根据大小 ,取出来, 这个汉字的 点阵。
这个函数的作用是 , 根据 一个 字符串 生成一个 bmp 图片, 然后 将很多个bmp 图片 拼接成一个 大的bmp 图片。
这个 方式 还挺好的。
与这个对应的是 一个小项目 是 将 bmp 图片转换成 rgb 的数值。 还有根据 rgb 的数值生成一个bmp 的图片。
可以从网上找一找 他其他的课程。
第13节, osd 源码分析。
接下来就是 这两个函数的区别。 这两个 函数就是在对 一个像素点 , 进行扩展。
我的疑问:
你这么扩展, 万一 像素点不够怎么办呢?
剩下的就没有什么了。