MI WM API
REVISION HISTORY¶
| Revision No. | Description |
Date |
|---|---|---|
| 1.00 | 11/15/2022 |
1. 概述¶
1.1 模块说明¶
WM(window manger)模块设计用来堆叠窗口,重叠区域显示最高优先级窗口内容,每个输入通道对应一个窗口。可以通过置顶某窗口,将该窗口的优先级设置为最大。最多支持128个窗口堆叠。
在置顶某窗口后,其他窗口之间优先级关系不变,如图1-1所示,
图1-1 WM置顶窗口应用场景
1.2 流程框图¶
WM根据窗口的优先级关系,计算出各窗口的显示区域,避免重复拷贝重叠区域。
本模块的输入源包括以下两类:
-
APP直接注入图像数据到本模块。
-
绑定的前级模块发送图像数据到本模块。
1.3 约束¶
-
目前只支持一种数据格式:
E_MI_SYS_PIXEL_FRAME_YUV_SEMIPLANAR_420
-
目前只支持固定帧率输出:参见MI_WM_OutputPortAttr_t的参数u32FrmRate。
-
WM 模块目前不支持:格式转换/裁剪/缩放 等功能。
-
参见更多的规格参数。
2. API参考¶
该模块提供以下API:
| API名 | 功能 |
|---|---|
| MI_WM_OpenDevice | 打开一个WM虚拟设备 |
| MI_WM_CloseDevice | 关闭一个WM虚拟设备 |
| MI_WM_StartDevice | 开始WM设备的工作 |
| MI_WM_StopDevice | 停止WN设备的工作 |
| MI_WM_CreateInputChannel | 创建输入通道 |
| MI_WM_DestroyInputChannel | 销毁输入通道 |
| MI_WM_SetInputChannelAttr | 设置输入通道的属性 |
| MI_WM_GetInputChannelAttr | 获取输入通道的属性 |
| MI_WM_SetOutputPortAttr | 设置输出通道的属性 |
| MI_WM_GetOutputPortAttr | 获取输出通道的属性 |
| MI_WM_EnableInputChannel | 使能一个输入通道 |
| MI_WM_DisableInputChannel | 关闭一个输入通道 |
| MI_WM_ResumeInputChannel | 恢复一个输入通道的画面 |
| MI_WM_PauseInputChannel | 静止一个输入通道的画面 |
| MI_WM_MoveToTop | 置顶一个输入通道的画面 |
2.1 MI_WM_OpenDevice¶
-
描述
初始化WM虚拟设备,向sys注册本虚拟设备,用以和其它模块绑定。
-
语法
MI_S32 MI_WM_OpenDevice(MI_WM_DEV devId)
-
参数
参数名称 描述 输入/输出 devId 本参数指定要打开的虚拟设备ID。
[0, WM_MAX_DEVICE_NUM),见规格参数。输入 -
返回值
-
0:成功。
-
非0:失败,参照错误码。
-
-
依赖
-
头文件:mi_wm.h, mi_wm_datatype.h
-
库文件:libmi_wm.a(so)
-
-
注意
对WM执行任何操作之前,先调用本函数初始化WM模块。
-
相关主题
2.2 MI_WM_CloseDevice¶
-
描述
关闭wm虚拟设备,向sys解注册本虚拟设备,不能绑定其它模块。
-
语法
MI_S32 MI_WM_CloseDevice(MI_WM_DEV devId)
-
参数
参数名称 描述 输入/输出 devId 本参数指定要关闭的虚拟设备ID。
[0, WM_MAX_DEVICE_NUM),见规格参数。输入 -
返回值
-
0:成功。
-
非0:失败,参照错误码。
-
-
依赖
-
头文件:mi_wm.h, mi_wm_datatype.h
-
库文件:libmi_wm.a(so)
-
-
注意
调用本函数前,先使用MI_WM_StopDevice停止对应的设备。
-
相关主题
2.3 MI_WM_StartDevice¶
-
描述
使能该虚拟设备,wm output port开始输出input channels 数据堆叠之后的数据帧。使能所有状态为enable的input channel,使能output port。
-
语法
MI_S32 MI_WM_StartDevice(MI_WM_DEV devId)
-
参数
参数名称 描述 输入/输出 devId 本参数指定要启动的虚拟设备ID。
[0, WM_MAX_DEVICE_NUM),见规格参数。输入 -
返回值
-
0:成功。
-
非0:失败,参照错误码。
-
-
依赖
-
头文件:mi_wm.h, mi_wm_datatype.h
-
库文件:libmi_wm.a(so)
-
-
注意
调用本函数前,先使用MI_WM_OpenDevice打开对应的设备。
-
相关主题
2.4 MI_WM_StopDevice¶
-
描述
停止该虚拟设备,wm output port停止输出数据帧。禁用input channel状态为enable的所有input channel以及output port,但是不修改其状态。
-
语法
MI_S32 MI_WM_StopDevice(MI_WM_DEV devId)
-
参数
参数名称 描述 输入/输出 devId 本参数指定要停止的虚拟设备ID。
[0, WM_MAX_DEVICE_NUM),见规格参数。输入 -
返回值
-
0:成功。
-
非0:失败,参照错误码。
-
-
依赖
-
头文件:mi_wm.h, mi_wm_datatype.h
-
库文件:libmi_wm.a(so)
-
-
注意
-
调用本函数前,先使用MI_WM_OpenDevice打开对应的设备。
-
本函数会disable所有enable的输入通道/输出端口。
-
-
相关主题
2.5 MI_WM_CreateInputChannel¶
-
描述
创建 input channel。
-
语法
MI_S32 MI_WM_CreateInputChannel(MI_WM_DEV devId, MI_WM_CHN chnId)
-
参数
参数名称 描述 输入/输出 devId 目标input channel所属wm虚拟设备的ID。
[0, WM_MAX_DEVICE_NUM),见规格参数。输入 chnId 目标input channel的channel ID。
[0, WM_MAX_INPUT_CHN_NUM),见规格参数。输入 -
返回值
-
0:成功。
-
非0:失败,参照错误码。
-
-
依赖
-
头文件:mi_wm.h, mi_wm_datatype.h
-
库文件:libmi_wm.a(so)
-
-
注意
-
调用本函数前,先使用MI_WM_OpenDevice打开对应的设备。
-
本函数创建的 input channel 状态为未初始化,需之后使用MI_WM_SetInputChannelAttr初始化。新增的 input channel 默认为最高优先级,但是需要使用MI_WM_EnableInputChannel enable 后才能生效。
-
-
相关主题
2.6 MI_WM_DestroyInputChannel¶
-
描述
删除一个 input channel。
-
语法
MI_S32 MI_WM_DestroyInputChannel(MI_WM_DEV devId, MI_WM_CHN chnId)
-
参数
参数名称 描述 输入/输出 devId 目标input channel所属wm虚拟设备的ID。
[0, WM_MAX_DEVICE_NUM),见规格参数。输入 chnId 目标input channel的channel ID。
[0, WM_MAX_INPUT_CHN_NUM),见规格参数。输入 -
返回值
-
0:成功。
-
非0:失败,参照错误码。
-
-
依赖
-
头文件:mi_wm.h, mi_wm_datatype.h
-
库文件:libmi_wm.a(so)
-
-
注意
调用本函数前,先使用MI_WM_OpenDevice打开对应的设备,MI_WM_CreateInputChannel创建输入通道。
-
相关主题
2.7 MI_WM_SetInputChannelAttr¶
-
描述
设置该wm虚拟设备input channel的参数。
-
语法
MI_S32 MI_WM_SetInputChannelAttr(MI_WM_DEV devId, MI_WM_CHN chnId, MI_WM_InputChnAttr_t *pstInputChnAttr)
-
参数
参数名称 描述 输入/输出 devId 目标input channel所属wm虚拟设备的ID。
[0, WM_MAX_DEVICE_NUM),见规格参数。输入 chnId 目标input channel的channel ID。
[0, WM_MAX_INPUT_CHN_NUM),见规格参数。输入 pstInputChnAttr 目标input channel的配置参数指针。
MI_WM_InputChnAttr_t输入 -
返回值
-
0:成功。
-
非0:失败,参照错误码。
-
-
依赖
-
头文件:mi_wm.h, mi_wm_datatype.h
-
库文件:libmi_wm.a(so)
-
-
注意
-
调用本函数前,先使用MI_WM_OpenDevice打开对应的设备,MI_WM_CreateInputChannel创建输入通道。
-
在调用本函数前,先使用MI_WM_SetOutputPortAttr设置output port的参数。
-
窗口大小应当和输入图像大小相等。
-
-
相关主题
2.8 MI_WM_GetInputChannelAttr¶
-
描述
获取该wm虚拟设备input channel的参数。
-
语法
MI_S32 MI_WM_GetInputChannelAttr(MI_WM_DEV devId, MI_WM_CHN chnId, MI_WM_InputChnAttr_t *pstInputChnAttr)
-
参数
参数名称 描述 输入/输出 devId 目标input channel所属wm虚拟设备的ID。
[0, WM_MAX_DEVICE_NUM),见规格参数。输入 chnId 目标input channel的channel ID。
[0, WM_MAX_INPUT_CHN_NUM),见规格参数。输入 pstInputChnAttr 目标input channel的配置参数指针。
MI_WM_InputChnAttr_t输出 -
返回值
-
0:成功。
-
非0:失败,参照错误码。
-
-
依赖
-
头文件:mi_wm.h, mi_wm_datatype.h
-
库文件:libmi_wm.a(so)
-
-
注意
调用本函数前,先使用MI_WM_OpenDevice打开对应的设备,MI_WM_CreateInputChannel创建输入通道。
-
相关主题
2.9 MI_WM_SetOutputPortAttr¶
-
描述
设置该wm虚拟设备output port的参数。
-
语法
MI_S32 MI_WM_SetOutputPortAttr(MI_WM_DEV devId, MI_WM_PORT portId, MI_WM_OutputPortAttr_t *pstOutputPortAttr)
-
参数
参数名称 描述 输入/输出 devId 目标output port所属wm虚拟设备的ID。
[0, WM_MAX_DEVICE_NUM),见规格参数。输入 portId 目标output port的port ID。
[0, WM_MAX_OUTPUTPORT_NUM),见规格参数。输入 pstOutputPortAttr 目标output port的配置参数指针。
MI_WM_OutputPortAttr_t输入 -
返回值
-
0:成功。
-
非0:失败,参照错误码。
-
-
依赖
-
头文件:mi_wm.h, mi_wm_datatype.h
-
库文件:libmi_wm.a(so)
-
-
注意
调用本函数前,先使用MI_WM_OpenDevice打开对应的设备。
-
相关主题
2.10 MI_WM_GetOutputPortAttr¶
-
描述
获取该wm虚拟设备output port的参数。
-
语法
MI_S32 MI_WM_GetOutputPortAttr(MI_WM_DEV devId, MI_WM_PORT portId, MI_WM_OutputPortAttr_t *pstOutputPortAttr)
-
参数
参数名称 描述 输入/输出 devId 目标output port所属wm虚拟设备的ID。
[0, WM_MAX_DEVICE_NUM),见规格参数。输入 portId 目标output port的port ID。
[0, WM_MAX_OUTPUTPORT_NUM),见规格参数。输入 pstOutputPortAttr 目标output port的配置参数指针。
MI_WM_OutputPortAttr_t输出 -
返回值
-
0:成功。
-
非0:失败,参照错误码。
-
-
依赖
-
头文件:mi_wm.h, mi_wm_datatype.h
-
库文件:libmi_wm.a(so)
-
-
注意
调用本函数前,先使用MI_WM_OpenDevice打开对应的设备。
-
相关主题
2.11 MI_WM_EnableInputChannel¶
-
描述
使能该input channel,wm模块开始接收deviceID=devId,channelID=chnId的输入通道的数据。标记该channel状态为enable。
-
语法
MI_S32 MI_WM_EnableInputChannel(MI_WM_DEV devId, MI_WM_CHN chnId)
-
参数
参数名称 描述 输入/输出 devId 目标input channel所属wm虚拟设备的ID。
[0, WM_MAX_DEVICE_NUM),见规格参数。输入 chnId 目标input channel的channel ID。
[0, WM_MAX_INPUT_CHN_NUM),见规格参数。输入 -
返回值
-
0:成功。
-
非0:失败,参照错误码。
-
-
依赖
-
头文件:mi_wm.h, mi_wm_datatype.h
-
库文件:libmi_wm.a(so)
-
-
注意
调用本函数前,先使用MI_WM_OpenDevice打开对应的设备。
-
相关主题
2.12 MI_WM_DisableInputChannel¶
-
描述
无效input channel,wm模块停止接收deviceID=devId, channelID=chnId的输入通道的数据。标记该channel状态为disable。
-
语法
MI_S32 MI_WM_DisableInputChannel(MI_WM_DEV devId, MI_WM_CHN chnId)
-
参数
参数名称 描述 输入/输出 devId 目标input channel所属wm虚拟设备的ID。
[0, WM_MAX_DEVICE_NUM),见规格参数。输入 chnId 目标input channel的channel ID。
[0, WM_MAX_INPUT_CHN_NUM),见规格参数。输入 -
返回值
-
0:成功。
-
非0:失败,参照错误码。
-
-
依赖
-
头文件:mi_wm.h, mi_wm_datatype.h
-
库文件:libmi_wm.a(so)
-
-
注意
调用本函数前,先使用MI_WM_OpenDevice打开对应的设备。
-
相关主题
2.13 MI_WM_ResumeInputChannel¶
-
描述
恢复某一个WM设备上 input channel 的画面。
-
语法
MI_S32 MI_WM_ResumeInputChannel(MI_WM_DEV devId, MI_WM_CHN chnId)
-
参数
参数名称 描述 输入/输出 devId 目标input channel所属wm虚拟设备的ID。
[0, WM_MAX_DEVICE_NUM),见规格参数。输入 chnId 目标input channel的channel ID。
[0, WM_MAX_INPUT_CHN_NUM),见规格参数。输入 -
返回值
-
0:成功。
-
非0:失败,参照错误码。
-
-
依赖
-
头文件:mi_wm.h, mi_wm_datatype.h
-
库文件:libmi_wm.a(so)
-
-
注意
-
调用本函数前,先使用MI_WM_OpenDevice打开对应的设备。
-
此接口只对已经enable的通道产生作用。
-
-
相关主题
2.14 MI_WM_PauseInputChannel¶
-
描述
静帧某一个wm设备 input channel 的画面。
-
语法
MI_S32 MI_WM_ResumeInputChannel(MI_WM_DEV devId, MI_WM_CHN chnId)
-
参数
参数名称 描述 输入/输出 devId 目标input channel所属wm虚拟设备的ID。
[0, WM_MAX_DEVICE_NUM),见规格参数。输入 chnId 目标input channel的channel ID。
[0, WM_MAX_INPUT_CHN_NUM),见规格参数。输入 -
返回值
-
0:成功。
-
非0:失败,参照错误码。
-
-
依赖
-
头文件:mi_wm.h, mi_wm_datatype.h
-
库文件:libmi_wm.a(so)
-
-
注意
-
调用本函数前,先使用MI_WM_OpenDevice打开对应的设备。
-
此接口只对已经enable的通道产生作用。
-
-
相关主题
2.15 MI_WM_MoveToTop¶
-
描述
置顶某一个输入通道的画面。
-
语法
MI_S32 MI_WM_MoveToTop(MI_WM_DEV devId, MI_WM_CHN chnId)
-
参数
参数名称 描述 输入/输出 devId 目标input channel所属wm虚拟设备的ID。
[0, WM_MAX_DEVICE_NUM),见规格参数。输入 chnId 目标input channel的channel ID。
[0, WM_MAX_INPUT_CHN_NUM),见规格参数。输入 -
返回值
-
0:成功。
-
非0:失败,参照错误码。
-
-
依赖
-
头文件:mi_wm.h, mi_wm_datatype.h
-
库文件:libmi_wm.a(so)
-
-
注意
-
调用本函数前,先使用MI_WM_OpenDevice打开对应的设备。
-
此接口只对已经enable的通道产生作用。
-
-
相关主题
无
3. 数据类型¶
MI WM相关数据类型、数据结构定义如下:
| 数据类型 | 定义 |
|---|---|
| MI_WM_DEV | 定义device id类型 |
| MI_WM_PORT | 定义port id类型 |
| MI_WM_CHN | 定义channel id 类型 |
| MI_WM_OutputPortAttr_t | 定义输出端口属性 |
| MI_WM_InputChnAttr_t | 定义输入通道属性 |
3.1 MI_WM_DEV¶
-
说明
定义device id类型。
-
定义
typedef MI_U32 MI_WM_DEV;
-
注意事项
小于0为无效值。
3.2 MI_WM_PORT¶
-
说明
定义port id类型。
-
定义
typedef MI_U32 MI_WM_PORT;
-
注意事项
小于0为无效值。
3.3 MI_WM_CHN¶
-
说明
定义channel id类型。
-
定义
typedef MI_U32 MI_WM_CHN;
-
注意事项
小于0为无效值。
3.4 MI_WM_OutputPortAttr_t¶
-
说明
定义输出端口属性。
-
定义
typedef struct MI_WM_OutputPortAttr_s { MI_U32 u32BgColor; MI_SYS_PixelFormat_e ePixelFormat; MI_U32 u32Frmate; MI_U32 u32Width; MI_U32 u32Height; }MI_WM_OutputPortAttr_t; -
成员
成员名称 描述 u32BgColor 输出图像的背景颜色,RGB
[23:16]: R
[15:8]: G
[7:0]: BePixelFormat 输出frame的像素格式,目前只支持E_MI_SYS_PIXEL_FRAME_YUV_SEMIPLANAR_420 u32FrmRate 固定的输出帧率 u32Width wm输出frame的宽。需要2对齐。 u32Height wm输出frame的高。需要2对齐。
3.5 MI_WM_InputChnAttr_t¶
-
说明
wm的input channel属性。
-
定义
typedef struct MI_WM_InputChnAttr_s { MI_U32 u32OutX; MI_U32 u32OutY; MI_U32 u32OutWidth; MI_U32 u32OutHeight; }MI_WM_InputChnAttr_t; -
成员
成员名称 描述 u32OutX wm输入通道在输出的frame的预览窗口的起始横坐标,需要2对齐。 u32OutY wm输入通道在输出的frame的预览窗口的起始纵坐标,需要2对齐。 u32OutWidth wm输入通道在输出的frame的预览窗口的宽,需要2对齐。 u32OutHeight wm输入通道在输出的frame的预览窗口的高,需要2对齐。
4. 错误码¶
错误码如表4-1所示:
表4-1 API错误码
| 错误代码 | 宏定义 | 描述 |
|---|---|---|
| 0XA029201F | MI_WM_ERR_FAIL | wm 函数执行失败,参见系统log |
| 0XA029200C | MI_WM_ERR_NOMEM | 内存不足,申请内存失败 |
| 0XA0292003 | MI_WM_ERR_ILLEGAL_PARAM | 函数的某个参数非法,参见系统log |
| 0XA0292008 | MI_WM_ERR_NOT_SUPPORT | 函数不支持当前参数设定 |
| 0XA0292016 | MI_WM_ERR_MOD_INITED | wm已经初始化过 |
| 0XA0292015 | MI_WM_ERR_MOD_NOT_INIT | wm还没有初始化 |
| 0XA0292342 | MI_WM_ERR_CHN_NOT_EXIST | 通道不存在 |
| 0XA0292343 | MI_WM_ERR_CHN_EXIST | 通道已存在 |
| 0XA0292340 | MI_WM_ERR_DEV_OPENED | wm dev已经open过 |
| 0XA0292341 | MI_WM_ERR_DEV_NOT_OPEN | 在调用该函数前,需要先open wm设备 |
| 0XA029201B | MI_WM_ERR_DEV_NOT_STOP | 在调用该函数前,需要先stop wm设备 |
| 0XA0292006 | MI_WM_ERR_NULL_PTR | 输入参数空指针错误 |
| 0XA0292007 | MI_WM_ERR_NOT_CONFIG | wm 的input/output 没有配置 |
5. 规格¶
规格参数如表5-1所示:
表5-1 wm模块规格参数
| 宏定义 | 参数 | 描述 |
|---|---|---|
| WM_MAX_DEVICE_NUM | 4 | WM模块支持的虚拟设备个数 |
| WM_MAX_INPUTPORT_NUM | 1 | 单个虚拟设备通道的的最大入口数 |
| WM_MAX_OUTPUTPORT_NUM | 1 | 单个虚拟设备通道的最大出口数 |
| WM_MAX_INPUT_CHN_NUM | 128 | 单个虚拟设备的最大输入通道数 |
6.示例代码¶
本节为示例代码。
6.1 示例程序流程图¶
图6-1 WM示例流程图
6.2. WM相关代码¶
6.2.1. 构建wm模块¶
/*
* 打开wm设备
* v
* 设置wm output port 参数
* v
* 创建 input channel
* v
* 设置 input channel 参数
* v
* 使能 input channel
* v
* 开始wm设备
*/
void construct_wm_module(void)
{
/*
*打开wm设备
*/
MI_WM_DEV devId = 0;
MI_WM_CHN Chn_0_Id = 0;
MI_WM_CHN Chn_1_Id = 1;
MI_WM_CHN Chn_2_Id = 2;
MI_WM_PORT portId = 0;
MI_WM_OutputPortAttr_t stOutputPortAttr;
MI_WM_InputChnAttr_t stInputChnAttr;
MI_WM_OpenDevice(devId);
/*
*设置wm output port 参数
*/
stOutputPortAttr.u32BgColor = 255;
stOutputPortAttr.u32Frmate = 30;
stOutputPortAttr.u32Width = 1920;
stOutputPortAttr.u32Height = 1080;
stOutputPortAttr.ePixelFormat = E_MI_SYS_PIXEL_FRAME_YUV_SEMIPLANAR_420;
MI_WM_SetOutputPortAttr(devId, portId, &stOutputPortAttr);
/*
*创建输入通道
*/
MI_WM_CreateInputChannel(devId, Chn_0_Id);
MI_WM_CreateInputChannel(devId, Chn_1_Id);
MI_WM_CreateInputChannel(devId, Chn_2_Id);
/*
*设置 input channel 参数
*/
stInputChnAttr.u32OutX = 0;
stInputChnAttr.u32OutY = 0;
stInputChnAttr.u32OutWidth = 720;
stInputChnAttr.u32OutHeight = 576;
MI_WM_SetInputChannelAttr(devId, Chn_0_Id, &stInputChnAttr);
stInputChnAttr.u32OutX = 100;
stInputChnAttr.u32OutY = 100;
MI_WM_SetInputChannelAttr(devId, Chn_1_Id, &stInputChnAttr);
stInputChnAttr.u32OutX = 200;
stInputChnAttr.u32OutY = 200;
MI_WM_SetInputChannelAttr(devId, Chn_2_Id, &stInputChnAttr);
/*
*激活input channel
*/
MI_WM_EnableInputChannel(devId, Chn_0_Id);
MI_WM_EnableInputChannel(devId, Chn_1_Id);
MI_WM_EnableInputChannel(devId, Chn_2_Id);
/*
*开始wm设备
*/
MI_WM_StartDevice(devId);
}
6.2.2. 绑定wm上下游模块¶
/*
* 绑定 vdec out0 -> wm in0--------->--> venc in0
* 绑定 vdec out1 -> wm in1 ---/
* 绑定 vdec out2 -> wm in2---------/
*/
void bind_vdec_wm_venc(void)
{
MI_SYS_ChnPort_t stSrcChnPort;
MI_SYS_ChnPort_t stDstChnPort;
MI_SYS_BindAttr_t stBindAttr;
/*
* 绑定wm out0-> venc in0
* <chn,dev,port> : (0,0,0) -> (0,0,0)
*/
stSrcChnPort.eModId = E_MI_MODULE_ID_WM;
stSrcChnPort.u32ChnId = 0;
stSrcChnPort.u32DevId = 0;
stSrcChnPort.u32PortId = 0;
stDstChnPort.eModId = E_MI_MODULE_ID_VENC;
stDstChnPort.u32ChnId = 0;
stDstChnPort.u32DevId = MI_VENC_DEV_ID_JPEG_0;
stDstChnPort.u32PortId = 0;
stBindAttr.eBindType = E_MI_SYS_BIND_TYPE_FRAME_BASE;
MI_SYS_BindChnPort(0, &stSrcChnPort, &stDstChnPort, &stBindAttr);
/*
* 绑定vdec out0-> wm 0
* <chn,dev,port> : (0,0,0) -> (0,0,0)
*/
stSrcChnPort.eModId = E_MI_MODULE_ID_VDEC;
stSrcChnPort.u32ChnId = 0;
stSrcChnPort.u32DevId = 0;
stSrcChnPort.u32PortId = 0;
stDstChnPort.eModId = E_MI_MODULE_ID_WM;
stDstChnPort.u32ChnId = 0;
stDstChnPort.u32DevId = 0;
stDstChnPort.u32PortId = 0;
MI_SYS_BindChnPort(0, &stSrcChnPort, &stDstChnPort, &stBindAttr);
/*
* 绑定vdec out0-> wm in1
* <chn,dev,port> : (1,0,0) -> (1,0,0)
*/
stSrcChnPort.eModId = E_MI_MODULE_ID_VDEC;
stSrcChnPort.u32ChnId = 1;
stSrcChnPort.u32DevId = 0;
stSrcChnPort.u32PortId = 0;
stDstChnPort.eModId = E_MI_MODULE_ID_WM;
stDstChnPort.u32ChnId = 1;
stDstChnPort.u32DevId = 0;
stDstChnPort.u32PortId = 0;
MI_SYS_BindChnPort(0, &stSrcChnPort, &stDstChnPort, &stBindAttr);
/*
* 绑定vdec out2-> wm in2
* <chn,dev,port> : (2,0,0) -> (2,0,0)
*/
stSrcChnPort.eModId = E_MI_MODULE_ID_VDEC;
stSrcChnPort.u32ChnId = 2;
stSrcChnPort.u32DevId = 0;
stSrcChnPort.u32PortId = 0;
stDstChnPort.eModId = E_MI_MODULE_ID_WM;
stDstChnPort.u32ChnId = 2;
stDstChnPort.u32DevId = 0;
stDstChnPort.u32PortId = 0;
MI_SYS_BindChnPort(0, &stSrcChnPort, &stDstChnPort, &stBindAttr);
}
6.2.3. 解绑wm上下游模块¶
与绑定过程区别很小,参见完整代码实现。
6.2.4. 析构wm模块¶
/*
* 禁用所有channel
* v
* 停止wm设备
* v
* 关闭wm设备
*/
void destruct_wm_module(void)
{
MI_WM_DEV devId = 0;
MI_WM_CHN Chn_0_Id = 0;
MI_WM_CHN Chn_1_Id = 1;
MI_WM_CHN Chn_2_Id = 2;
MI_WM_PORT portId = 0;
/*
* 先禁用已经打开wm channel
* <0,1,2>
*/
MI_WM_DisableInputChannel(devId, Chn_0_Id);
MI_WM_DisableInputChannel(devId, Chn_1_Id);
MI_WM_DisableInputChannel(devId, Chn_2_Id);
MI_WM_DestroyInputChannel(devId, Chn_0_Id);
MI_WM_DestroyInputChannel(devId, Chn_1_Id);
MI_WM_DestroyInputChannel(devId, Chn_2_Id);
/*
*停止已经打开的wm设备
*/
MI_WM_StopDevice(devId);
/*
*关闭已经打开的wm设备
*/
MI_WM_CloseDevice(devId);
}
6.3. 完整代码¶
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <signal.h>
#include <poll.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <mi_sys_datatype.h>
#include <mi_sys.h>
#include <mi_vdec_datatype.h>
#include <mi_vdec.h>
#include <mi_venc_datatype.h>
#include <mi_venc.h>
#include <mi_wm_datatype.h>
#include <mi_wm.h>
#define VDEC_FILE0 "./src/h264_720_576_refnum_1-new_len.es"
#define VDEC_FILE1 "./src/h264_1280_720_refnum_1_len.es"
#define VDEC_FILE2 "./src/h264_1920_1080_refnum_1_len.es"
#define MI_U32VALUE(pu8Data, index) \
(pu8Data[index] << 24) | (pu8Data[index + 1] << 16) | (pu8Data[index + 2] << 8) | (pu8Data[index + 3])
#define VESFILE_READER_BATCH (128 * 1024)
typedef struct vdecStream
{
FILE *fp;
MI_VDEC_CHN VdecChn;
int frameRate;
} vdecStream;
static volatile bool keepRunning = TRUE;
pthread_t thr0, thr1, thr2, g_vencGet;
vdecStream vS0, vS1, vS2;
static void intHandler(int signo)
{
if (signo == SIGINT)
{
printf("catch Ctrl + C, exit\n");
keepRunning = FALSE;
}
}
MI_U64 get_pts(MI_U32 u32FrameRate)
{
if (0 == u32FrameRate)
{
return (MI_U64)(-1);
}
return (MI_U64)(1000 / u32FrameRate);
}
void *push_stream(void *args)
{
MI_S32 s32Ret = MI_SUCCESS;
MI_VDEC_CHN VdecChn;
MI_U32 u32FrmRate = 0;
MI_U8 *pu8Buf = NULL;
MI_U32 u32Len = 0;
MI_U32 u32FrameLen = 0;
MI_U64 u64Pts = 0;
MI_U8 au8Header[16] = {0};
MI_U32 u32Pos = 0;
vdecStream *vdecS = (vdecStream *)args;
MI_VDEC_VideoStream_t stVdecStream;
MI_S32 s32TimeOutMs = 20;
MI_U32 u32FpBackLen = 0; // if send stream failed, file pointer back length
VdecChn = vdecS->VdecChn;
u32FrmRate = vdecS->frameRate;
pu8Buf = (MI_U8 *)malloc(VESFILE_READER_BATCH);
while (keepRunning)
{
/// frame mode, read one frame lenght every time
memset(au8Header, 0, 16);
u32Pos = fseek(vdecS->fp, 0L, SEEK_CUR);
u32Len = fread(au8Header, 16, 1, vdecS->fp);
if (u32Len <= 0)
{
fseek(vdecS->fp, 0, SEEK_SET);
continue;
}
u32FrameLen = MI_U32VALUE(au8Header, 4);
if (u32FrameLen > VESFILE_READER_BATCH)
{
fseek(vdecS->fp, 0, SEEK_SET);
continue;
}
u32Len = fread(pu8Buf, u32FrameLen, 1, vdecS->fp);
if (u32Len <= 0)
{
fseek(vdecS->fp, 0, SEEK_SET);
continue;
}
stVdecStream.pu8Addr = pu8Buf;
stVdecStream.u32Len = u32FrameLen;
stVdecStream.u64PTS = u64Pts;
stVdecStream.bEndOfFrame = 1;
stVdecStream.bEndOfStream = 0;
u32FpBackLen = stVdecStream.u32Len + 16; // back length
if (MI_SUCCESS != (s32Ret = MI_VDEC_SendStream(0, VdecChn, &stVdecStream, s32TimeOutMs)))
{
fseek(vdecS->fp, -u32FpBackLen, SEEK_CUR);
}
u64Pts = u64Pts + get_pts(1000 / u32FrmRate);
usleep(20 * 1000);
}
free(pu8Buf);
return NULL;
}
void construct_vdec_module()
{
MI_VDEC_ChnAttr_t stChnAttr;
MI_VDEC_CHN Chn_0_Id = 0;
MI_VDEC_CHN Chn_1_Id = 1;
MI_VDEC_CHN Chn_2_Id = 2;
MI_VDEC_InitParam_t stInitParams;
MI_VDEC_OutputPortAttr_t stOutputPortAttr;
memset(&stChnAttr, 0, sizeof(MI_VDEC_ChnAttr_t));
stInitParams.u16MaxWidth = 4096;
stInitParams.u16MaxHeight = 4096;
MI_VDEC_CreateDev(0, &stInitParams);
stChnAttr.eCodecType = E_MI_VDEC_CODEC_TYPE_H264;
stChnAttr.u32PicWidth = 1920;
stChnAttr.u32PicHeight = 1080;
stChnAttr.eVideoMode = E_MI_VDEC_VIDEO_MODE_FRAME;
stChnAttr.u32BufSize = 1024 * 1024;
stChnAttr.eDpbBufMode = E_MI_VDEC_DPB_MODE_NORMAL;
stChnAttr.stVdecVideoAttr.u32RefFrameNum = 1;
MI_VDEC_CreateChn(0, Chn_0_Id, &stChnAttr);
stOutputPortAttr.u16Width = 720;
stOutputPortAttr.u16Height = 576;
MI_VDEC_SetOutputPortAttr(0, Chn_0_Id, &stOutputPortAttr);
MI_VDEC_CreateChn(0, Chn_1_Id, &stChnAttr);
stOutputPortAttr.u16Width = 720;
stOutputPortAttr.u16Height = 576;
MI_VDEC_SetOutputPortAttr(0, Chn_1_Id, &stOutputPortAttr);
MI_VDEC_CreateChn(0, Chn_2_Id, &stChnAttr);
stOutputPortAttr.u16Width = 720;
stOutputPortAttr.u16Height = 576;
MI_VDEC_SetOutputPortAttr(0, Chn_2_Id, &stOutputPortAttr);
MI_VDEC_StartChn(0, Chn_0_Id);
MI_VDEC_StartChn(0, Chn_1_Id);
MI_VDEC_StartChn(0, Chn_2_Id);
vS0.fp = fopen(VDEC_FILE0, "rb");
vS0.frameRate = 30;
vS0.VdecChn = Chn_0_Id;
assert(vS0.fp);
pthread_create(&thr0, NULL, push_stream, &vS0);
vS1.fp = fopen(VDEC_FILE1, "rb");
vS1.frameRate = 30;
vS1.VdecChn = Chn_1_Id;
assert(vS1.fp);
pthread_create(&thr1, NULL, push_stream, &vS1);
vS2.fp = fopen(VDEC_FILE2, "rb");
vS2.frameRate = 30;
vS2.VdecChn = Chn_2_Id;
assert(vS2.fp);
pthread_create(&thr2, NULL, push_stream, &vS2);
}
void destruct_vdec_module(void)
{
printf(" destruct_vdec_module \n");
pthread_join(thr0, NULL);
pthread_join(thr1, NULL);
pthread_join(thr2, NULL);
MI_VDEC_StopChn(0, vS0.VdecChn);
MI_VDEC_StopChn(0, vS1.VdecChn);
MI_VDEC_StopChn(0, vS2.VdecChn);
MI_VDEC_DestroyChn(0, vS0.VdecChn);
MI_VDEC_DestroyChn(0, vS1.VdecChn);
MI_VDEC_DestroyChn(0, vS2.VdecChn);
MI_VDEC_DestroyDev(0);
}
/*
* 打开wm设备
* v
* 设置wm output port 参数
* v
* 创建 input channel
* v
* 设置 input channel 参数
* v
* 使能 input channel
* v
* 开始wm设备
*/
void construct_wm_module(void)
{
/*
*打开wm设备
*/
MI_WM_DEV devId = 0;
MI_WM_CHN Chn_0_Id = 0;
MI_WM_CHN Chn_1_Id = 1;
MI_WM_CHN Chn_2_Id = 2;
MI_WM_PORT portId = 0;
MI_WM_OutputPortAttr_t stOutputPortAttr;
MI_WM_InputChnAttr_t stInputChnAttr;
MI_WM_OpenDevice(devId);
/*
*设置wm output port 参数
*/
stOutputPortAttr.u32BgColor = 255;
stOutputPortAttr.u32Frmate = 30;
stOutputPortAttr.u32Width = 1920;
stOutputPortAttr.u32Height = 1080;
stOutputPortAttr.ePixelFormat = E_MI_SYS_PIXEL_FRAME_YUV_SEMIPLANAR_420;
MI_WM_SetOutputPortAttr(devId, portId, &stOutputPortAttr);
/*
*创建输入通道
*/
MI_WM_CreateInputChannel(devId, Chn_0_Id);
MI_WM_CreateInputChannel(devId, Chn_1_Id);
MI_WM_CreateInputChannel(devId, Chn_2_Id);
/*
*设置 input channel 参数
*/
stInputChnAttr.u32OutX = 0;
stInputChnAttr.u32OutY = 0;
stInputChnAttr.u32OutWidth = 720;
stInputChnAttr.u32OutHeight = 576;
MI_WM_SetInputChannelAttr(devId, Chn_0_Id, &stInputChnAttr);
stInputChnAttr.u32OutX = 100;
stInputChnAttr.u32OutY = 100;
MI_WM_SetInputChannelAttr(devId, Chn_1_Id, &stInputChnAttr);
stInputChnAttr.u32OutX = 200;
stInputChnAttr.u32OutY = 200;
MI_WM_SetInputChannelAttr(devId, Chn_2_Id, &stInputChnAttr);
/*
*激活input channel
*/
MI_WM_EnableInputChannel(devId, Chn_0_Id);
MI_WM_EnableInputChannel(devId, Chn_1_Id);
MI_WM_EnableInputChannel(devId, Chn_2_Id);
/*
*开始wm设备
*/
MI_WM_StartDevice(devId);
}
/*
* 禁用所有channel
* v
* 停止wm设备
* v
* 关闭wm设备
*/
void destruct_wm_module(void)
{
MI_WM_DEV devId = 0;
MI_WM_CHN Chn_0_Id = 0;
MI_WM_CHN Chn_1_Id = 1;
MI_WM_CHN Chn_2_Id = 2;
MI_WM_PORT portId = 0;
/*
* 先禁用已经打开wm channel
* <0,1,2>
*/
MI_WM_DisableInputChannel(devId, Chn_0_Id);
MI_WM_DisableInputChannel(devId, Chn_1_Id);
MI_WM_DisableInputChannel(devId, Chn_2_Id);
MI_WM_DestroyInputChannel(devId, Chn_0_Id);
MI_WM_DestroyInputChannel(devId, Chn_1_Id);
MI_WM_DestroyInputChannel(devId, Chn_2_Id);
/*
*停止已经打开的wm设备
*/
MI_WM_StopDevice(devId);
/*
*关闭已经打开的wm设备
*/
MI_WM_CloseDevice(devId);
}
void construct_venc_module(void)
{
MI_VENC_InitParam_t initParam;
MI_VENC_ChnAttr_t vencChnattr;
MI_VENC_InputSourceConfig_t vencInputSourceConfig;
memset(&vencChnattr, 0x0, sizeof(MI_VENC_ChnAttr_t));
memset(&vencInputSourceConfig, 0x0, sizeof(MI_VENC_InputSourceConfig_t));
memset(&initParam, 0x0, sizeof(MI_VENC_InitParam_t));
initParam.u32MaxWidth = 4096;
initParam.u32MaxHeight = 4096;
//创建设备
MI_VENC_CreateDev(MI_VENC_DEV_ID_JPEG_0, &initParam);
//创建编码通道 编码器属性 码率控制器属性
vencChnattr.stVeAttr.stAttrJpeg.u32PicWidth = 1920;
vencChnattr.stVeAttr.stAttrJpeg.u32PicHeight = 1080;
vencChnattr.stVeAttr.stAttrJpeg.u32MaxPicWidth = 1920;
vencChnattr.stVeAttr.stAttrJpeg.u32MaxPicHeight = 1080;
vencChnattr.stVeAttr.stAttrJpeg.u32BufSize = 1920 * 1080 * 1.5;
vencChnattr.stVeAttr.stAttrJpeg.bByFrame = TRUE;
vencChnattr.stVeAttr.eType = E_MI_VENC_MODTYPE_JPEGE;
vencChnattr.stRcAttr.eRcMode = E_MI_VENC_RC_MODE_MJPEGCBR;
vencChnattr.stRcAttr.stAttrMjpegCbr.u32BitRate = 1024 * 1024 * 4;
vencChnattr.stRcAttr.stAttrMjpegCbr.u32SrcFrmRateNum = 30;
vencChnattr.stRcAttr.stAttrMjpegCbr.u32SrcFrmRateDen = 1;
MI_VENC_CreateChn(MI_VENC_DEV_ID_JPEG_0, 0, &vencChnattr);
//设置H.264的输入配置信息
vencInputSourceConfig.eInputSrcBufferMode = E_MI_VENC_INPUT_MODE_NORMAL_FRMBASE;
MI_VENC_SetInputSourceConfig(MI_VENC_DEV_ID_JPEG_0, 0, &vencInputSourceConfig);
//设置码流最大缓存帧数
MI_VENC_SetMaxStreamCnt(MI_VENC_DEV_ID_JPEG_0, 0, 4);
MI_VENC_StartRecvPic(MI_VENC_DEV_ID_JPEG_0, 0);
}
void destruct_venc_module(void)
{
//停止编码通道接收输入图像
MI_VENC_StopRecvPic(MI_VENC_DEV_ID_JPEG_0, 0);
//销毁编码通道
MI_VENC_DestroyChn(MI_VENC_DEV_ID_JPEG_0, 0);
//销毁venc设备
MI_VENC_DestroyDev(MI_VENC_DEV_ID_JPEG_0);
}
/*
* 绑定 vdec out0 -> wm in0--------->--> venc in0
* 绑定 vdec out1 -> wm in1 ---/
* 绑定 vdec out2 -> wm in2---------/
*/
void bind_vdec_wm_venc(void)
{
MI_SYS_ChnPort_t stSrcChnPort;
MI_SYS_ChnPort_t stDstChnPort;
MI_SYS_BindAttr_t stBindAttr;
/*
* 绑定wm out0-> venc in0
* <chn,dev,port> : (0,0,0) -> (0,0,0)
*/
stSrcChnPort.eModId = E_MI_MODULE_ID_WM;
stSrcChnPort.u32ChnId = 0;
stSrcChnPort.u32DevId = 0;
stSrcChnPort.u32PortId = 0;
stDstChnPort.eModId = E_MI_MODULE_ID_VENC;
stDstChnPort.u32ChnId = 0;
stDstChnPort.u32DevId = MI_VENC_DEV_ID_JPEG_0;
stDstChnPort.u32PortId = 0;
stBindAttr.eBindType = E_MI_SYS_BIND_TYPE_FRAME_BASE;
MI_SYS_BindChnPort(0, &stSrcChnPort, &stDstChnPort, &stBindAttr);
/*
* 绑定vdec out0-> wm 0
* <chn,dev,port> : (0,0,0) -> (0,0,0)
*/
stSrcChnPort.eModId = E_MI_MODULE_ID_VDEC;
stSrcChnPort.u32ChnId = 0;
stSrcChnPort.u32DevId = 0;
stSrcChnPort.u32PortId = 0;
stDstChnPort.eModId = E_MI_MODULE_ID_WM;
stDstChnPort.u32ChnId = 0;
stDstChnPort.u32DevId = 0;
stDstChnPort.u32PortId = 0;
MI_SYS_BindChnPort(0, &stSrcChnPort, &stDstChnPort, &stBindAttr);
/*
* 绑定vdec out0-> wm in1
* <chn,dev,port> : (1,0,0) -> (1,0,0)
*/
stSrcChnPort.eModId = E_MI_MODULE_ID_VDEC;
stSrcChnPort.u32ChnId = 1;
stSrcChnPort.u32DevId = 0;
stSrcChnPort.u32PortId = 0;
stDstChnPort.eModId = E_MI_MODULE_ID_WM;
stDstChnPort.u32ChnId = 1;
stDstChnPort.u32DevId = 0;
stDstChnPort.u32PortId = 0;
MI_SYS_BindChnPort(0, &stSrcChnPort, &stDstChnPort, &stBindAttr);
/*
* 绑定vdec out2-> wm in2
* <chn,dev,port> : (2,0,0) -> (2,0,0)
*/
stSrcChnPort.eModId = E_MI_MODULE_ID_VDEC;
stSrcChnPort.u32ChnId = 2;
stSrcChnPort.u32DevId = 0;
stSrcChnPort.u32PortId = 0;
stDstChnPort.eModId = E_MI_MODULE_ID_WM;
stDstChnPort.u32ChnId = 2;
stDstChnPort.u32DevId = 0;
stDstChnPort.u32PortId = 0;
MI_SYS_BindChnPort(0, &stSrcChnPort, &stDstChnPort, &stBindAttr);
}
void unbind_vdec_wm_venc(void)
{
MI_SYS_ChnPort_t stSrcChnPort;
MI_SYS_ChnPort_t stDstChnPort;
stSrcChnPort.eModId = E_MI_MODULE_ID_WM;
stSrcChnPort.u32ChnId = 0;
stSrcChnPort.u32DevId = 0;
stSrcChnPort.u32PortId = 0;
stDstChnPort.eModId = E_MI_MODULE_ID_VENC;
stDstChnPort.u32ChnId = 0;
stDstChnPort.u32DevId = MI_VENC_DEV_ID_JPEG_0;
stDstChnPort.u32PortId = 0;
MI_SYS_UnBindChnPort(0, &stSrcChnPort, &stDstChnPort);
stSrcChnPort.eModId = E_MI_MODULE_ID_VDEC;
stSrcChnPort.u32ChnId = 0;
stSrcChnPort.u32DevId = 0;
stSrcChnPort.u32PortId = 0;
stDstChnPort.eModId = E_MI_MODULE_ID_WM;
stDstChnPort.u32ChnId = 0;
stDstChnPort.u32DevId = 0;
stDstChnPort.u32PortId = 0;
MI_SYS_UnBindChnPort(0, &stSrcChnPort, &stDstChnPort);
stSrcChnPort.eModId = E_MI_MODULE_ID_VDEC;
stSrcChnPort.u32ChnId = 1;
stSrcChnPort.u32DevId = 0;
stSrcChnPort.u32PortId = 0;
stDstChnPort.eModId = E_MI_MODULE_ID_WM;
stDstChnPort.u32ChnId = 1;
stDstChnPort.u32DevId = 0;
stDstChnPort.u32PortId = 0;
MI_SYS_UnBindChnPort(0, &stSrcChnPort, &stDstChnPort);
stSrcChnPort.eModId = E_MI_MODULE_ID_VDEC;
stSrcChnPort.u32ChnId = 2;
stSrcChnPort.u32DevId = 0;
stSrcChnPort.u32PortId = 0;
stDstChnPort.eModId = E_MI_MODULE_ID_WM;
stDstChnPort.u32ChnId = 2;
stDstChnPort.u32DevId = 0;
stDstChnPort.u32PortId = 0;
MI_SYS_UnBindChnPort(0, &stSrcChnPort, &stDstChnPort);
}
void *venc_output_thread(void *data)
{
MI_S32 vencFd = -1;
MI_S32 s32Ret = MI_SUCCESS;
int fd = -1;
MI_U32 u32DumpNum = 0;
fd_set read_fds;
struct timeval TimeoutVal;
MI_VENC_ChnStat_t stStat;
MI_VENC_Stream_t stStream;
MI_VDEC_VideoStream_t stVdecStream;
MI_VENC_Pack_t *pstPack = NULL;
TimeoutVal.tv_sec = 2;
TimeoutVal.tv_usec = 0;
fd = open("venc_out.jpeg", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
vencFd = MI_VENC_GetFd(MI_VENC_DEV_ID_JPEG_0, 0);
if (vencFd <= 0)
{
printf("get fd err\n");
return NULL;
}
while (keepRunning)
{
FD_ZERO(&read_fds);
FD_SET(vencFd, &read_fds);
s32Ret = select(vencFd + 1, &read_fds, NULL, NULL, &TimeoutVal);
if (s32Ret < 0)
{
printf("select failed\n");
usleep(10 * 1000);
continue;
}
else if (0 == s32Ret)
{
usleep(10 * 1000);
continue;
}
else
{
if (FD_ISSET(vencFd, &read_fds))
{
memset(&stStat, 0, sizeof(MI_VENC_ChnStat_t));
s32Ret = MI_VENC_Query(MI_VENC_DEV_ID_JPEG_0, 0, &stStat);
if (MI_SUCCESS != s32Ret)
{
usleep(10 * 1000);
continue;
}
memset(&stStream, 0, sizeof(MI_VENC_Stream_t));
memset(&stVdecStream, 0, sizeof(MI_VDEC_VideoStream_t));
pstPack = (MI_VENC_Pack_t *)malloc(sizeof(MI_VENC_Pack_t) * stStat.u32CurPacks);
stStream.u32PackCount = stStat.u32CurPacks;
stStream.pstPack = pstPack;
s32Ret = MI_VENC_GetStream(MI_VENC_DEV_ID_JPEG_0, 0, &stStream, -1);
if (MI_SUCCESS == s32Ret)
{
if (u32DumpNum < 30)
{
lseek(fd, 0, SEEK_SET);
write(fd, stStream.pstPack[0].pu8Addr, stStream.pstPack[0].u32Len);
u32DumpNum++;
}
MI_VENC_ReleaseStream(MI_VENC_DEV_ID_JPEG_0, 0, &stStream);
}
free(pstPack);
}
}
}
close(fd);
MI_VENC_CloseFd(MI_VENC_DEV_ID_JPEG_0, 0);
return NULL;
}
int main(void)
{
signal(SIGINT, intHandler);
MI_SYS_Init(0);
construct_vdec_module();
construct_wm_module();
construct_venc_module();
bind_vdec_wm_venc();
pthread_create(&g_vencGet, NULL, venc_output_thread, NULL);
while (keepRunning)
{
sleep(1);
}
pthread_join(g_vencGet, NULL);
sleep(2);
unbind_vdec_wm_venc();
destruct_venc_module();
destruct_wm_module();
destruct_vdec_module();
MI_SYS_Exit(0);
return 0;
}
7. PROCFS介绍¶
7.1 cat¶
-
调试信息
# cat proc/mi_modules/mi_wm/mi_wm0 -------------------------- Start Dump WM DEV 0 Info -------------------------------- DeviceStatus Start -------------------------- End Dump WM DEV 0 info -------------------------------- -------------------------- Start Dump WM CHN Info -------------------------------- chnID status outX outY width height priority 4 Enabled 890 490 140 100 63 5 Enabled 880 480 160 120 62 6 Enabled 870 470 180 140 61 7 Enabled 860 460 200 160 60 8 Enabled 850 450 220 180 59 9 Enabled 840 440 240 200 58 10 Enabled 830 430 260 220 57 0 Enabled 938 520 44 38 56 1 Enabled 920 520 80 46 55 2 Enabled 910 510 100 60 54 3 Enabled 900 500 120 80 53 -------------------------- End Dump WM CHN Info -------------------------------- -------------------------- Start Dump WM OUTPUT PORT Info ----------------------- inited chnId portId pixel width height bgColor frmate 1 0 0 11 1920 1080 65025 30 -------------------------- End Dump WM OUTPUT PORT Info ------------------------- -
调试信息分析
记录当前wm的使用状况以及device属性、Input属性、Output port属性,可以动态地获取到这些信息,方便调试和测试。
-
参数说明
参数 描述 device info DeviceStatus WM设备的工作状态
Uninit:未初始化
Init:初始化
Start:运行状态
Stop:停止状态input channel info chnId 输入通道ID
取值范围:[0,128),对应一个窗口。status 通道状态
Uninit:未初始化
Init:初始化
Enabled:已经使能
Disabled:已经禁用
Paused: 静止outX 窗口起始坐标X地址 outY 窗口起始坐标Y地址 width 窗口的图像宽度 height 窗口的图像高度 priority 窗口优先级,高优先级覆盖低优先级
取值范围:[0,128)Output port info Inited 是否有初始化Output Port
0:未初始化
1:已初始化chnId 输出通道ID
目前仅支持0portId 输出通道对应port
目前仅支持0pixel 色彩空间
目前仅支持11,即YUV420width 图像输出宽度 height 图像输出高度 bgColor 背景颜色
此处打印的是十进制frmate 输出帧率