MI WM API


REVISION HISTORY

Revision No.
Description
Date
1.00
  • Initial release
  • 11/15/2022

    1. 概述

    1.1 模块说明

    WM(window manger)模块设计用来堆叠窗口,重叠区域显示最高优先级窗口内容,每个输入通道对应一个窗口。可以通过置顶某窗口,将该窗口的优先级设置为最大。最多支持128个窗口堆叠。

    在置顶某窗口后,其他窗口之间优先级关系不变,如图1-1所示,

    图1-1 WM置顶窗口应用场景

    1.2 流程框图

    WM根据窗口的优先级关系,计算出各窗口的显示区域,避免重复拷贝重叠区域。

    本模块的输入源包括以下两类:

    1. APP直接注入图像数据到本模块。

    2. 绑定的前级模块发送图像数据到本模块。

    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模块。

    • 相关主题

      MI_WM_CloseDevice

    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停止对应的设备。

    • 相关主题

      MI_WM_OpenDevice

    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打开对应的设备。

    • 相关主题

      MI_WM_StopDevice

    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的输入通道/输出端口。

    • 相关主题

      MI_WM_StartDevice

    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_DestroyInputChannel

    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创建输入通道。

    • 相关主题

      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_GetInputChannelAttr

    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创建输入通道。

    • 相关主题

      MI_WM_SetInputChannelAttr

    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打开对应的设备。

    • 相关主题

      MI_WM_GetInputChannelAttr

    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打开对应的设备。

    • 相关主题

      MI_WM_SetOutputPortAttr

    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打开对应的设备。

    • 相关主题

      MI_WM_DisableInputChannel

    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打开对应的设备。

    • 相关主题

      MI_WM_EnableInputChannel

    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的通道产生作用。

    • 相关主题

      MI_WM_PauseInputChannel

    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的通道产生作用。

    • 相关主题

      MI_WM_ResumeInputChannel

    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]: B
      ePixelFormat 输出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
      目前仅支持0
      portId 输出通道对应port
      目前仅支持0
      pixel 色彩空间
      目前仅支持11,即YUV420
      width 图像输出宽度
      height 图像输出高度
      bgColor 背景颜色
      此处打印的是十进制
      frmate 输出帧率