跳转至

MI VDEC API


REVISION HISTORY

Revision No.
Description
Date
3.00
  • Initial release
  • 12/04/2020
    3.01
  • 新增API,用于暂停解码后刷重复帧功能
    MI_VDEC_PauseChn
    MI_VDEC_RefreshChn
    MI_VDEC_ResumeChn
  • 01/04/2021
    3.02
  • 新增MI_VDEC_StepChn,用于暂停解码后单帧播放功能
  • 02/24/2021
    3.03
  • 新增Muffin芯片解码规格
  • 新增Muffin数据流程图
  • 新增API
    MI_VDEC_SetOutputPortAttrEx
    MI_VDEC_GetOutputPortAttrEx
    MI_VDEC_SetDestCropEx
    MI_VDEC_GetDestCropEx
  • 05/19/2021
    3.04
  • 删除MI_VDEC_CreateDev原参数bDisableLowLatency,在MI_VDEC_CreateChn新增该参数,且支持按chn设置
  • MI_VDEC_CreateDev新增参数解码最大宽和高,用于调整解码器支持的最大码流分辨率
  • MI_VDEC_GetChnStat新增错误类型
  • 07/20/2021
  • 新增PROCFS介绍
  • 08/25/2021
    3.05
  • 新增API
    MI_VDEC_GetEventFd
    MI_VDEC_CloseEventFd
    MI_VDEC_CloseFd
    MI_VDEC_SubscribeEvent
    MI_VDEC_UnSubscribeEvent
    MI_VDEC_GetEvents
    MI_VDEC_GetEventData
    MI_VDEC_ClearEvents
  • 新增结构体
    MI_VDEC_SeqChgEvtInfo_t
    MI_VDEC_DecErrEvtInfo_t
    MI_VDEC_DecEosEvtInfo_t
    MI_VDEC_EventData_t
  • 新增枚举
    MI_VDEC_Event_e
  • 06/15/2022
  • MI_VDEC_ChnStat_s 新增解码图像原始宽高参数
  • 06/17/2022
  • 新增Opera芯片解码规格
  • 新增Opera数据流程图
  • 新增抓图场景port1口使用介绍
  • 06/17/2022
  • Opera平台中MI_VDEC_CreateDev接口添加接口调用顺序注意事项
  • 10/14/2022
  • 修改结构体,兼容32位和64位地址长度
    MI_VDEC_VideoStream_t
    MI_VDEC_UserData_t
  • 10/25/2022
    3.06
  • 新增结构体
    MI_VDEC_FrameDroppedEvtInfo_t
  • 新增MI_VDEC_Event_e枚举成员
    E_MI_VDEC_EVENT_FRAME_DROPPED
  • 10/28/2022
  • 更新procfs调试信息
  • 12/01/2022
  • 修改MI_PTR64 u64Reserved变量描述
  • 01/09/2023
    3.07
  • 更新iBopper芯片信息
  • 新增支持modparam配置的参数信息
  • 08/29/2024
    3.08
  • 修正文档部分错误表述
  • 添加ifackel芯片信息,包括新增MI_VDEC_SetChnRotate api描述和ifackel支持的功能信息
  • 09/10/2024
  • 修改API MI_VDEC_SetChnParam的支持情况和举例说明。
  • 修改结构体MI_VDEC_ChnParam_t的支持情况,新增支持设置成员eDecMode。
  • 修改枚举MI_VDEC_DecodeMode_e的支持情况,新增支持E_MI_VDEC_DECODE_MODE_I和E_MI_VDEC_DECODE_MODE_ALL。
  • 10/11/2024
    3.09
  • 更新jaguar1芯片信息
  • 更新procfs debug信息
  • 01/10/2025
    3.10
  • modparam新增支持配置参数:cpuMaskAffinity、threadPriority和maxChnNum
  • 02/27/2025
    3.11
  • 更新procfs debug信息
  • 05/21/2025
    3.12
  • 文档内容及示意图优化,新增三个章节:功能介绍、应用场景和实例介绍
  • 06/06/2025
    3.13
  • 新增mHera芯片信息
  • 新增关于LSYC功能的描述
  • 新增关于mHera支持port 2的介绍
  • 新增关于sps crop/user crop关系的描述
  • 12/02/2025
    3.14
  • 增加关于port属性相关的API新增PortId参数的描述
  • 12/23/2025
    3.15
  • 新增procfs debug中dumpfb命令支持按指定port dump
  • 04/24/2026
    3.16
  • modparam新增支持配置参数:maxChnId
  • 05/25/2026
    3.17
  • 增加关于mHera的功能限制说明
  • 修正文档格式错误
  • 07/27/2026

    1. 概述


    1.1. 模块简介

    视频解码功能参考,提供解码通道创建、码流传送及控制、输出图像裁剪和缩放等功能。

    VDEC模块的输入源主要是两类:

    • 用户读取码流文件向解码模块发送数据;

    • 用户将网络接收到的码流数据直接发送到解码模块。

      表 1-1 芯片解码规格

      芯片 硬件解码模块 支持最大通道数 通道号范围 支持协议 分辨率范围 默认最大分辨率
      Taiyaki DEC2.0 16 [0, 16) H.264/H.265 H.264: max 4096x4096, min 176x128
      H.265: max 4096x4096, min 176x128
      H.264: 4096x4096
      H.265: 4096x4096
      Takoyaki DEC2.0 4 [0, 4) H.264/H.265 H.264: max 4096x4096, min 176x128
      H.265: max 4096x4096, min 176x128
      H.264: 4096x4096
      H.265: 4096x4096
      Tiramisu DEC2.0 16 [0, 16) H.264/H.265 H.264: max 4096x4096, min 176x128
      H.265: max 4096x4096, min 176x128
      H.264: 4096x4096
      H.265: 4096x4096
      Mochi DEC2.0 64x2 [0, 64) H.264/H.265 H.264: max 8192x4096, min 176x128
      H.265: max 8192x4096, min 176x128
      H.264: 4704x4704
      H.265: 4704x4704
      Muffin DEC2.0 64x2 [0, 64) H.264/H.265 H.264: max 8192x4096, min 176x128
      H.265: max 8192x4096, min 176x128
      H.264: 3840x3840
      H.265: 3840x3840
      Opera DEC2.0 16 [0, 16) H.264/H.265 H.264: max 8192x4096, min 176x128
      H.265: max 8192x4096, min 176x128
      H.264: 4096x4096
      H.265: 4096x4096
      iBopper DEC2.0 64 [0, 64) H.264/H.265 H.264: max 8192x4096, min 176x128
      H.265: max 8192x4096, min 176x128
      H.264: 3840x3840
      H.265: 3840x3840
      ifackel DEC1.0 1 [0, 1) H.264 H.264: max 2304x1296, min 176x128 H.264: 2304x1296
      jaguar1 DEC2.0 64 [0, 64) H.264/H.265 H.264: max 8192x4096, min 176x128
      H.265: max 8192x4096, min 176x128
      H.264: 3840x3840
      H.265: 3840x3840
      mHera DEC3.0 64x2 [0, 128) H.264/H.265 H.264: max 8192x4320, min 176x128
      H.265: max 8192x4320, min 176x128
      H.264: 3840x3840
      H.265: 3840x3840

    注意:

    分辨率范围是以图像像素总数来计算的。比如:解码支持最大分辨率8192x4096,那么换成走廊模式的4096x8192,也是支持的。

    若用户未设置解码最大分辨率,则MI_VDEC模块使用默认的最大分辨率。用户可以通过MI_VDEC_CreateDev接口修改解码最大分辨率的限制。解码所需的sram大小匹配默认最大分辨率。如果用户设置最大图像的宽度超过默认值时,解码所需的sram大小也会随之增加,会影响到其他使用sram的MI模块;所以非必要时,最好通过MI_VDEC_CreateDev接口将解码最大分辨率设回默认最大分辨率。

    通道号范围用于描述解码通道号的合法取值区间,单个VDEC设备可创建的总通道数受其最大支持通道数的约束。


    1.2. 解码流程图

    1.2.1. Taiyaki数据流程图

    图1-1 VDEC数据流程图

    1.2.2. Takoyaki数据流程图

    图1-2 VDEC数据流程图

    1.2.3. Tiramisu数据流程图

    图1-3 VDEC数据流程图

    1.2.4. Muffin数据流程图

    图1-4 VDEC数据流程图

    Muffin 总共有两个VDEC硬件,两硬件解码能力一致。通过Device ID区分,分别为Device0与Device1。

    1.2.5. Mochi数据流程图

    图1-5 VDEC数据流程图

    Mochi 总共有两个VDEC硬件,两硬件解码能力一致。通过Device ID区分,分别为Device0与Device1。

    1.2.6. Opera数据流程图

    图1-6 VDEC数据流程图

    1.2.7. iBopper数据流程图

    图1-7 VDEC数据流程图

    1.2.8. ifackel数据流程图

    图1-8 VDEC数据流程图

    1.2.9. jaguar1数据流程图

    图1-9 VDEC数据流程图

    注意:不支持与VENC Device id为MI_VENC_DEV_ID_H264_H265_1的设备同时开启。

    1.2.10. mHera数据流程图

    图1-10 VDEC数据流程图

    mHera 总共有两个VDEC硬件,两硬件解码能力一致。通过Device ID区分,分别为Device0与Device1。


    1.3. 关键字说明

    • 码流发送方式

      VDEC解码器定义两种码流发送方式:

      1. 按帧发送(E_MI_VDEC_VIDEO_MODE_FRAME):用户每次发送完整的一帧码流到解码器,每调用一次发送接口,解码器就认为该帧码流已经结束,并开始解码图像。因此,用户需保证每次发送的码流必须为完整的一帧,否则会出现解码错误。使用该模式可以达到快速解码的目的。

      2. 按流发送(E_MI_VDEC_VIDEO_MODE_STREAM):用户每次可发送任意长度码流到解码器,由解码器内部完成码流帧的解析和拼接过程。对于H.264/H.265,需在收到下一帧码流才能确认为当前码流帧的结束,所以在该模式下,输入一帧H.264/H.265码流,不会立刻解出图像。目前不支持按流发送功能。

      码流发送方式eVideoMode可在接口MI_VDEC_CreateChn 中设置。

    • 图像输出顺序

      根据H.264/H.265协议,解码图像输出的方式包括以下两种:

      1. 解码序:解码图像按照解码的先后顺序输出。

      2. 显示序:解码图像按照协议中的显示顺序输出。

      根据H.264/H.265协议,视频的解码顺序(即解码序)和解码图像的显示顺序(即显示序)可能不一致。例如:解码B帧时,需要前后的P帧作为参考,所以B帧后的P帧先于B帧解码,但B帧先于后面的P帧显示。

      VDEC解码器根据用户设置的低延时开关来决定使用何种输出方式。当开启低延时,会以解码序输出,可以达到快速输出的目的,但必须保证码流的解码序和显示序相同,才能保证显示画面的正确性;当不开启低延时,则会以显示序输出。

    • 低延时

      这里的延时是指解码B帧后,需要对待显示的图像队列进行重排序(reorder)所产生的延时。当解码不含B帧的码流时,解码顺序和显示顺序相同,因此不需要延时输出,即低延时;而解码含B帧的码流时,由于B帧有前后向参考,需要等待所参考的图像解码完后,才能解当前帧,并且需要对解码后的图像重排序(reorder),由此产生输出延时。这两种模式需要通过设置bDisableLowLatency来完成。默认bDisableLowLatency为FALSE,用户无需设置;当需要解码B帧码流时,需要将bDisableLowLatency设为TRUE。

      注意:芯片ifackel不支持bDisableLowLatency设置为TRUE,所以只会按解码序输出。

    • 时间戳(PTS)处理

      在按帧模式发送码流时,解码输出的图像时间戳PTS为发送码流接口(MI_VDEC_SendStream)中用户送入的PTS,解码器不会更改此值。如果用户送入的PTS值为-2,则解码器不会输出该帧,达到隐藏帧的效果;如果是其他值,则解码器不做任何处理。

      该PTS不用于帧率控制。帧率控制功能请参考MI SYS文档中的API说明。

    • 码流Buffer

      码流Buffer用于缓存用户输入的码流,然后送入解码器解码。码流buffer的大小没有固定的计算公式,一般按照经验值,分辨率小于或等于D1,建议配置为512KB;分辨率在(D1,1080P],建议配置为1MB;分辨率在(1080P,4K],建议配置为2MB;用户可根据实际需求,选择合理的值设置。

    • eDpbBufMode

      eDpbBufMode可供用户设置不同的DPB buffer模式进行解码。根据不同的场景,选择不同的buffer模式,可以达到省内存的目的。当设为E_MI_VDEC_DPB_MODE_NORMAL,则不能节省内存;当设为E_MI_VDEC_DPB_MODE_INPLACE_ONE_BUF,则用于解码仅包含一个参考帧的码流,此时仅需一个DPB buffer;当设为E_MI_VDEC_DPB_MODE_INPLACE_TWO_BUF,则用于解码仅包含两个参考帧的码流,此时仅需两个DPB buffer。

      注意:芯片ifackel不支持设置eDpbBufMode,仅支持E_MI_VDEC_DPB_MODE_NORMAL。

    • u32RefFrameNum

      u32RefFrameNum表示最大参考帧个数。由于在实际的场景中,系统的内存并不是无限大,用户可以根据产品的定义对参考帧的个数进行限制,以便提示用户当前码流可能超规格。如果用户设置了eDpbBufMode为E_MI_VDEC_DPB_MODE_INPLACE_ONE_BUF或者E_MI_VDEC_DPB_MODE_INPLACE_TWO_BUF,则该参数无效。如果用户设置了eDpbBufMode为E_MI_VDEC_DPB_MODE_NORMAL,则解码器在参考帧个数受到限制时进行解码,解码图像可能会异常或者解码超时。

    • 输出buffer模式

      用户可以调用MI_VDEC_SetOutputPortLayoutMode设置输出buffer的模式。当用户需要手动控制输出buffer的模式时,可调用该接口。当为E_MI_VDEC_OUTBUF_LAYOUT_LINEAR模式时,表示输出buffer为线性模式;当为E_MI_VDEC_OUTBUF_LAYOUT_TILE模式时,表示输出buffer为TILE模式;默认为E_MI_VDEC_OUTBUF_LAYOUT_AUTO模式,表示输出buffer会自动在线性模式和TILE模式间切换。

    • 输出图像格式

      目前H264及H265解码只支持输出NV12图像格式。

    • H264/H265语法特性支持情况

      仅支持解码YUV位宽为8bit的码流;不支持H264场模式/FMO(Flexiable mb ordering)/ASO(Arbitrary slice ordering)。


    1.4. 功能介绍

    • 输出图像缩放

      用户调用MI_VDEC_SetOutputPortAttr可以对解码后的图像进行缩放,以输出需要的分辨率的图像。

      注意:1.解码器仅支持对图像缩小,不支持对图像放大;2.芯片ifackel不支持该功能。

    • 输出图像裁剪

      用户调用MI_VDEC_SetDestCrop可以对解码后的图像进行裁剪再输出。设置裁剪时,裁剪的左上角坐标X和裁剪宽度必须按一定长度对齐(芯片mHera为按2对齐,其余支持裁剪功能的芯片按16对齐),裁剪的左上角坐标Y和裁剪高度必须按2对齐,否则接口会返回错误码MI_ERR_VDEC_ILLEGAL_PARAM。如果裁剪功能和缩放功能同时使用,则按照先裁剪后缩放的处理顺序,裁剪的图像大小不能小于缩放的大小,否则接口会返回错误码MI_ERR_VDEC_ILLEGAL_PARAM。

      注意:芯片ifackel不支持该功能。

      裁剪和缩放的关系:

      1. 裁剪关闭,缩放关闭,输出为原图像;

      2. 裁剪关闭,缩放开启,输出为缩放后的图像;

      3. 裁剪开启,缩放关闭,输出为裁剪后的图像;

      4. 裁剪开启,缩放开启,输出为以裁剪后的的图像为参考,再做缩放后的图像;

        如果开启了缩放,则最后输出的frame buffer以缩放大小为最终输出大小。

      用户设置的裁剪(user crop)和缩放(scale)都是基于码流原始分辨率(source resolution)下进行。若码流SPS(序列参数集)中带有crop window信息,VDEC内部会再做一层转换以给出最终的显示区域。SPS crop window指示了在码流原始分辨率下可用于显示的范围,需要结合用户裁剪/缩放后的窗口情况,通过转换得到最终的显示窗口(Content Crop Window)。转换的公式如下:

      content_crop_win_x = (MAX(sps_crop_x,user_crop_x)-user_crop_x)*scale_width/user_crop_width
      content_crop_win_y = (MAX(sps_crop_y,user_crop_y)-user_crop_y)*scale_height/user_crop_height
      content_crop_win_width = (MIN(sps_crop_x+sps_crop_width,user_crop_x+user_crop_width)-MAX(sps_crop_x,user_crop_x))*scale_width/user_crop_width
      content_crop_win_height = (MIN(sps_crop_y+sps_crop_height,user_crop_y+user_crop_height)-MAX(sps_crop_y,user_crop_y))*scale_height/user_crop_height

      若只开启scale,没有开启user crop,则使用以下规则:user_crop_x=0,user_crop_y=0,user_crop_width=sps_width,user_crop_height=sps_height,代入公式。

      若只开启user crop,没有开启scale,则使用以下规则:scale_width=user_crop_width,scale_height=user_crop_height,代入公式。

      最后转换后的显示窗口信息,在开启低延时(bDisableLowLatency=FALSE)的情况下,可通过output buffer的MI_SYS_FrameData_t结构体中的stContentCropWindow获得,该结构体定义请参考MI SYS文档。

      下面以三种情况举例说明通过结合user crop和SPS crop转换到最终显示窗口的过程:

      • 情况1:用户设置的user crop window包含在SPS crop window里面

        此时整个user crop window都在图像有效显示区域内,所以不需要对VDEC输出的output buffer再做额外的裁剪,例子中同时开启了scale功能,所以最终显示的窗口为scale后的窗口。

      • 情况2:用户设置的user crop window与SPS crop window有部分重叠

        此时user crop window只有与SPS crop window重叠的部分(图中Valid Area部分)是在图像有效显示区域内,所以需要对VDEC输出的output buffer做额外的裁剪,因例子中同时开启了scale功能,需要对Valid Area部分做对应比例的缩放,得到最终显示的窗口。

      • 情况3:SPS crop window包含在用户设置的user crop window里面

        此时只有SPS crop window的部分是图像的有效显示区域,所以需要对VDEC输出的output buffer做额外的裁剪,因例子中同时开启了scale功能,需要对SPS crop window部分做对应比例的缩放,得到最终显示的窗口。

      注意:如果user crop window和SPS crop window没有交集,此时整个user crop window都未在图像有效显示区域内,应避免这种情况。

    • 抓图功能

      抓图的目的是为了在保持port0输出分辨率不变的情况下,同时port1可以输出码流原始分辨率的图像。这样,解码同一个码流数据帧时,可以输出两种不同分辨率的图像。在抓图场景下,解码输出码流原始分辨率大小的数据帧,可以使抓拍的图像更清晰。需要注意,除了以下芯片外:mHera,其余支持该功能的芯片的Port1只支持原图输出,不支持裁剪与缩放功能,用户如需调整Port1输出图像大小,可以先绑定MI_SCL调整输出图像大小,再绑定MI_VENC编码存盘。而且,仅在开启低延时(bDisableLowLatency=FALSE)的情况下支持该功能。

      注意:芯片ifackel不支持该功能。

      Port1 bind场景用例:

      以下芯片:mHera,对该功能进行了拓展:

      • 除了支持port1,还支持再出一路输出port2。port1/port2是分时复用的,一帧图像的port输出只会出现以下的情况:只输出port0、输出port0加输出port1、输出port0加输出port2,所以port1加上port2的输出帧率必须小于等于port0的输出帧率。关于port的帧率控制设置请参考MI SYS文档。

      • port0/port1/port2都支持裁剪/缩放/LSYC功能(LSYC使用限制参考下面的功能描述)。且开启缩放功能时,port0缩放最大输出分辨率为3840x2160,port1/port2缩放最大输出分辨率为1920x1080。

    • 静帧功能

      静帧是指对同一帧码流数据进行多次解码,用于需要多次查看同一帧画面经过不同缩放、裁剪操作后的图像。例如,在进行多路视频画面预览时,如果需要对某个通道全屏显示,可以先暂停该通道解码,随后调整该通道的输出缩放、裁剪参数,再使用此功能对该通道当前码流数据重新进行解码,使解码输出图像分辨率可以和屏幕分辨率相匹配,从而达到全屏清晰显示的效果。

      注意:1.解码B帧时,不支持该功能;2.芯片ifackel不支持该功能。

    • 旋转功能

      对解码输出图像进行旋转,旋转角度(顺时针)包括:90°、180°、270°。

      注意:目前仅芯片ifackel支持该功能。

    • LSYC功能

      对解码输出图像进行有损压缩,需VDEC后级绑定支持解压缩的模块(目前仅MI_DISP模块支持),通过pipeline将压缩后的数据传递到后级模块,后级模块的解压缩硬件对数据进行解压缩,以得到可以用于显示的图像。该功能可以减小VDEC output buffer的用量,同时降低带宽的消耗,但是会损失图像画质。LSYC功能开关是每个port独立设置的,使用上存在以下限制:当port0打开LSYC功能,port1/port2必须关闭LSYC功能;当port0关闭LSYC功能时,port1/port2各自可打开或关闭LSYC功能。

      注意:支持该功能的芯片:mHera。在使用上存在的限制:LSYC开启时,输出的最大分辨率为4096x4096;LSYC功能不支持H265开启多Tile划分(图像参数集PPS语法中tiles_enabled_flag为1)的码流,若解码到这类码流,LSYC功能会被强制关闭。


    1.5. modparam 模块参数

    • vdec支持通过模块参数(modparam)修改部分参数配置,用户可以根据需要进行修改。各参数具体信息如下表:

      参数名

      作用

      默认参数

      iBopper ifackel jaguar1 mHera
      cpuMaskAffinity VDEC线程与CPU之间的亲和力,参数配置说明如下 0 0 0 0
      threadPriority VDEC线程优先级,有效范围[0-99],不设置或超出有效范围时内部会使用默认值 99 99 99 99
      maxChnNum 单个VDEC设备可创建的最大通道数,有效范围[1,N],N参考表 1-1 芯片解码规格;不设置或设置超过有效范围时内部会使用默认值 64 1 64 64
      maxChnId 单个VDEC通道可创建的最大通道号,有效范围[1,N),N参考表 1-1 芯片解码规格;不设置或设置超过有效范围时内部会使用默认值 64 1 64 64
      vdec_clock VDEC硬件时钟,不设置或设置为0时内部会使用默认值。注意:支持多个VDEC硬件的芯片(如:mHera)需要使用数组的形式进行配置,对应于支持的相应数量的VDEC硬件的时钟设置,如:设置为[504000000,480000000]表示Device0的VDEC硬件时钟为504000000,Device1的VDEC硬件时钟为480000000。 0 0 0 [0,0]
      vdec_clock_2nd VDEC硬件子模块时钟,不设置或设置为0时内部会使用默认值 0 0 0 x
      vdec_clock_axi VDEC arbiter时钟,不设置或设置为0时内部会使用默认值 0 0 0 x

    • cpuMaskAffinity为16位mask使用形式,每4位分为一组共4组,从低位到高位每一组分别对应VDEC设备0~3线程的亲和力配置;每一组4位[0,3]分别表示将对应该组的VDEC设备线程绑定到CPU核[0,3]的配置位,每一位置为1表示绑定到该CPU核,为0表示不绑定到该CPU核,4位全为0表示不绑定该VDEC设备线程到任何一个CPU核,此时由CPU自行调度VDEC设备线程。举例,将VDEC设备0线程绑定到CPU核1,需配置cpuMaskAffinity为2 = 0b0000 0000 0000 0010。

    • 模块参数通过文件modparam.json进行配置和修改,该文件一般放在板端/config目录下。参数配置可参照如下方式:

      "E_MI_MODULE_ID_VDEC" :
      {
          "cpuMaskAffinity" : 0,
          "threadPriority" : 99,
          "maxChnNum" : 64,
          "maxChnId" : 64,
          "vdec_clock" : 0,
          "vdec_clock_2nd" : 0,
          "vdec_clock_axi" : 0
      }
      
    • 模块参数也可通过echo命令导入修改后的配置,流程如下:

      • 新建或者从/config目录下拷贝一份json文件,并按照要求的格式进行修改。以参数vdec_clock为例,新建文件命名为vdec_clock.json,内容如下:

        "E_MI_MODULE_ID_VDEC" :
        {
            "cpuMaskAffinity" : 1,
            "threadPriority" : 98,
            "maxChnNum" : 32,
            "maxChnId" : 32,
            "vdec_clock": 384000000,
            "vdec_clock_2nd" : 384000000,
            "vdec_clock_axi" : 384000000
        }
        
      • 使用echo命令导入json配置

        echo vdec_clock.json > /proc/mi_modules/mi_common/modparam
        
      • 重新加载mi_vdec.ko后,运行应用程序或者调用VDEC相关API

    • 注意

      • 模块参数在insmod mi_vdec.ko时生效。VDEC模块启动后,再输入修改命令则无效。

      • 每次系统重启后,模块参数将被重置为默认值,用户需要重新配置模块参数。


    1.6. 应用场景

    • 本地视频回放

      读取本地视频文件,通过视频解码模块解析出原始的画面,在屏幕上显示。

    • 网络视频预览

      读取网络视频流,通过视频解码模块解析之后在屏幕上显示,从而对网络视频进行实时预览。

    • 视频解码再编码

      从本地文件或网络读取视频流数据,通过视频解码模块解析出原始的画面,经应用程序进一步处理后,再送给视频编码模块重新编码为视频流。


    1.7. 实例介绍

    本实例调用MI VDEC API对本地一个H.264格式、1920x1080分辨率的视频文件进行解码,并将VDEC和DISP两个模块进行绑定,以30fps的帧率进行回放。

    #include <stdio.h>
    #include <stdlib.h>     // malloc + free
    #include <string.h>     // memset
    #include <unistd.h>     // usleep
    #include <stdint.h>     // uint8_t
    
    #include "mi_sys.h"     // MI SYS API
    #include "mi_vdec.h"    // MI VDEC API
    #include "mi_disp.h"    // MI DISP API
    
    static const int SCREEN_WIDTH = 1920;       // width of display screen
    static const int SCREEN_HEIGHT = 1080;      // height of display screen
    static const int VIDEO_WIDTH = 1920;        // width of input video bitstream file
    static const int VIDEO_HEIGHT = 1080;       // height of input video bitstream file
    static const int BS_BUFFER_SIZE = 0x100000; // buffer for read from input file
    
    int VdecInit(MI_VDEC_DEV vdecDev, MI_VDEC_CHN vdecChn, MI_VDEC_CodecType_e eCodecType, int width, int height)
    {
        MI_S32 s32Ret   = MI_SUCCESS;
        MI_U8  u8PortId = 0;
    
        // Create vdec device
        MI_VDEC_InitParam_t stInitParam;
        memset(&stInitParam, 0, sizeof(MI_VDEC_InitParam_t));
        stInitParam.u16MaxWidth = 8192;
        stInitParam.u16MaxHeight = 4096;
        if((s32Ret = MI_VDEC_CreateDev(vdecDev, &stInitParam)) != MI_SUCCESS)
        {
            printf("MI_VDEC_CreateDev failed, ret:0x%x\n", s32Ret);
            return -1;
        }
    
        // Create vdec channel with given information
        MI_VDEC_ChnAttr_t stChnAttr;
        memset(&stChnAttr, 0x0, sizeof(MI_VDEC_ChnAttr_t));
        stChnAttr.eCodecType = eCodecType;
        stChnAttr.u32PicWidth = width;
        stChnAttr.u32PicHeight = height;
        stChnAttr.eVideoMode = E_MI_VDEC_VIDEO_MODE_FRAME;
        stChnAttr.u32BufSize = 2 * 1024 * 1024;
        stChnAttr.eDpbBufMode = E_MI_VDEC_DPB_MODE_NORMAL;
        stChnAttr.stVdecVideoAttr.u32RefFrameNum = 10;
        stChnAttr.u32Priority = 0;
        stChnAttr.stVdecVideoAttr.stErrHandlePolicy.bUseCusPolicy = false;
        stChnAttr.stVdecVideoAttr.bDisableLowLatency = true;
        if ((s32Ret = MI_VDEC_CreateChn(vdecDev, vdecChn, &stChnAttr)) != MI_SUCCESS)
        {
            printf("MI_VDEC_CreateChn failed, ret:0x%x\n", s32Ret);
            return -1;
        }
    
        // Set scale output size if needed
        // Only support zoom out, DO NOT support zoom in
        MI_VDEC_OutputPortAttr_t stOutputPortAttr;
        memset(&stOutputPortAttr, 0, sizeof(stOutputPortAttr));
        stOutputPortAttr.u16Width = width;
        stOutputPortAttr.u16Height = height;
        if ((s32Ret = MI_VDEC_SetOutputPortAttr(vdecDev, vdecChn, u8PortId, &stOutputPortAttr)) != MI_SUCCESS)
        {
            printf("MI_VDEC_SetOutputPortAttr failed, ret:0x%x\n", s32Ret);
            return -1;
        }
    
        // Start vdec channel
        if ((s32Ret = MI_VDEC_StartChn(vdecDev, vdecChn)) != MI_SUCCESS)
        {
            printf("MI_VDEC_StartChn failed, ret:0x%x\n", s32Ret);
            return -1;
        }
    
        return 0;
    }
    
    void VdecDeinit(MI_VDEC_DEV vdecDev, MI_VDEC_CHN vdecChn)
    {
        // Stop vdec channel
        MI_VDEC_StopChn(vdecDev, vdecChn);
        // Destroy vdec channel
        MI_VDEC_DestroyChn(vdecDev, vdecChn);
        // Destroy vdec device
        MI_VDEC_DestroyDev(vdecDev);
    }
    
    int DispInit(MI_DISP_DEV dispDev, MI_DISP_LAYER dispLayer, int srcWidth, int srcHeight)
    {
        MI_S32 s32Ret = MI_SUCCESS;
    
        MI_DISP_PubAttr_t stDispPubAttr;
        memset(&stDispPubAttr, 0, sizeof(stDispPubAttr));
        stDispPubAttr.u32BgColor = 0x800080;    // YUYV Black
        stDispPubAttr.eIntfSync = E_MI_DISP_OUTPUT_1080P60;
        stDispPubAttr.eIntfType = E_MI_DISP_INTF_HDMI;
        if ((s32Ret = MI_DISP_SetPubAttr(dispDev, &stDispPubAttr)) != MI_SUCCESS)
        {
            printf("MI_DISP_SetPubAttr failed, ret:0x%x\n", s32Ret);
            return -1;
        }
        if ((s32Ret = MI_DISP_Enable(dispDev)) != MI_SUCCESS)
        {
            printf("MI_DISP_Enable failed, ret:0x%x\n", s32Ret);
            return -1;
        }
    
        MI_DISP_VideoLayerAttr_t stLayerAttr;
        memset(&stLayerAttr, 0, sizeof(stLayerAttr));
        stLayerAttr.stVidLayerSize.u16Width  = SCREEN_WIDTH;
        stLayerAttr.stVidLayerSize.u16Height = SCREEN_HEIGHT;
        stLayerAttr.ePixFormat = E_MI_SYS_PIXEL_FRAME_YUV_SEMIPLANAR_420;
        stLayerAttr.stVidLayerDispWin.u16X = 0;
        stLayerAttr.stVidLayerDispWin.u16Y = 0;
        stLayerAttr.stVidLayerDispWin.u16Width = SCREEN_WIDTH;
        stLayerAttr.stVidLayerDispWin.u16Height = SCREEN_HEIGHT;
        if ((s32Ret = MI_DISP_BindVideoLayer(dispLayer, dispDev)) != MI_SUCCESS)
        {
            printf("MI_DISP_BindVideoLayer failed, ret:0x%x\n", s32Ret);
            return -1;
        }
        if ((s32Ret = MI_DISP_SetVideoLayerAttr(dispLayer, &stLayerAttr)) != MI_SUCCESS)
        {
            printf("MI_DISP_SetVideoLayerAttr failed, ret:0x%x\n", s32Ret);
            return -1;
        }
        if ((s32Ret = MI_DISP_EnableVideoLayer(dispLayer)) != MI_SUCCESS)
        {
            printf("MI_DISP_EnableVideoLayer failed, ret:0x%x\n", s32Ret);
            return -1;
        }
    
        MI_DISP_InputPortAttr_t stInputPortAttr;
        memset(&stInputPortAttr, 0, sizeof(stInputPortAttr));
        // Video frame size
        stInputPortAttr.u16SrcWidth = srcWidth;
        stInputPortAttr.u16SrcHeight = srcHeight;
        stInputPortAttr.stDispWin.u16X = 0;
        stInputPortAttr.stDispWin.u16Y = 0;
        stInputPortAttr.stDispWin.u16Width = SCREEN_WIDTH;
        stInputPortAttr.stDispWin.u16Height = SCREEN_HEIGHT;
        if ((s32Ret = MI_DISP_SetInputPortAttr(dispLayer, 0, &stInputPortAttr)) != MI_SUCCESS)
        {
            printf("MI_DISP_SetInputPortAttr failed, ret:0x%x\n", s32Ret);
            return -1;
        }
        if ((s32Ret = MI_DISP_EnableInputPort(dispLayer, 0)) != MI_SUCCESS)
        {
            printf("MI_DISP_EnableInputPort failed, ret:0x%x\n", s32Ret);
            return -1;
        }
    
        return 0;
    }
    
    void DispDeinit(MI_DISP_DEV dispDev, MI_DISP_LAYER dispLayer)
    {
        MI_DISP_DisableInputPort(dispLayer, 0);
        MI_DISP_DisableVideoLayer(dispLayer);
        MI_DISP_UnBindVideoLayer(dispLayer, dispDev);
        MI_DISP_Disable(dispDev);
    }
    
    // Find start code {0x00 0x00 0x00 0x01} of H.264
    const uint8_t *FindStartcode(const uint8_t *pStart, const uint8_t *pEnd)
    {
        const uint8_t *out = NULL;
        const uint8_t *p = pStart;
        const uint8_t *end = pEnd;
        const uint8_t *a = p + 4 - ((intptr_t)p & 3);
    
        for (end -= 3; p < a && p < end; p++)
        {
            if (p[0] == 0 && p[1] == 0 && p[2] == 1)
            {
                out = p;
                goto EXIT;
            }
        }
    
        for (end -= 3; p < end; p += 4)
        {
            uint32_t x = *(const uint32_t *)p;
            if ((x - 0x01010101) & (~x) & 0x80808080) // generic
            {
                if (p[1] == 0)
                {
                    if (p[0] == 0 && p[2] == 1)
                    {
                        out = p;
                        goto EXIT;
                    }
                    if (p[2] == 0 && p[3] == 1)
                    {
                        out = p + 1;
                        goto EXIT;
                    }
                }
                if (p[3] == 0)
                {
                    if (p[2] == 0 && p[4] == 1)
                    {
                        out = p + 2;
                        goto EXIT;
                    }
                    if (p[4] == 0 && p[5] == 1)
                    {
                        out = p + 3;
                        goto EXIT;
                    }
                }
            }
        }
    
        for (end += 3; p < end; p++)
        {
            if (p[0] == 0 && p[1] == 0 && p[2] == 1)
            {
                out = p;
                goto EXIT;
            }
        }
    
        out = end + 3;
    
    EXIT:
        if (pStart < out && out < pEnd && !out[-1])
            out--;
    
        return out;
    }
    
    int main(int argc, const char *argv[])
    {
        const char *pInputFilePath = NULL;
        FILE *pInputFile = NULL;
        uint8_t *pBsBuffer = NULL;
        uint64_t naluCnt = 0;
    
        MI_VDEC_DEV vdecDev = 0;
        MI_VDEC_CHN vdecChn = 0;
        MI_VDEC_CodecType_e eCodecType = E_MI_VDEC_CODEC_TYPE_H264;
        MI_SYS_ChnPort_t stVdecChnPort, stDispChnPort;
        MI_DISP_DEV dispDev = 0;
        MI_DISP_LAYER dispLayer = 0;
        MI_U32 u32FrameRate = 30;
    
        for (int i = 1; i < argc; i++)
        {
            if (!strcmp(argv[i], "-i"))
                pInputFilePath = argv[++i];
        }
    
        if (pInputFilePath)
        {
            printf("InputFilePath:%s\n", pInputFilePath);
            if ((pInputFile = fopen(pInputFilePath, "rb")) == NULL)
            {
                printf("Failed to open input file for read\n");
                goto EXIT;
            }
        }
        else
        {
            printf("No input file specified\n");
            printf("Usage: %s -i INPUT_FILE\n", argv[0]);
            goto EXIT;
        }
    
        // Init MI SYS
        MI_SYS_Init(0);
    
        // Init MI VDEC
        if (VdecInit(vdecDev, vdecChn, eCodecType, VIDEO_WIDTH, VIDEO_HEIGHT) < 0)
            goto EXIT;
    
        // Init MI DISP
        if (DispInit(dispDev, dispLayer, VIDEO_WIDTH, VIDEO_HEIGHT) < 0)
            goto EXIT;
    
        // Set output port depth(total output buffer count that VDEC can use)
        memset(&stVdecChnPort, 0x0, sizeof(MI_SYS_ChnPort_t));
        stVdecChnPort.eModId = E_MI_MODULE_ID_VDEC;
        stVdecChnPort.u32DevId = vdecDev;
        stVdecChnPort.u32ChnId = vdecChn;
        stVdecChnPort.u32PortId = 0;
        MI_SYS_SetChnOutputPortDepth(0, &stVdecChnPort, 0, 4);
    
        // Bind vdec and disp
        memset(&stDispChnPort, 0x0, sizeof(MI_SYS_ChnPort_t));
        stDispChnPort.eModId = E_MI_MODULE_ID_DISP;
        stDispChnPort.u32DevId = dispDev;
        stDispChnPort.u32ChnId = 0;
        stDispChnPort.u32PortId = 0;
        MI_SYS_BindChnPort2(0, &stVdecChnPort, &stDispChnPort, u32FrameRate, u32FrameRate, E_MI_SYS_BIND_TYPE_FRAME_BASE, 0);
    
        // Read nalu from input es file, and send stream to MI VDEC
        pBsBuffer = (uint8_t *)malloc(BS_BUFFER_SIZE);
        long readPosition = 0;
        while (true)
        {
            fseek(pInputFile, readPosition, SEEK_SET);
            memset(pBsBuffer, 0, BS_BUFFER_SIZE);
            size_t readSize = fread(pBsBuffer, 1, BS_BUFFER_SIZE, pInputFile);
            if (readSize == 0)
            {
                printf("Get EOF flag, restart from begining\n");
                readPosition = 0;
                continue;
            }
    
            const uint8_t *pStart = pBsBuffer;
            const uint8_t *pEnd = pBsBuffer + readSize;
            const uint8_t *pNaluStart = FindStartcode(pStart, pEnd);
            const uint8_t *pNaluEnd = NULL;
            int i = 0;
            // Skip start code
            while (pNaluStart && (pNaluStart < pEnd) && !pNaluStart[i]) i++;
            // Find next nalu start code as nalu end
            pNaluEnd = FindStartcode(pNaluStart + i, pEnd);
            int naluSize = pNaluEnd - pNaluStart;
    
            printf("Get new nalu pos:%ld size:%d cnt:%lld\n", readPosition, naluSize, ++naluCnt);
    
            // Mark next nalu read position in file
            readPosition += (pNaluEnd - pStart);
    
            // Send bitstream data to MI VDEC
            MI_VDEC_VideoStream_t stVdecStream;
            memset(&stVdecStream, 0x0, sizeof(MI_VDEC_VideoStream_t));
            stVdecStream.pu8Addr = (MI_U8 *)pNaluStart;
            stVdecStream.u32Len = naluSize;
            stVdecStream.u64PTS = 0;
            stVdecStream.bEndOfFrame = true;
            stVdecStream.bEndOfStream = 0;
            MI_VDEC_SendStream(vdecDev, vdecChn, &stVdecStream, 0);
    
            // Sleep for rate control
            usleep(25000);
        }
    
    EXIT:
        DispDeinit(dispDev, dispLayer);
        VdecDeinit(vdecDev, vdecChn);
        // Deinit MI SYS
        MI_SYS_Exit(0);
    
        if (pInputFile)
            fclose(pInputFile);
        if (pBsBuffer)
            free(pBsBuffer);
    
        return 0;
    }
    

    2. API列表


    该功能模块提供以下API:

    API名 功能
    MI_VDEC_CreateDev 创建解码设备
    MI_VDEC_DestroyDev 销毁解码设备
    MI_VDEC_CreateChn 创建解码通道
    MI_VDEC_DestroyChn 销毁解码通道
    MI_VDEC_StartChn 开始通道解码
    MI_VDEC_StopChn 停止通道解码
    MI_VDEC_GetChnAttr 获取解码通道属性
    MI_VDEC_GetChnStat 获取解码通道状态
    MI_VDEC_FlushChn 清理解码通道缓存数据
    MI_VDEC_ResetChn 复位解码通道
    MI_VDEC_SetChnParam 设置解码通道参数
    MI_VDEC_GetChnParam 获取解码通道参数
    MI_VDEC_SendStream 向解码通道发送码流数据
    MI_VDEC_PauseChn 暂停通道解码
    MI_VDEC_RefreshChn 刷新通道,再次解码当前帧
    MI_VDEC_ResumeChn 恢复通道解码
    MI_VDEC_StepChn 通道单帧解码。
    MI_VDEC_GetUserData 获取解码通道的用户数据
    MI_VDEC_ReleaseUserData 释放解码通道的用户数据
    MI_VDEC_SetDisplayMode 设置解码通道显示模式
    MI_VDEC_GetDisplayMode 获取解码通道显示模式
    MI_VDEC_SetOutputPortAttr 设置解码通道输出端口属性
    MI_VDEC_GetOutputPortAttr 获取解码通道输出端口属性
    MI_VDEC_SetOutputPortLayoutMode 设置输出端口Buffer模式
    MI_VDEC_GetOutputPortLayoutMode 获取输出端口Buffer模式
    MI_VDEC_SetDestCrop 设置解码通道裁剪属性
    MI_VDEC_GetDestCrop 获取解码通道裁剪属性
    MI_VDEC_SetChnErrHandlePolicy 设置解码通道错误宏块的数据帧的输出策略
    MI_VDEC_GetEventFd 获取指定通道对应的设备文件句柄
    MI_VDEC_CloseEventFd 关闭指定通道句柄
    MI_VDEC_SubscribeEvent 开始监听通道指定事件信息
    MI_VDEC_UnSubscribeEvent 取消监听通道指定事件信息
    MI_VDEC_GetEvents 获取通道产生的所有的事件信息
    MI_VDEC_GetEventData 获取通道指定事件的详细信息
    MI_VDEC_ClearEvents 清除通道产生的指定的事件信息
    MI_VDEC_SetChnRotate 设置解码通道输出图像旋转角度

    2.1. MI_VDEC_CreateDev

    • 功能

      创建解码设备。

    • 定义

      MI_S32 MI_VDEC_CreateDev(MI_VDEC_DEV VdecDev, MI_VDEC_InitParam_t *pstInitParam);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      pstInitParam 解码设备初始化参数指针,数据类型:MI_VDEC_InitParam_t 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 设备号不能超出最大的设备号范围。

      • 该接口可选调用,若在创建解码通道前未调用该接口,则在创建解码通道时会再去创建解码设备。

    • 举例

      MI_S32 StartVdec(void)
      {
          MI_S32 s32Ret = MI_ERR_VDEC_FAILED;
          MI_VDEC_DEV VdecDev = 0;
          MI_VDEC_CHN VdecChn = 0;
          MI_VDEC_InitParam_t stInitParam;
          MI_VDEC_ChnAttr_t stChnAttr;
      
          memset(&stInitParam, 0x0, sizeof(MI_VDEC_InitParam_t));
          memset(&stChnAttr, 0x0, sizeof(MI_VDEC_ChnAttr_t));
      
          s32Ret = MI_VDEC_CreateDev(VdecDev, &stInitParam);
          if(MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_CreateDev failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          VdecChn = 0;
          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_INPLACE_ONE_BUF;
          stChnAttr.stVdecVideoAttr.u32RefFrameNum = 1;
          stChnAttr.u32Priority = 0;
          stChnAttr.stVdecVideoAttr.stErrHandlePolicy.bUseCusPolicy = FALSE;
          stChnAttr.stVdecVideoAttr.bDisableLowLatency = FALSE;
      
          s32Ret = MI_VDEC_CreateChn(VdecDev, VdecChn, &stChnAttr);
          if(MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_CreateChn failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          return MI_SUCCESS;
      }
      

    2.2. MI_VDEC_DestroyDev

    • 功能

      销毁解码设备。

    • 定义

      MI_S32 MI_VDEC_DestroyDev(MI_VDEC_DEV VdecDev);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 设备号不能超出最大的设备号范围;

      • 该接口调用需与MI_VDEC_CreateDev的调用行为保持一致,若选择调用该接口,则必须在销毁所有解码通道后调用;如果用户未主动销毁所有解码通道,则该接口内部会做销毁所有解码通道的处理;

      • 若解码设备已销毁后,再重复调用该接口,则会返回设备未初始化的错误码MI_ERR_VDEC_NOT_INIT。

    • 举例

      MI_S32 StopVdec(void)
      {
          MI_S32 s32Ret = MI_ERR_VDEC_FAILED;
          MI_VDEC_DEV VdecDev = 0;
          MI_VDEC_CHN VdecChn = 0;
      
          s32Ret = MI_VDEC_DestroyChn(VdecDev, VdecChn);
          if(MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_DestroyChn failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          //Confirm that you have destroyed all channels
          s32Ret = MI_VDEC_DestroyDev(VdecDev);
          if(MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_DestroyDev failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          return MI_SUCCESS;
      }
      

    2.3. MI_VDEC_CreateChn

    • 功能

      创建视频解码通道。

    • 定义

      MI_S32 MI_VDEC_CreateChn(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_VDEC_ChnAttr_t *pstChnAttr);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      pstChnAttr 解码通道属性指针,数据类型:MI_VDEC_ChnAttr_t 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 通道号不能超出最大的通道号范围。

      • 创建解码通道前,需要保证解码通道未创建或者已销毁,否则会返回错误码MI_ERR_VDEC_CHN_EXIST。

      • 如果设置eDpbBufMode为E_MI_VDEC_DPB_MODE_INPLACE_ONE_BUF模式或者E_MI_VDEC_DPB_MODE_INPLACE_TWO_BUF模式,解码器只保证支持正常解码SGS编码器编出的码流,对第三方编码器编出的码流不保证完全支持,且码流的MV(Motion Vector)的垂直分量不可超过256。另外,eDpbBufMode要与待解码的码流参考帧个数一致。

      • 对于CHIP:ifackel,不支持设置eDpbBufMode。

      • 对于CHIP:mHera,eDpbBufMode为E_MI_VDEC_DPB_MODE_INPLACE_ONE_BUF模式或者E_MI_VDEC_DPB_MODE_INPLACE_TWO_BUF模式下不支持解码H265开启多tile划分(图像参数集PPS语法中tiles_enabled_flag为1)的码流。

      • 如果需要解码B帧码流,则需要设置bDisableLowLatency为TRUE,以保证解码器按显示顺序输出解码后的图像;否则,输出的图像会有抖动,不连贯的问题。注意:芯片ifackel不支持bDisableLowLatency设置为TRUE。

    • 举例

      MI_S32 StartVdec(void)
      {
          MI_S32 s32Ret = MI_ERR_VDEC_FAILED;
          MI_VDEC_DEV VdecDev = 0;
          MI_VDEC_CHN VdecChn = 0;
          MI_U8 u8PortId = 0;
          MI_VDEC_DisplayMode_e eDisplayMode = E_MI_VDEC_DISPLAY_MODE_MAX;
          MI_VDEC_ChnAttr_t stChnAttr;
          MI_VDEC_OutputPortAttr_t stOutputPortAttr;
          MI_VDEC_ChnParam_t  stVdecChnParam;
      
          memset(&stChnAttr, 0x0, sizeof(MI_VDEC_ChnAttr_t));
          memset(&stOutputPortAttr, 0x0, sizeof(MI_VDEC_OutputPortAttr_t));
          memset(&stVdecChnParam, 0x0, sizeof(MI_VDEC_ChnParam_t));
      
          VdecChn = 0;
          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_INPLACE_ONE_BUF;
          stChnAttr.stVdecVideoAttr.u32RefFrameNum = 1;
          stChnAttr.u32Priority = 0;
          stChnAttr.stVdecVideoAttr.stErrHandlePolicy.bUseCusPolicy = FALSE;
          stChnAttr.stVdecVideoAttr.bDisableLowLatency = FALSE;
      
          s32Ret = MI_VDEC_CreateChn(VdecDev, VdecChn, &stChnAttr);
          if(MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_CreateChn failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          eDisplayMode = E_MI_VDEC_DISPLAY_MODE_PLAYBACK;
          s32Ret = MI_VDEC_SetDisplayMode (VdecDev, VdecChn, eDisplayMode);
          if(MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_SetDisplayMode failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          s32Ret = MI_VDEC_StartChn(VdecDev, VdecChn);
          if(MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_StartChn failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          stOutputPortAttr.u16Width = 640;
          stOutputPortAttr.u16Height = 480;
          s32Ret = MI_VDEC_SetOutputPortAttr(VdecDev, VdecChn, u8PortId, &stOutputPortAttr);
          if(MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_SetOutputPortAttr failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          stCropCfg.bEnable   = TRUE;
          stCropCfg.stRect.u16X  = 0;
          stCropCfg.stRect.u16Y  = 0;
          stCropCfg.stRect.u16Width = 720;
          stCropCfg.stRect.u16Height = 576;
          s32Ret = MI_VDEC_SetDestCrop(VdecDev, VdecChn, u8PortId, &stCropCfg);
          if(MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_SetDestCrop failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          stVdecChnParam.eDecMode = E_MI_VDEC_DECODE_MODE_I;
          s32Ret = MI_VDEC_SetChnParam(VdecDev, VdecChn, &stVdecChnParam);
          if(MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_SetChnParam failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          return MI_SUCCESS;
      }
      

    2.4. MI_VDEC_DestroyChn

    • 功能

      销毁视频解码通道。

    • 定义

      MI_S32 MI_VDEC_DestroyChn(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 销毁解码通道前必须保证通道已创建,否则会返回通道未创建的错误码MI_ERR_VDEC_CHN_UNEXIST。

      • 销毁解码通道前需要先停止解码,否则会返回通道未停止解码的错误码MI_ERR_VDEC_CHN_NOT_STOP。

    • 举例

      MI_S32 StopVdec(void)
      {
          MI_S32 s32Ret = MI_ERR_VDEC_FAILED;
          MI_VDEC_DEV VdecDev = 0;
          MI_VDEC_CHN VdecChn = 0;
      
          // Destroy send stream thread
          ...
      
          s32Ret = MI_VDEC_StopChn(VdecDev, VdecChn);
          if(MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_StopChn failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          s32Ret = MI_VDEC_DestroyChn(VdecDev, VdecChn);
          if(MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_DestroyChn failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          return MI_SUCCESS;
      }
      

    2.5. MI_VDEC_StartChn

    • 功能

      开始通道解码。

    • 定义

      MI_S32 MI_VDEC_StartChn(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 开始通道解码前必须保证通道已创建,否则会返回通道未创建的错误码MI_ERR_VDEC_CHN_UNEXIST。

      • 开始通道解码之后,才能调用 MI_VDEC_SendStream 发送码流成功。

      • 重复调用该接口时,会返回通道未停止解码的错误码MI_ERR_VDEC_CHN_NOT_STOP。

    • 举例

      请参见MI_VDEC_CreateChn的举例。


    2.6. MI_VDEC_StopChn

    • 功能

      停止通道解码。

    • 定义

      MI_S32 MI_VDEC_StopChn(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 调用该接口时,需要保证通道已创建,否则会报通道未创建的错误码MI_ERR_VDEC_CHN_UNEXIST。

      • 调用该接口时,需要保证通道已使能,否则会报通道未使能的错误码MI_ERR_VDEC_CHN_NOT_START。

      • 调用此接口后,调用发送码流的接口 MI_VDEC_SendStream 会返回失败。

      • 重复调用该接口时,会返回通道未开始解码的错误码MI_ERR_VDEC_CHN_NOT_START。

      • 解码B帧时,如果MI_VDEC后级绑定了MI_DISP模块,则在MI_VDEC停止通道解码前,需要保证MI_DISP模块先退出;否则,MI_VDEC退出时,会直接释放输出buffer,而MI_DISP此时还在访问MI_VDEC的输出buffer,会引起踩内存等问题;如果MI_VDEC在退出时,发现有buffer未还回,会报错MI_ERR_VDEC_BUSY。

    • 举例

      请参见MI_VDEC_DestroyChn的举例。


    2.7. MI_VDEC_GetChnAttr

    • 功能

      获取视频解码通道属性。

    • 定义

      MI_S32 MI_VDEC_GetChnAttr(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_VDEC_ChnAttr_t *pstChnAttr);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      pstChnAttr 解码通道属性指针。参数类型:MI_VDEC_ChnAttr_t 输出
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 获取通道属性前必须保证通道已创建,否则会返回通道未创建的错误码MI_ERR_VDEC_CHN_UNEXIST。

    2.8. MI_VDEC_GetChnStat

    • 功能

      查询解码通道状态。

    • 定义

      MI_S32 MI_VDEC_GetChnStat(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_VDEC_ChnStat_t *pstChnStat);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      pstChnStat 解码通道状态结构体指针。 输出
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 查询解码通道状态前必须保证通道已创建,否则会返回通道未创建的错误码MI_ERR_VDEC_CHN_UNEXIST。
    • 举例

      请参见MI_VDEC_SendStream的举例。


    2.9. MI_VDEC_FlushChn

    • 功能

      清理解码通道缓存数据。

    • 定义

      MI_S32 MI_VDEC_FlushChn(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 该接口可用于解码过程中,切换到其他GOP时,清理解码通道缓存的数据,从而使解码继续进行。

    2.10. MI_VDEC_ResetChn

    • 功能

      复位解码通道。

    • 定义

      MI_S32 MI_VDEC_ResetChn(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 该接口暂不支持。

    2.11. MI_VDEC_SetChnParam

    • 功能

      设置解码通道参数。

    • 定义

      MI_S32 MI_VDEC_SetChnParam(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_VDEC_ChnParam_t *pstChnParam);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      pstChnParam 通道参数。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 若通道未创建,则返回错误码MI_ERR_VDEC_CHN_UNEXIST。

      • 通道参数只支持设置结构体MI_VDEC_ChnParam_t的成员eDecMode,其他成员设置无效。

    • 举例

      请参见MI_VDEC_CreateChn的举例。


    2.12. MI_VDEC_GetChnParam

    • 功能

      获取解码通道参数。

    • 定义

      MI_S32 MI_VDEC_GetChnParam(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_VDEC_ChnParam_t *pstChnParam);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      pstChnParam 通道参数。 输出
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 该接口暂不支持。

    2.13. MI_VDEC_SendStream

    • 功能

      向解码通道发送码流数据。

    • 定义

      MI_S32 MI_VDEC_SendStream(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_VDEC_VideoStream_t *pstVideoStream, MI_S32 s32MilliSec);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      pstVideoStream 解码码流数据指针。参考MI_VDEC_VideoStream_t定义。 输入
      s32MilliSec 设定推送数据超时时间参数。取值范围: -1:阻塞。 0:非阻塞。 正值:超时时间,单位为毫秒。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 暂不支持按流发送。

      • 按帧传送时,每次需完整传送一帧数据。

      • 若用户在送流时,设置pstVideoStream->u64PTS = -2, 则在解码后,VDEC会丢弃该帧。用户可根据需要进行设置。

    • 举例

      每次传送完整一帧数据。以帧为单位,如果当前数据帧传送失败,需要重新传送。

      MI_S32 VdecSendStream(void)
      {
          MI_S32 s32Ret = MI_ERR_VDEC_FAILED;
          MI_VDEC_DEV VdecDev = 0;
          MI_VDEC_CHN VdecChn = 0;
          MI_S32 s32MilliSec = 0;
          MI_VDEC_VideoStream_t stVideoStream;
          MI_VDEC_ChnAttr_t stChnAttr;
          MI_VDEC_ChnStat_t stChnStat;
      
          do{
              //Check if you need stop sending stream
              if(bStop)
              {
                  break;
              }
      
              memset(&stChnAttr, 0x0, sizeof(MI_VDEC_ChnAttr_t));
              s32Ret = MI_VDEC_GetChnAttr(VdecDev, VdecChn, &stChnAttr);
              if(MI_SUCCESS != s32Ret)
              {
                  printf("MI_VDEC_GetChnAttr failed, s32Ret: 0x%x.\n", s32Ret);
                  return s32Ret;
              }
      
              memset(&stChnStat, 0x0, sizeof(MI_VDEC_ChnStat_t));
              s32Ret = MI_VDEC_GetChnStat(VdecDev, VdecChn, &stChnStat);
              if(MI_SUCCESS != s32Ret)
              {
                  printf("MI_VDEC_GetChnStat failed, s32Ret: 0x%x.\n", s32Ret);
                  return s32Ret;
              }
      
              //suggest to check chn status
              if(stChnAttr.u32Bufsize - stChnStat.u32LeftStreamBytes < u32StreamSize)
              {
                  continue;
              }
      
              memset(&stVideoStream, 0x0, sizeof(MI_VDEC_VideoStream_t));
              stVideoStream.pu8Addr = pu8StreamBuf;
              stVideoStream.u32Len  = u32StreamSize;
              stVideoStream.u64PTS  = u64StreamPts;
              stVideoStream.bEndOfFrame  = TRUE;
              stVideoStream.bEndOfStream = FALSE;
              s32MilliSec = 0;                    //0ms
              s32Ret = MI_VDEC_SendStream(VdecDev, VdecChn, &stVideoStream, s32MilliSec);
              if(MI_SUCCESS != s32Ret)
              {
                  printf("MI_VDEC_SendStream failed, s32Ret: 0x%x.\n", s32Ret);
                  continue;
              }
          }while(!ShouldStop);
      
          return MI_SUCCESS;
      }
      

    2.14. MI_VDEC_PauseChn

    • 功能

      暂停通道解码。

    • 定义

      MI_S32 MI_VDEC_PauseChn(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 调用该接口后,解码器暂停解码;此时,上层可以继续调用MI_VDEC_SendStream接口送流,但是码流buffer满时,MI_VDEC_SendStream会返回错误码MI_ERR_VDEC_BUF_FULL。

      • 该接口可以重复调用,不会报错。

      • 芯片ifackel不支持该接口。

    • 举例

      MI_S32 PauseChn(void)
      {
          MI_S32 s32Ret = MI_ERR_VDEC_FAILED;
          MI_VDEC_DEV VdecDev  = 0;
          MI_VDEC_CHN VdecChn  = 0;
          MI_U32 u32RefreshCnt = 0;
      
          //While decoding...
      
          s32Ret = MI_VDEC_PauseChn(VdecDev, VdecChn);
          if (MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_PauseChn failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          //refresh 10 times
          while (u32RefreshCnt < 10)
          {
              s32Ret = MI_VDEC_RefreshChn(VdecDev, VdecChn);
              if(MI_SUCCESS != s32Ret)
              {
                  printf("MI_VDEC_RefreshChn failed, s32Ret: 0x%x.\n", s32Ret);
                  break;
              }
              u32RefreshCnt ++;
              usleep(100*1000);
          }
      
          s32Ret = MI_VDEC_ResumeChn(VdecDev, VdecChn);
          if (MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_ResumeChn failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
          return MI_SUCCESS;
      }
      

    2.15. MI_VDEC_RefreshChn

    • 功能

      刷新通道,再次解码当前帧。

    • 定义

      MI_S32 MI_VDEC_RefreshChn(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 调用该接口时,需要保证已调用MI_VDEC_PauseChn停止解码,否则会报错误码MI_ERR_VDEC_NOT_DISABLE。

      • 每调用一次该接口,会触发解码器再次解码当前帧;可以多次调用,同时可以配合MI_VDEC_SetOutputPortAttr调整缩放倍数,以适应不同的场景需求。

      • 用户在调用该接口时,需要保证码流buffer中还有待解码的数据,否则不能完成refresh动作。

      • 用户连续多次调用该接口时,如果上一次的refresh或step task未完成,则接口会返回错误码MI_ERR_VDEC_BUSY。

      • 解码B帧时,不支持此功能。

      • 芯片ifackel不支持该接口。

    • 举例

      请参见MI_VDEC_PauseChnMI_VDEC_StepChn的举例。

      实现暂停时电子放大与抓图功能。

      常见应用场景举例:假设MI_DISP在预览模式下输出分辨率为1920x1080,4通道都为1080P的源码流同时解码预览时,每个通道输出分辨率设置为960x540输出显示。如果暂停解码,然后将通道2切换至全屏预览,MI_DISP会将960x540的图像拉伸至1920x1080全屏显示,此时图像数据会失真。此时可以通过调用MI_VDEC_RefreshChn获取到当前暂停的数据帧的1920x1080的图像进行无失真显示输出。

      通道要实现暂停电子放大功能,依赖于 MI_VDEC_PauseChnMI_VDEC_RefreshChnMI_VDEC_ResumeChn以及MI_VDEC_SendStream组合,目的是为相同的码流数据帧能获得不同分辨率的图像的功能,如下,图像3需要重复输出4次。

      API组合调用时序:

      1. 调用MI_VDEC_SendStream推送数据帧‘1’和‘2’的码流数据。

      2. 调用MI_VDEC_PauseChn暂停解码器,进入解码输出重复图像帧模式。

      3. 调用MI_VDEC_SendStream推送需要重复输出图像‘3’的码流数据到解码器。

      4. 重复调用MI_VDEC_RefreshChn,重复输出图像‘3’,每调用1次将输出1帧图像,调用次数无限制。当前示例调用4次。

      5. 调用MI_VDEC_ResumeChn退出重复解码相同图像帧模式。

      6. 调用MI_VDEC_SendStream推送数据帧‘4’和‘5’的码流数据。


    2.16. MI_VDEC_ResumeChn

    • 功能

      恢复通道解码。

    • 定义

      MI_S32 MI_VDEC_ResumeChn(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 调用该接口时,需要保证通道已创建,否则会报通道未创建的错误码MI_ERR_VDEC_CHN_UNEXIST。

      • 调用该接口时,需要保证通道已使能,否则会报通道未使能的错误码MI_ERR_VDEC_CHN_NOT_START。

      • 允许重复调用该接口。

      • 调用该接口时,如果还有refresh或step task未完成,则接口会返回错误码MI_ERR_VDEC_BUSY。

      • 芯片ifackel不支持该接口。

    • 举例

      请参见MI_VDEC_PauseChnMI_VDEC_StepChn的举例。


    2.17. MI_VDEC_StepChn

    • 功能

      通道单帧解码。

    • 定义

      MI_S32 MI_VDEC_StepChn(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 每调用一次该接口,会触发解码器解码下一帧;可以多次调用,同时可以配合MI_VDEC_SetOutputPortAttr调整缩放倍数,以适应不同的场景需求。

      • 用户在调用该接口时,需要保证码流buffer中还有待解码的数据,否则不能完成step动作。

      • 用户连续多次调用该接口时,如果上一次的refresh或step task未完成,则接口会返回错误码MI_ERR_VDEC_BUSY。

      • 芯片ifackel不支持该接口。

    • 举例

      Case 1:

      MI_S32 StepChn(void)
      {
          MI_S32 s32Ret = MI_ERR_VDEC_FAILED;
          MI_VDEC_DEV VdecDev  = 0;
          MI_VDEC_CHN VdecChn  = 0;
      
          //While decoding...
      
          s32Ret = MI_VDEC_PauseChn(VdecDev, VdecChn);
          if (MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_PauseChn failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          /// 此处送流过程也可以用另起独立的线程调用MI_VDEC_SendStream 替代
          s32Ret = MI_VDEC_SendStream(VdecDev, VdecChn, &stVdecStream, 0);
          if(MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_ SendStream failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          s32Ret = MI_VDEC_StepChn(VdecDev, VdecChn);
          if(MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_StepChn failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
          usleep(20*1000);
      
          s32Ret = MI_VDEC_ResumeChn(VdecDev, VdecChn);
          if (MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_ResumeChn failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
          return MI_SUCCESS;
      }
      

      Case 2:

      MI_S32 refresh_and_step_chn(void)
      {
          MI_S32 s32Ret = MI_ERR_VDEC_FAILED;
          MI_VDEC_DEV VdecDev  = 0;
          MI_VDEC_CHN VdecChn  = 0;
          MI_U32 u32LoopCnt = 0;
      
          //While decoding...
      
          s32Ret = MI_VDEC_PauseChn(VdecDev, VdecChn);
          if (MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_PauseChn failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          /// 此处送流过程也可以用另起独立的线程调用MI_VDEC_SendStream 替代
          s32Ret = MI_VDEC_SendStream(VdecDev, VdecChn, &stVdecStream, 0);
          if(MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_ SendStream failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          /*Loop 10 times*/
          While(u32LoopCnt < 10)
          {
              s32Ret = MI_VDEC_RefreshChn(VdecDev, VdecChn);
              if(MI_SUCCESS != s32Ret)
              {
                  printf("MI_VDEC_RefreshChn failed, s32Ret: 0x%x.\n", s32Ret);
                  return s32Ret;
              }
              usleep(20*1000);
      
              /// 此处送流过程也可以用另起独立的线程调用MI_VDEC_SendStream 替代
              s32Ret = MI_VDEC_SendStream(VdecDev, VdecChn, &stVdecStream, 0);
              if(MI_SUCCESS != s32Ret)
              {
                  printf("MI_VDEC_ SendStream failed, s32Ret: 0x%x.\n", s32Ret);
                  return s32Ret;
              }
      
              s32Ret = MI_VDEC_StepChn(VdecDev, VdecChn);
              if(MI_SUCCESS != s32Ret)
              {
                  printf("MI_VDEC_StepChn failed, s32Ret: 0x%x.\n", s32Ret);
                  return s32Ret;
              }
              usleep(20*1000);
              u32LoopCnt ++;
          }
      
          s32Ret = MI_VDEC_ResumeChn(VdecDev, VdecChn);
          if (MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_ResumeChn failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
          return MI_SUCCESS;
      }
      

    2.18. MI_VDEC_GetUserData

    • 功能

      获取解码通道的用户数据。

    • 定义

      MI_S32 MI_VDEC_GetUserData(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_VDEC_UserData_t *pstUserData, MI_S32 s32MilliSec);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      s32MilliSec 获取用户数据超时定义。取值范围: -1:阻塞。 0:非阻塞。 正值:推送数据超时时间,以 毫秒为单位。 输入
      pstUserData 获取的解码用户数据,参考MI_VDEC_UserData_t定义 输出
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 该接口暂不支持。

    2.19. MI_VDEC_ReleaseUserData

    • 功能

      释放用户数据。

    • 定义

      MI_S32 MI_VDEC_ReleaseUserData(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_VDEC_UserData_t * pstUserData);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      pstUserData 解码后的用户数据指针,由MI_VDEC_GetUserData接口获取。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 该接口暂不支持。

    2.20. MI_VDEC_SetDisplayMode

    • 功能

      设置显示模式。

    • 定义

      MI_S32 MI_VDEC_SetDisplayMode(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn,  MI_VDEC_DisplayMode_e eDisplayMode);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      eDisplayMode 显示模式枚举。参考MI_VDEC_DisplayMode_e定义。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 设置显示模式前必须保证通道已创建,否则会返回通道未创建的错误码MI_ERR_VDEC_CHN_UNEXIST。

      • 帧率控制机制优化后,MI_VDEC无需丢帧,因此该接口目前设置无效。

      • 预览模式(E_MI_VDEC_DISPLAY_MODE_PREVIEW):为了保持解码图像预览的实时性,MI_VDEC会在帧堆积到一定程度时,立刻丢弃解码后的图像,以快速清理码流buffer中堆积的数据,保证对实时接收到的码流立刻进行解码。

      • 回放模式(E_MI_VDEC_DISPLAY_MODE_PLAYBACK):为了保持解码图像的连贯性,MI_VDEC在解码过程中,即使出现了帧堆积的现象,也不会丢弃解码后的图像,避免显示图像卡顿,不连贯。

    • 举例

      请参见MI_VDEC_CreateChn的举例。


    2.21. MI_VDEC_GetDisplayMode

    • 功能

      获取显示模式。

    • 定义

      MI_S32 MI_VDEC_GetDisplayMode(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_VDEC_DisplayMode_e *peDisplayMode);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      peDisplayMode 显示模式枚举指针,参考MI_VDEC_DisplayMode_e定义。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 获取显示模式前必须保证通道已创建,否则会返回通道未创建的错误码MI_ERR_VDEC_CHN_UNEXIST。

    2.22. MI_VDEC_SetOutputPortAttr

    • 功能

      设置解码通道输出端口属性。

    • 定义

      MI_S32 MI_VDEC_SetOutputPortAttr(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_U8 u8PortId, MI_VDEC_OutputPortAttr_t *pstOutputPortAttr);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      u8PortId 解码输出port ID。 取值范围:mHera芯片为[0,3),其余芯片仅支持设置为0。 输入
      pstOutputPortAttr 输出端口属性,数据类型:MI_VDEC_OutputPortAttr_t 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 若通道未创建,则返回错误码MI_ERR_VDEC_CHN_UNEXIST。

      • 缩放宽和高需要按2对齐。

      • mHera芯片的缩放范围为[1/32, 1],其余支持缩放功能的芯片缩放范围为[⅛, 1]。

      • 不支持放大。

      • 若裁剪和缩放同时开启,则缩放宽和高不能大于裁剪的宽和高。

      • 芯片ifackel不支持缩放功能。

    • 举例

      请参见MI_VDEC_CreateChn的举例。


    2.23. MI_VDEC_GetOutputPortAttr

    • 功能

      获取解码通道输出端口属性。

    • 定义

      MI_S32 MI_VDEC_GetOutputPortAttr(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_U8 u8PortId, MI_VDEC_OutputPortAttr_t *pstOutputPortAttr);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 视频解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      u8PortId 解码输出port ID。 取值范围:mHera芯片为[0,3),其余芯片仅支持设置为0。 输入
      pstOutputPortAttr 输出端口属性,数据类型:MI_VDEC_OutputPortAttr_t 输出
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 若通道未创建,则返回错误码MI_ERR_VDEC_CHN_UNEXIST

    2.24. MI_VDEC_SetOutputPortLayoutMode

    • 功能

      设置输出端口Buffer模式。

    • 定义

      MI_S32 MI_VDEC_SetOutputPortLayoutMode(MI_VDEC_DEV VdecDev, MI_VDEC_OutbufLayoutMode_e eBufTileMode);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      eBufTileMode 输出Buffer模式,数据类型:MI_VDEC_OutbufLayoutMode_e 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 若设备未初始化,则返回错误码MI_ERR_VDEC_NOT_INIT。

      • 该接口需要在开始解码前调用,否则会报系统忙的错误码MI_ERR_VDEC_BUSY。

      • ifackel只支持设置eBufTileMode = E_MI_VDEC_OUTBUF_LAYOUT_TILE;mHera只支持设置eBufTileMode = E_MI_VDEC_OUTBUF_LAYOUT_LINEAR。

    • 举例

      MI_S32 StartVdec(void)
      {
          MI_S32 s32Ret = MI_ERR_VDEC_FAILED;
          MI_VDEC_DEV VdecDev = 0;
          MI_VDEC_CHN VdecChn = 0;
          MI_VDEC_OutbufLayoutMode_e eBufTileMode = E_MI_VDEC_OUTBUF_LAYOUT_MAX;
          MI_VDEC_ChnAttr_t stChnAttr;
      
          memset(&stChnAttr, 0x0, sizeof(MI_VDEC_ChnAttr_t));
      
          eBufTileMode = E_MI_VDEC_OUTBUF_LAYOUT_AUTO;
          s32Ret = MI_VDEC_SetOutputPortLayoutMode(VdecDev, eBufTileMode) ;
          if(MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_SetOutputPortLayoutMode failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          VdecChn = 0;
          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_INPLACE_ONE_BUF;
          stChnAttr.stVdecVideoAttr.u32RefFrameNum = 1;
          stChnAttr.u32Priority = 0;
      
          s32Ret = MI_VDEC_CreateChn(VdecDev, VdecChn, &stChnAttr);
          if(MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_CreateChn failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          return MI_SUCCESS;
      }
      

    2.25. MI_VDEC_GetOutputPortLayoutMode

    • 功能

      获取输出端口Buffer模式。

    • 定义

      MI_S32 MI_VDEC_GetOutputPortLayoutMode(MI_VDEC_DEV VdecDev, MI_VDEC_OutbufLayoutMode_e *peBufTileMode);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      eBufTileMode 输出Buffer模式,数据类型:MI_VDEC_OutbufLayoutMode_e 输出
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 若设备未初始化,则返回错误码MI_ERR_VDEC_NOT_INIT

    2.26. MI_VDEC_SetDestCrop

    • 功能

      设置解码通道裁剪属性。

    • 定义

      MI_S32 MI_VDEC_SetDestCrop(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_U8 u8PortId, MI_VDEC_CropCfg_t *pstCropCfg);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      u8PortId 解码输出port ID。 取值范围:mHera芯片为[0,3),其余芯片仅支持设置为0。 输入
      pstCropCfg 解码通道裁剪属性指针,数据类型:MI_VDEC_CropCfg_t 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 裁剪设置的坐标X和宽需要按一定长度对齐(芯片mHera为按2对齐,其余支持裁剪功能的芯片按16对齐),坐标Y和高需要按2对齐;

      • 若通道未创建,则返回错误码MI_ERR_VDEC_CHN_UNEXIST;

      • 若裁剪和缩放同时开启,则裁剪宽和高不能小于缩放的宽和高。

      • 芯片ifackel不支持裁剪功能。

    • 举例

      请参见MI_VDEC_CreateChn的举例。


    2.27. MI_VDEC_GetDestCrop

    • 功能

      获取解码通道裁剪属性。

    • 定义

      MI_S32 MI_VDEC_GetDestCrop(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_U8 u8PortId, MI_VDEC_CropCfg_t *pstCropCfg);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      u8PortId 解码输出port ID。 取值范围:mHera芯片为[0,3),其余芯片仅支持设置为0。 输入
      pstCropCfg 解码通道裁剪属性指针,数据类型:MI_VDEC_CropCfg_t 输出
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 若通道未创建,则返回错误码MI_ERR_VDEC_CHN_UNEXIST;

    2.28. MI_VDEC_SetChnErrHandlePolicy

    • 功能

      设置解码通道错误宏块的数据帧的输出策略。

    • 定义

      MI_S32 MI_VDEC_SetChnErrHandlePolicy(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_VDEC_ErrHandlePolicy_t *pstErrHandlePolicy);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      pstErrHandlePolicy 设置错误宏块的数据帧的输出策略,参考MI_VDEC_ErrHandlePolicy_t定义。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 若通道未创建,则返回错误码MI_ERR_VDEC_CHN_UNEXIST。

      • 芯片ifackel暂不支持该接口。


    2.29. MI_VDEC_GetEventFd

    • 功能

      获取指定通道对应的设备文件句柄,用于调用poll监听是否有event信息。

    • 语法

      MI_S32 MI_VDEC_GetEventFd(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
    • 返回值

      • -1:失败,无效的句柄。

      • 非负值:成功,通道句柄。

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 若成功创建句柄,需要通过MI_VDEC_CloseEventFd(#230-mi_vdec_closeeventfd)关闭相应句柄。
    • 举例

      static MI_S32 g_s32EvtFd = -1;
      static MI_S32 g_s32DevId = -1;
      static MI_S32 g_s32ChnId = -1;
      static MI_U8  g_u8PortId = 0;
      
      void GetEventFd(MI_S32 s32DevId, MI_S32 s32ChnId)
      {
          g_s32EvtFd = MI_VDEC_GetEventFd(s32DevId, s32ChnId);
          g_s32DevId = s32DevId;
          g_s32ChnId = s32ChnId;
      }
      
      void SubscribeEvent(void)
      {
          MI_VDEC_SubscribeEvent(g_s32DevId, g_s32ChnId, E_MI_VDEC_EVENT_SEQCHANGE);
          MI_VDEC_SubscribeEvent(g_s32DevId, g_s32ChnId, E_MI_VDEC_EVENT_EOS);
          MI_VDEC_SubscribeEvent(g_s32DevId, g_s32ChnId, E_MI_VDEC_EVENT_DECERR);
          MI_VDEC_SubscribeEvent(g_s32DevId, g_s32ChnId, E_MI_VDEC_EVENT_FRAME_DROPPED);
      }
      
      void HandleResolutionChangeEvent(void)
      {
          MI_VDEC_EventData_t stEventInfo;
          MI_VDEC_OutputPortAttr_t stOutputPortAttr;
      
          memset(&stEventInfo, 0x0, sizeof(MI_VDEC_EventData_t));
          MI_VDEC_GetEventData(g_s32DevId, g_s32ChnId, E_MI_VDEC_EVENT_SEQCHANGE, &stEventInfo);
      
          memset(&stOutputPortAttr, 0x0, sizeof(MI_VDEC_OutputPortAttr_t));
          stOutputPortAttr.u16Width  = stEventInfo.value.stSeqChgEvtInfo.u16PicWidth / 4;
          stOutputPortAttr.u16Height = stEventInfo.value.stSeqChgEvtInfo.u16PicHeight / 4;
          MI_VDEC_SetOutputPortAttr(g_s32DevId, g_s32ChnId, g_u8PortId, &stOutputPortAttr);
      
          // need to clear event
          MI_VDEC_ClearEvents(g_s32DevId, g_s32ChnId, 1 << E_MI_VDEC_EVENT_SEQCHANGE);
      }
      
      void HandleEndOfSttreamEvent(void)
      {
          MI_VDEC_EventData_t stEventInfo;
          MI_VDEC_OutputPortAttr_t stOutputPortAttr;
      
          memset(&stEventInfo, 0x0, sizeof(MI_VDEC_EventData_t));
          MI_VDEC_GetEventData(g_s32DevId, g_s32ChnId, E_MI_VDEC_EVENT_EOS, &stEventInfo);
      
          if (stEventInfo.value.stDecEosEvtInfo.bAbnormal)
          {
          }
      
          // need to clear event
          MI_VDEC_ClearEvents(g_s32DevId, g_s32ChnId, 1 << E_MI_VDEC_EVENT_EOS);
      }
      
      void HandleFrameDecErrorEvent(void)
      {
          MI_VDEC_EventData_t stEventInfo;
          MI_VDEC_OutputPortAttr_t stOutputPortAttr;
      
          memset(&stEventInfo, 0x0, sizeof(MI_VDEC_EventData_t));
          MI_VDEC_GetEventData(g_s32DevId, g_s32ChnId, E_MI_VDEC_EVENT_DECERR, &stEventInfo);
      
          if (stEventInfo.value.stDecErrEvtInfo.eErrCode == E_MI_VDEC_ERR_CODE_OUT_OF_MEMORY)
          {
              // handle no more memory error
          }
      
          // need to clear event
          MI_VDEC_ClearEvents(g_s32DevId, g_s32ChnId, 1 << E_MI_VDEC_EVENT_DECERR);
      }
      
      void HandleFrameDroppedEvent(void)
      {
          MI_VDEC_EventData_t stEventInfo;
          MI_VDEC_OutputPortAttr_t stOutputPortAttr;
      
          memset(&stEventInfo, 0x0, sizeof(MI_VDEC_EventData_t));
          MI_VDEC_GetEventData(g_s32DevId, g_s32ChnId, E_MI_VDEC_EVENT_FRAME_DROPPED, &stEventInfo);
      
          if (stEventInfo.value.stFrameDroppedEvtInfo.u8FrameDroppedCnt > 0)
          {
      
          }
      
          // need to clear event
          MI_VDEC_ClearEvents(g_s32DevId, g_s32ChnId, 1 << E_MI_VDEC_EVENT_FRAME_DROPPED);
      }
      
      MI_BOOL GetEvent(MI_U64 *pu64GetEvent)
      {
          // 15 ms
          MI_S32 s32Timeout = 15;
          struct pollfd pollFd[1];
      
          memset(pollFd, 0x0, sizeof(pollFd));
          // seq chage and other vdec event
          pollFd[0].fd = g_s32EvtFd;
          pollFd[0].events = POLLIN | POLLPRI | POLLERR;
          *pu64GetEvent = 0ULL;
      
          // polling events and wait timeout util events signal
          if (0 >= poll((struct pollfd*)pollFd, 2, s32Timeout))
          {
              // timeout or poll error
              return FALSE;
          }
      
          // poll error
          if (pollFd[0].revents & POLLERR)
          {
              return FALSE;
          }
      
          if (pollFd[0].revents & (POLLPRI | POLLIN))
          {
              // has events
              MI_U64 u64Events = 0ULL;
      
              if (MI_SUCCESS != MI_VDEC_GetEvents(g_s32DevId, g_s32ChnId, &u64Events))
              {
                  // get event error
                  return FALSE;
              }
      
              // get seq change
              if (u64Events & (1 << E_MI_VDEC_EVENT_SEQCHANGE))
              {
                  HandleResolutionChangeEvent();
              }
      
              // get eos event
              if (u64Events & (1 << E_MI_VDEC_EVENT_EOS))
              {
                  HandleEndOfSttreamEvent();
              }
      
              // get decode error event
              if (u64Events & (1 << E_MI_VDEC_EVENT_DECERR))
              {
                  HandleFrameDecErrorEvent();
              }
      
              // get frame dropped event
              if (u64Events & (1 << E_MI_VDEC_EVENT_FRAME_DROPPED))
              {
                  HandleFrameDroppedEvent();
              }
      
              *pu64GetEvent = u64Events;
          }
      
          return TRUE;
      }
      
      void UnSubscribeEvent(void)
      {
          MI_VDEC_UnSubscribeEvent(g_s32DevId, g_s32ChnId, E_MI_VDEC_EVENT_SEQCHANGE);
          MI_VDEC_UnSubscribeEvent(g_s32DevId, g_s32ChnId, E_MI_VDEC_EVENT_EOS);
          MI_VDEC_UnSubscribeEvent(g_s32DevId, g_s32ChnId, E_MI_VDEC_EVENT_DECERR);
          MI_VDEC_UnSubscribeEvent(g_s32DevId, g_s32ChnId, E_MI_VDEC_EVENT_FRAME_DROPPED);
      }
      
      void CloseEventFd(void)
      {
          MI_VDEC_CloseEventFd(g_s32DevId, g_s32ChnId);
          g_s32EvtFd    = -1;
          g_s32DevId = -1;
          g_s32ChnId = -1;
      }
      

    2.30. MI_VDEC_CloseEventFd

    • 功能

      关闭指定通道句柄。

    • 语法

      MI_S32 MI_VDEC_CloseEventFd(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

    • 举例

      参考MI_VDEC_GetEventFd举例。


    2.31. MI_VDEC_SubscribeEvent

    • 功能

      开始监听通道指定事件信息。

    • 语法

      MI_S32 MI_VDEC_SubscribeEvent(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_VDEC_Event_e eEvent);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      eEvent 事件信息,参考MI_VDEC_Event_e定义。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 需要先调用MI_VDEC_CreateChn创建使能通道。

      • MI_VDEC_DestroyChn调用后会取消所有已监听的事件

      • 调用MI_VDEC_StopChn不会取消已监听的事件。

      • 如果有订阅监听E_MI_VDEC_EVENT_SEQCHANGE事件,那么发生E_MI_VDEC_EVENT_SEQCHANGE事件时,应用必须调用MI_VDEC_ClearEvents清除事件,否则会停止解码,直到调用MI_VDEC_ClearEvents清除E_MI_VDEC_EVENT_SEQCHANGE事件记录为止。

      • E_MI_VDEC_EVENT_DECERR事件只会保留最新的错误信息,如果没有及时通过MI_VDEC_GetEventData获取,将会被最新的错误信息所覆盖。

    • 举例

      参考MI_VDEC_GetEventFd举例。


    2.32. MI_VDEC_UnSubscribeEvent

    • 功能

      取消监听通道指定事件信息。

    • 语法

      MI_S32 MI_VDEC_UnSubscribeEvent(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_VDEC_Event_e eEvent);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      eEvent 事件信息,参考MI_VDEC_Event_e定义。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 需要先调用MI_VDEC_CreateChn创建使能通道。

      • MI_VDEC_DestroyChn调用后会取消所有已监听的事件

      • 调用MI_VDEC_StopChn不会取消已监听的事件。

    • 举例

      参考MI_VDEC_GetEventFd举例。


    2.33. MI_VDEC_GetEvents

    • 功能

      获取通道产生的所有的事件信息。

    • 语法

      MI_S32 MI_VDEC_GetEvents(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_U64 *pu64Events);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      pu64Events 返回所有已产生的事件信息。 输出
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 通过调用poll接口只能获取到有事件发生,但无法知道发生哪类事件信息。因此,需要使用当前接口获知通道有哪些事件信息产生。

      • 需要先调用MI_VDEC_StartChn成功使能通道。

    • 举例

      参考MI_VDEC_GetEventFd举例。


    2.34. MI_VDEC_GetEventData

    • 功能

      获取通道指定事件的详细信息。

    • 语法

      MI_S32 MI_VDEC_GetEventData(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_VDEC_Event_e eEvent, MI_VDEC_EventData_t *pstEvtData);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      eEvent 需要获取指定的事件信息,参考MI_VDEC_Event_e定义。 输入
      pstEvtData 返回的事件详细信息,参考MI_VDEC_EventData_t定义。 输出
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 只能取到指定的事件。如果有多类事情同时发生,需要多次调用分别获取。

      • 需要先调用MI_VDEC_StartChn成功使能通道。

    • 举例

      参考MI_VDEC_GetEventFd举例。


    2.35. MI_VDEC_ClearEvents

    • 功能

      清除通道产生的指定的事件信息。

    • 语法

      MI_S32 MI_VDEC_ClearEvents(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_U64 u64Events);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      u64Events 需要清除的指定的事件信息。 如果清除事件为E_MI_VDEC_EVENT_SEQCHANGE,那么参数u64Events需要设置为u64Events=1 << E_MI_VDEC_EVENT_SEQCHANGE。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 允许一次调用清除多个事件信息,如u64Events=(1 << E_MI_VDEC_EVENT_SEQCHANGE) |(1 << E_MI_VDEC_EVENT_EOS)。

      • 需要先调用MI_VDEC_StartChn成功使能通道。

    • 举例

      参考MI_VDEC_GetEventFd举例。


    2.36. MI_VDEC_SetChnRotate

    • 功能

      设置解码通道输出图像旋转角度。

    • 语法

      MI_S32 MI_VDEC_SetChnRotate(MI_VDEC_DEV VdecDev, MI_VDEC_CHN VdecChn, MI_U8 u8PortId, MI_VDEC_RotateConfig_t *pstRotateConfig);
      
    • 形参

      参数名称 描述 输入/输出
      VdecDev 解码设备号。 取值范围:[0, MI_VDEC_MAX_DEV_NUM)。 输入
      VdecChn 解码通道号。 取值范围:[0, MI_VDEC_MAX_CHN_ID)。 输入
      u8PortId 解码输出port ID。 取值范围:仅支持设置为0。 输入
      pstRotateConfig 旋转参数结构体指针,参考MI_VDEC_RotateConfig_t定义。 输入
    • 返回值

      • MI_SUCCESS:成功。

      • 非MI_SUCCESS:失败,详情参照错误码

    • 依赖

      • 头文件:mi_vdec.h、mi_vdec_datatype.h

      • 库文件:libmi_vdec.a/libmi_vdec.so

    • 注意

      • 若通道未创建,则返回错误码MI_ERR_VDEC_CHN_UNEXIST。

      • 目前支持旋转功能的芯片有:ifackel,且仅支持Port0。

    • 举例

      MI_S32 StartVdec(void)
      {
          MI_S32 s32Ret = MI_ERR_VDEC_FAILED;
          MI_VDEC_DEV VdecDev = 0;
          MI_VDEC_CHN VdecChn = 0;
          MI_U8 u8PortId = 0;
          MI_VDEC_RotateConfig_t stRotateCfg;
      
          memset(&stChnAttr, 0x0, sizeof(MI_VDEC_ChnAttr_t));
          stChnAttr.eCodecType = E_MI_VDEC_CODEC_TYPE_H264;
          stChnAttr.eVideoMode = E_MI_VDEC_VIDEO_MODE_FRAME;
          stChnAttr.u32BufSize = 1024*1024;
      
          s32Ret = MI_VDEC_CreateChn(VdecDev, VdecChn, &stChnAttr);
          if (MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_CreateChn failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          s32Ret = MI_VDEC_StartChn(VdecDev, VdecChn);
          if (MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_StartChn failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          stRotateCfg.eRotateMode = E_MI_SYS_ROTATE_90; // set rotate angle to 90°
          s32Ret = MI_VDEC_SetChnRotate(VdecDev, VdecChn, u8PortId, &stRotateCfg);
          if (MI_SUCCESS != s32Ret)
          {
              printf("MI_VDEC_SetChnRotate failed, s32Ret: 0x%x.\n", s32Ret);
              return s32Ret;
          }
      
          return MI_SUCCESS;
      }
      

    3. 数据类型


    视频解码相关数据类型、数据结构定义如下:

    数据结构 说明
    MI_VDEC_CodecType_e 定义解码类型
    MI_VDEC_DPB_BufMode_e 定义DPB buffer模式
    MI_VDEC_VideoMode_e 定义码流发送方式
    MI_VDEC_ErrCode_e 定义错误码类型
    MI_VDEC_DecodeMode_e 定义码流解码方式
    MI_VDEC_OutputOrder_e 定义解码输出顺序方式
    MI_VDEC_VideoFormat_e 定义解码图像数据格式
    MI_VDEC_DisplayMode_e 定义显示模式
    MI_VDEC_OutbufLayoutMode_e 定义输出buffer模式
    MI_VDEC_Event_e 定义事件信息
    MI_VDEC_InitParam_t 定义解码设备初始化参数结构体
    MI_VDEC_ChnAttr_t 定义视频解码通道属性
    MI_VDEC_VideoAttr_t 定义H264/H265视频解码属性
    MI_VDEC_ChnStat_t 定义通道状态结构体
    MI_VDEC_ChnParam_t 定义解码通道参数结构体
    MI_VDEC_VideoStream_t 定义视频解码的码流结构体
    MI_VDEC_UserData_t 定义用户数据结构体
    MI_VDEC_OutputPortAttr_t 定义输出端口属性
    MI_VDEC_ErrHandlePolicy_t 定义错误宏块处理策略结构体
    MI_VDEC_CropCfg_t 定义裁剪属性
    MI_VDEC_SeqChgEvtInfo_t 定义码流信息变化事件详细信息结构体
    MI_VDEC_DecErrEvtInfo_t 定义解码错误事件详细信息结构体
    MI_VDEC_DecEosEvtInfo_t 定义解码结束事件详细信息结构体
    MI_VDEC_FrameDroppedEvtInfo_t 定义解码丢帧事件详细信息结构体
    MI_VDEC_EventData_t 定义通道事件详细信息结构体
    MI_VDEC_RotateConfig_t 定义旋转属性

    3.1. MI_VDEC_CodecType_e

    • 说明

      定义解码类型。

    • 定义

      typedef enum
      {
          E_MI_VDEC_CODEC_TYPE_H264 = 0x0,  /* H264 */
          E_MI_VDEC_CODEC_TYPE_H265,        /* H265 */
          E_MI_VDEC_CODEC_TYPE_MAX
      } MI_VDEC_CodecType_e;
      
    • 成员

      成员名称 描述
      E_MI_VDEC_CODEC_TYPE_H264 H264解码。
      E_MI_VDEC_CODEC_TYPE_H265 H265解码。

    3.2. MI_VDEC_DPB_BufMode_e

    • 说明

      定义DPB buffer模式。

    • 定义

      typedef enum
      {
          E_MI_VDEC_DPB_MODE_NORMAL=0,
          E_MI_VDEC_DPB_MODE_INPLACE_ONE_BUF=1,
          E_MI_VDEC_DPB_MODE_INPLACE_TWO_BUF=2,
          E_MI_VDEC_DPB_MODE_MAX
      } MI_VDEC_DPB_BufMode_e;
      
    • 成员

      成员名称 描述
      E_MI_VDEC_DPB_MODE_NORMAL 普通模式。
      E_MI_VDEC_DPB_MODE_INPLACE_ONE_BUF Inplace one buffer模式。
      E_MI_VDEC_DPB_MODE_INPLACE_TWO_BUF Inplace two buffer模式。

    3.3. MI_VDEC_VideoMode_e

    • 说明

      定义码流发送方式。

    • 定义

      typedef enum
      {
          E_MI_VDEC_VIDEO_MODE_STREAM = 0x0,
          E_MI_VDEC_VIDEO_MODE_FRAME,
          E_MI_VDEC_VIDEO_MODE_MAX
      } MI_VDEC_VideoMode_e;
      
    • 成员

      成员名称 描述
      E_MI_VDEC_VIDEO_MODE_STREAM 按流方式发送码流。
      E_MI_VDEC_VIDEO_MODE_FRAME 按帧方式发送码流,以帧为单位。
    • 注意事项

      • 暂不支持按流方式送码流。

    3.4. MI_VDEC_ErrCode_e

    • 说明

      定义错误码类型。

    • 定义

      typedef enum
      {
          E_MI_VDEC_ERR_CODE_NONE = 0x0,
          E_MI_VDEC_ERR_CODE_UNKNOWN,
          E_MI_VDEC_ERR_CODE_MB_ERROR,
          E_MI_VDEC_ERR_CODE_REF_FRAME_ERROR,
          E_MI_VDEC_ERR_CODE_REF_FRAME_BUFF_NOT_ENOUGH,
          E_MI_VDEC_ERR_CODE_VCL_NOT_FOUND,
          E_MI_VDEC_ERR_CODE_OVER_PROFILE,
          E_MI_VDEC_ERR_CODE_OVER_LEVEL,
          E_MI_VDEC_ERR_CODE_OVER_MULTISLICE_NUM,
          E_MI_VDEC_ERR_CODE_ILLEGAL_ACCESS,
          E_MI_VDEC_ERR_CODE_FRMRATE_UNSUPPORT,
          E_MI_VDEC_ERR_CODE_DEC_TIMEOUT,
          E_MI_VDEC_ERR_CODE_OUT_OF_MEMORY,
          E_MI_VDEC_ERR_CODE_CODEC_TYPE_UNSUPPORT,
          E_MI_VDEC_ERR_CODE_ERR_SPS_UNSUPPORT,
          E_MI_VDEC_ERR_CODE_ERR_PPS_UNSUPPORT,
          E_MI_VDEC_ERR_CODE_REF_LIST_ERR,
          E_MI_VDEC_ERR_CODE_MAX
      } MI_VDEC_ErrCode_e;
      
    • 成员

      成员名称 描述
      E_MI_VDEC_ERR_CODE_NONE
      E_MI_VDEC_ERR_CODE_UNKNOWN 未知错误。
      E_MI_VDEC_ERR_CODE_MB_ERROR 宏块错误
      E_MI_VDEC_ERR_CODE_REF_FRAME_ERROR 参考帧错误
      E_MI_VDEC_ERR_CODE_REF_FRAME_BUFF_NOT_ENOUGH 参考帧分配个数不够
      E_MI_VDEC_ERR_CODE_VCL_NOT_FOUND 无有效的图像数据
      E_MI_VDEC_ERR_CODE_OVER_PROFILE Profile不支持
      E_MI_VDEC_ERR_CODE_OVER_LEVEL Level不支持
      E_MI_VDEC_ERR_CODE_OVER_MULTISLICE_NUM 视频帧Slice个数超出限制
      E_MI_VDEC_ERR_CODE_ILLEGAL_ACCESS 不可访问,例如:未初始化或硬件出问题。
      E_MI_VDEC_ERR_CODE_FRMRATE_UNSUPPORT 帧率不支持
      E_MI_VDEC_ERR_CODE_DEC_TIMEOUT 解帧超时
      E_MI_VDEC_ERR_CODE_OUT_OF_MEMORY 内存不足
      E_MI_VDEC_ERR_CODE_CODEC_TYPE_UNSUPPORT 解码类型不支持
      E_MI_VDEC_ERR_CODE_ERR_SPS_UNSUPPORT 不支持的SPS或SPS出错
      E_MI_VDEC_ERR_CODE_ERR_PPS_UNSUPPORT 不支持的PPS或PPS出错
      E_MI_VDEC_ERR_CODE_REF_LIST_ERR 参考帧列表出错

    3.5. MI_VDEC_DecodeMode_e

    • 说明

      定义码流解码方式。

    • 定义

      typedef enum
      {
          E_MI_VDEC_DECODE_MODE_ALL = 0x0,
          E_MI_VDEC_DECODE_MODE_I,
          E_MI_VDEC_DECODE_MODE_IP,
          E_MI_VDEC_DECODE_MODE_MAX
      } MI_VDEC_DecodeMode_e;
      
    • 成员

      成员名称 描述
      E_MI_VDEC_DECODE_MODE_ALL 解码IPB数据帧模式
      E_MI_VDEC_DECODE_MODE_I 只解I帧模式
      E_MI_VDEC_DECODE_MODE_IP 只解IP帧,跳过B帧
    • 注意事项

      • 仅支持设置E_MI_VDEC_DECODE_MODE_I及E_MI_VDEC_DECODE_MODE_ALL。

    3.6. MI_VDEC_OutputOrder_e

    • 说明

      定义解码输出顺序方式。

    • 定义

      typedef enum
      {
          E_MI_VDEC_OUTPUT_ORDER_DISPLAY = 0x0,
          E_MI_VDEC_OUTPUT_ORDER_DECODE,
          E_MI_VDEC_OUTPUT_ORDER_MAX,
      } MI_VDEC_OutputOrder_e;
      
    • 成员

      成员名称 描述
      E_MI_VDEC_OUTPUT_ORDER_DISPLAY 按显示顺序输出数据帧
      E_MI_VDEC_OUTPUT_ORDER_DECODE 按解帧顺序列输出数据帧
    • 注意事项

      • 该参数暂不支持设置。

    3.7. MI_VDEC_VideoFormat_e

    • 说明

      定义解码图像数据格式。

    • 定义

      typedef enum
      {
          E_MI_VDEC_VIDEO_FORMAT_TILE = 0x0,
          E_MI_VDEC_VIDEO_FORMAT_REDUCE,
          E_MI_VDEC_VIDEO_FORMAT_MAX
      } MI_VDEC_VideoFormat_e;
      
    • 成员

      成员名称 描述
      E_MI_VDEC_VIDEO_FORMAT_TILE TILE数据格式。
      E_MI_VDEC_VIDEO_FORMAT_REDUCE 数据帧压缩模式,减少数据帧内存使用量。
    • 注意事项

      • 当前数据类型不支持上层设定,只能返回支持数据类型。

    3.8. MI_VDEC_DisplayMode_e

    • 说明

      定义显示模式。

    • 定义

      typedef enum
      {
          E_MI_VDEC_DISPLAY_MODE_PREVIEW = 0x0,
          E_MI_VDEC_DISPLAY_MODE_PLAYBACK,
          E_MI_VDEC_DISPLAY_MODE_MAX,
      } MI_VDEC_DisplayMode_e;
      
    • 成员

      成员名称 描述
      E_MI_VDEC_DISPLAY_MODE_PREVIEW 预览模式。不参考PTS输出。
      E_MI_VDEC_DISPLAY_MODE_PLAYBACK 回放模式。参考PTS数值输出。

    3.9. MI_VDEC_OutbufLayoutMode_e

    • 说明

      定义输出buffer模式。

    • 定义

      typedef enum
      {
          E_MI_VDEC_OUTBUF_LAYOUT_AUTO = 0x0,
          E_MI_VDEC_OUTBUF_LAYOUT_LINEAR,
          E_MI_VDEC_OUTBUF_LAYOUT_TILE,
          E_MI_VDEC_OUTBUF_LAYOUT_MAX
      } MI_VDEC_OutbufLayoutMode_e;
      
    • 成员

      成员名称 描述
      E_MI_VDEC_OUTBUF_LAYOUT_AUTO 输出buffer自适应模式。
      E_MI_VDEC_OUTBUF_LAYOUT_LINEAR 输出buffer为LINEAR模式。
      E_MI_VDEC_OUTBUF_LAYOUT_TILE 输出buffer为TILE模式
    • 注意事项

      • ifackel默认输出buffer模式为E_MI_VDEC_OUTBUF_LAYOUT_TILE;mHera默认输出buffer模式为E_MI_VDEC_OUTBUF_LAYOUT_LINEAR;其余芯片默认输出buffer模式为E_MI_VDEC_OUTBUF_LAYOUT_AUTO。

      • MI_DISP模块的旋转功能和MI_VDEC模块的TILE模式存在联动关系。如果MI_DISP模块需要开启旋转功能,则其前端送入的buffer必须为TILE格式。MI_VDEC模块有两种方式输出TILE格式的图像。

        1) 输出buffer模式为E_MI_VDEC_OUTBUF_LAYOUT_AUTO时,MI_DISP模块和MI_VDEC模块需要绑定;此时,由MI_DISP模块开启旋转,同时通过u64SidebandMsg告知MI_VDEC模块,然后MI_VDEC模块自动打开TILE模式,即可完成旋转功能的开启。如果MI_DISP模块关闭旋转,则同样通过u64SidebandMsg告知MI_VDEC模块,然后MI_VDEC模块再自动关闭TILE模式。该过程无需用户处理,由模块内部自动完成。

        2) 输出buffer模式为E_MI_VDEC_OUTBUF_LAYOUT_TILE时,MI_VDEC模块仅输出TILE格式的图像。MI_DISP模块必须开启旋转功能,才能正常显示TILE格式的图像。这种模式下,MI_VDEC模块和MI_DISP模块既可以直接绑定,也可由用户获取MI_VDEC模块的输出buffer,再发送给MI_DISP模块。

      • 如果MI_VDEC模块需要输出LINEAR图像,有两种方式。

        1) 输出buffer模式为E_MI_VDEC_OUTBUF_LAYOUT_AUTO时,如果MI_VDEC模块和MI_DISP模块绑定,则MI_DISP模块关闭旋转,即可输出LINEAR图像。其他情况下,均输出LINEAR图像。

        2) 输出buffer模式为E_MI_VDEC_OUTBUF_LAYOUT_LINEAR时,MI_VDEC模块仅输出LINEAR图像。

      • 输出buffer为TILE模式时,MI_VDEC模块输出buffer对齐方式如下表。

        芯片 TILE输出buffer对齐要求(BYTE)
        Taiyaki 128x32
        Takoyaki 128x32
        Tiramisu 128x64
        Muffin 128x64
        Opera 128x64
        iBopper 128x64

        因此,通过MI_VDEC_OutputPortAttr_t设置MI_VDEC模块输出buffer宽高时,也需要按TILE输出buffer对齐要求进行设置,否则会输出异常图像。如:TILE输出buffer对齐要求为128x32,那么MI_VDEC_OutputPortAttr_t设置MI_VDEC模块输出buffer的宽高也需要按128x32对齐。


    3.10. MI_VDEC_Event_e

    • 说明

      定义事件信息。

    • 定义

      typedef enum
      {
          E_MI_VDEC_EVENT_SEQCHANGE = 0,
          E_MI_VDEC_EVENT_EOS,
          E_MI_VDEC_EVENT_DECERR,
          E_MI_VDEC_EVENT_FRAME_DROPPED,
          E_MI_VDEC_EVENT_MAX = 64,
      } MI_VDEC_Event_e;
      
    • 成员

      成员名称 描述
      E_MI_VDEC_EVENT_SEQCHANGE 码流信息发生变化。如SPS,PPS的宽,高以及参数帧个数等等。
      E_MI_VDEC_EVENT_EOS 码流解码结束事件。当码流缓冲区最后1帧数据解码完成时,将会触发此事件。
      E_MI_VDEC_EVENT_DECERR 码流解码错误事件。解码器解码过程中发生错误时触发。
      E_MI_VDEC_EVENT_FRAME_DROPPED 解码丢帧事件。解码器解码过程中发生丢帧时触发。
      E_MI_VDEC_EVENT_MAX 非法事件信息。
    • 注意事项

      • E_MI_VDEC_EVENT_EOS事件需要在调用MI_VDEC_SendStream推送最后1帧码流数据时,设置MI_VDEC_VideoStream_t参数的bEndOfFrame为TRUE才能触发。

    3.11. MI_VDEC_InitParam_t

    • 说明

      定义解码设备初始化参数结构体。

    • 定义

      typedef struct MI_VDEC_InitParam_s
      {
          MI_U16 u16MaxWidth;
          MI_U16 u16MaxHeight;
      } MI_VDEC_InitParam_t;
      
    • 成员

      成员名称 描述
      u16MaxWidth 解码器支持的最大码流宽。参数类型:MI_U16
      u16MaxHeight 解码器支持的最大码流高。参数类型:MI_U16
    • 注意事项

      • VDEC根据硬件性能,内部默认设置了一组最大分辨率。如果用户需要解码超出默认的最大分辨率(如:4Kx3K),则需要在此修改最大码流的宽和高,以便可以正常解码。如果超出默认分辨率,解码帧率相应下降。

    3.12. MI_VDEC_ChnAttr_t

    • 说明

      定义视频解码通道属性。

    • 定义

      typedef struct MI_VDEC_ChnAttr_s
      {
          MI_VDEC_CodecType_e eCodecType;
          MI_U32 u32BufSize;
          MI_U32 u32Priority;
          MI_U32 u32PicWidth;
          MI_U32 u32PicHeight;
          MI_VDEC_VideoMode_e eVideoMode;
          MI_VDEC_DPB_BufMode_e eDpbBufMode;
          MI_VDEC_VideoAttr_t stVdecVideoAttr;
      } MI_VDEC_ChnAttr_t;
      
    • 成员

      成员名称 描述
      eCodecType 解码类型枚举值。参数类型:MI_VDEC_CodecType_e
      u32BufSize 码流缓存的大小。
      u32Priority 通道优先级,取值范围为 1 ~ 255,值越大优先级越高。 注意:当前暂不支持此功能。
      u32PicWidth 通道支持的解码图像最大宽(以像素为单位)。
      u32PicHeight 通道支持的解码图像最大高(以像素为单位)。
      eVideoMode 码流传送方式。 注意:当前只支持按帧。
      eDpbBufMode DPB buffer 模式。 注意:eDpbBufMode=E_MI_VDEC_DPB_MODE_INPLACE_ONE_BUF,只适用于一个参考帧的码流;eDpbBufMode=E_MI_VDEC_DPB_MODE_INPLACE_TWO_BUF,适用于两个参考帧的码流;如果超过两个参考帧,则需要设置为eDpbBufMode=E_MI_VDEC_DPB_MODE_NORMAL。
      stVdecVideoAttr 其它解码相关的属性
    • 注意事项

      • 当设置了eDpbBufMode为E_MI_VDEC_DPB_MODE_INPLACE_ONE_BUF或者E_MI_VDEC_DPB_MODE_INPLACE_TWO_BUF时,u32RefFrameNum的值将无效;

      • E_MI_VDEC_DPB_MODE_INPLACE_ONE_BUF与E_MI_VDEC_DPB_MODE_INPLACE_TWO_BUF为省内存模式,E_MI_VDEC_DPB_MODE_INPLACE_ONE_BUF解码器只分配1个参考帧,因此也只能解码1个参考帧的码流,同理,E_MI_VDEC_DPB_MODE_INPLACE_TWO_BUF最多只分配2个参考帧,只能解码最多2个参考帧的码流。对于2个参考帧以上的码流,只支持设置为E_MI_VDEC_DPB_MODE_NORMAL。例如:设置为E_MI_VDEC_DPB_MODE_NORMAL模式时,解码1个参考帧的码流,解码器需要申请2个参考帧才能正常解码,会比E_MI_VDEC_DPB_MODE_INPLACE_ONE_BUF省内存模式多申请1个参考帧。

      • 当eDpbBufMode为E_MI_VDEC_DPB_MODE_NORMAL时,需要设置u32RefFrameNum的值,用于限制最大参考帧个数,避免分配过多的frame buffer;若u32RefFrameNum的值小于当前解码所需的参考帧个数,则可能不解码或者解码花屏。

      • 如果无法预先确定码流参考帧个数,那么建议设置为E_MI_VDEC_DPB_MODE_NORMAL模式,最大参考帧申请个数u32RefFrameNum设置为16。解码器会自动解析码流所需参考帧个数,按解码码流所需参考帧个数进行申请。例如:u32RefFrameNum设置为16,当前码流解码需要3个参考帧,那么解码器将申请4个参考帧内存;反之,如果u32RefFrameNum设置为2,当前解码需要3个参考帧的码流,那么解码器最多只能申请到2个参考帧,无法正常解码。


    3.13. MI_VDEC_VideoAttr_t

    • 说明

      定义H264/H265视频解码属性。

    • 定义

      typedef struct MI_VDEC_VideoAttr_s
      {
          MI_U32 u32RefFrameNum;
          MI_VDEC_ErrHandlePolicy_t stErrHandlePolicy;
          MI_BOOL bDisableLowLatency;
      }MI_VDEC_VideoAttr_t;
      
    • 成员

      成员名称 描述
      u32RefFrameNum 参考帧的数目。 取值范围:[1, 16],以帧为单位。 参考帧的数目决定解码时需要的参考帧个数,影响内存使用量,根据实际情况设置合适的值。测试码流:推荐设为2。
      stErrHandlePolicy 设置错误宏块的数据帧的输出策略,参考MI_VDEC_ErrHandlePolicy_t定义。
      bDisableLowLatency 是否开启B帧解码功能,默认:FALSE。
    • 注意事项

      • 当设置了eDpbBufMode为E_MI_VDEC_DPB_MODE_INPLACE_ONE_BUF或者E_MI_VDEC_DPB_MODE_INPLACE_TWO_BUF时,u32RefFrameNum的值将无效;

      • 当eDpbBufMode为E_MI_VDEC_DPB_MODE_NORMAL时,需要设置u32RefFrameNum的值,用于限制最大参考帧个数,避免分配过多的frame buffer;若u32RefFrameNum的值小于当前解码所需的参考帧个数,则可能不解码或者解码花屏。

      • 若bDisableLowLatency设为TRUE,表示关闭低延时;这种情况适用于解码B帧,用于对B帧的输出帧做重排序,输出画面会有延时。另外,做重排序操作,也会增加内存使用量。

      • 如果用户的场景无需解码B帧格式码流,则需要设置 bDisableLowLatency为FALSE。


    3.14. MI_VDEC_ChnStat_t

    • 说明

      定义通道状态结构体。

    • 定义

      typedef struct MI_VDEC_ChnStat_s
      {
          MI_VDEC_CodecType_e eCodecType;
          MI_U32  u32LeftStreamBytes;
          MI_U32  u32LeftStreamFrames;
          MI_U32  u32LeftPics;
          MI_U32  u32RecvStreamFrames;
          MI_U32  u32DecodeStreamFrames;
          MI_BOOL bChnStart;
          MI_VDEC_ErrCode_e eErrCode;
          MI_U16  u16DecodeWidth;
          MI_U16  u16DecodeHeight;
      } MI_VDEC_ChnStat_t;
      
    • 成员

      成员名称 描述
      eCodecType 解码类型
      u32LeftStreamBytes 码流 buffer 中待解码的 byte 数。
      u32LeftStreamFrames 码流 buffer 中待解码的帧数。 –1 表示无效。 仅按帧发送时有效。
      u32LeftPics 图像 buffer 中剩余的 pic 数目。
      u32RecvStreamFrames 码流 buffer 中已接收码流帧数。 -1 表示无效。 仅按帧发送时有效。
      u32DecodeStreamFrames 码流 buffer 中已解码帧数。
      bChnStart 解码器是否已经启动接收码流。
      eErrCode 解码错误码信息。
      u16DecodeWidth 解码图像原始宽度
      u16DecodeHeight 解码图像原始高度

    3.15. MI_VDEC_ChnParam_t

    • 说明

      定义解码通道参数结构体。

    • 定义

      typedef struct MI_VDEC_ChnParam_s
      {
          MI_VDEC_DecodeMode_e eDecMode;
          MI_VDEC_OutputOrder_e eOutputOrder;
          MI_VDEC_VideoFormat_e eVideoFormat;
      } MI_VDEC_ChnParam_t;
      
    • 成员

      成员名称 描述
      eDecMode 解码模式,参考MI_VDEC_DecodeMode_e定义。默认为E_MI_VDEC_DECODE_MODE_ALL。
      eOutputOrder 参考MI_VDEC_OutputOrder_e定义,默认为 E_MI_VDEC_OUTPUT_ORDER_DISPLAY 按显示顺序输出数据帧。
      eVideoFormat 参考MI_VDEC_VideoFormat_e定义。
    • 注意事项

      • 仅支持设置eDecMode。eDecMode仅支持E_MI_VDEC_DECODE_MODE_I及E_MI_VDEC_DECODE_MODE_ALL,默认值是E_MI_VDEC_DECODE_MODE_ALL。

    3.16. MI_VDEC_VideoStream_t

    • 说明

      定义视频解码的码流结构体。

    • 定义

      typedef struct MI_VDEC_VideoStream_s
      {
          union
          {
              MI_U8*   pu8Addr;
              MI_PTR64 u64Reserved;
          };
          MI_U32 u32Len;
          MI_U64 u64PTS;
          MI_BOOL bEndOfFrame;
          MI_BOOL bEndOfStream;
      }MI_VDEC_VideoStream_t;
      
    • 成员

      成员名称 描述
      pu8Addr 码流包的地址。
      u64Reserved 预留,兼容32位和64位地址长度。(不可使用)
      u32Len 码流包的长度,以字节为单位。
      u64PTS 码流包的时间戳,以微秒为单位。
      bEndOfFrame 当前帧是否结束,预留,当前只支持帧模式下按帧传送。
      bEndOfStream 是否发完所有码流。当所有码流数据帧传送完毕时,bEndOfStream值需置为TRUE。
    • 注意事项

      • 暂不支持按流发送。按帧传送时,每次需完整传送一帧数据。

      • 码流帧数据附带PTS时,解码后输出数据输出相同PTS。当u64PTS = -2时,在解码后,VDEC会丢弃该帧。用户可根据需要进行设置。


    3.17. MI_VDEC_UserData_t

    • 说明

      定义用户数据结构体。

    • 定义

      typedef struct MI_VDEC_UserData_s
      {
          union
          {
              MI_U8*   pu8Addr;
              MI_PTR64 u64Reserved;
          };
          MI_U32 u32Len;
          MI_BOOL bValid;
      } MI_VDEC_UserData_t;
      
    • 成员

      成员名称 描述
      pu8Addr 用户数据的虚拟地址。
      u64Reserved 预留,兼容32位和64位地址长度。(不可使用)
      u32Len 用户数据的长度。以 byte 为单位。
      bValid 当前数据的有效标识。取值范围:{TRUE, FALSE}。 TRUE:有效。 FALSE:无效。
    • 注意事项

      • 目前暂不支持该参数相关功能。

    3.18. MI_VDEC_OutputPortAttr_t

    • 说明

      定义输出端口属性。

    • 定义

      typedef struct MI_VDEC_OutputPortAttr_s
      {
          MI_U16                u16Width;  // Width of target image
          MI_U16                u16Height; // Height of target image
          MI_SYS_CompressMode_e eCompressMode;
      } MI_VDEC_OutputPortAttr_t;
      
    • 成员

      成员名称 描述
      u16Width 输出图像宽
      u16Height 输出图像高
      eCompressMode 输出图像压缩模式
    • 注意事项

      • 缩放宽和高需要按2对齐。

      • mHera芯片的缩放范围为[1/32, 1],其余支持缩放功能的芯片缩放范围为[⅛, 1]。

      • 不支持放大。

      • 若裁剪和缩放同时开启,则裁剪宽和高不能小于缩放的宽和高。

      • eCompressMode目前仅支持E_MI_SYS_COMPRESS_MODE_NONE和E_MI_SYS_COMPRESS_MODE_LSYC0,分别对应LSYC功能关闭和LSYC功能开启。


    3.19. MI_VDEC_ErrHandlePolicy_t

    • 说明

      定义错误宏块处理策略结构体。

    • 定义

      typedef struct MI_VDEC_ErrHandlePolicy_s
      {
          MI_BOOL bUseCusPolicy;          // FALSE: use default; TRUE: use customized value
          MI_U8 u8ErrMBPercentThreshold;
      } MI_VDEC_ErrHandlePolicy_t;
      
    • 成员

      成员名称 描述
      bUseCusPolicy 是否需要客制化控制错误帧输出策略。
      u8ErrMBPercentThreshold 设置控制不输出数据帧时,错误宏块数占整张数据帧宏块数的比例值,取值范围[0, 100]。
    • 注意事项

      • bUseCusPolicy 值为FALSE时代表不做客制化,u8ErrMBPercentThreshold为系统内置默认值30;bUseCusPolicy值为TRUE时,则使用客制化定义的u8ErrMBPercentThreshold数值。

      • u8ErrMBPercentThreshold取值范围[0, 100]。例如数值为10时,代表错误宏块个数占整个数据帧宏块个数低于10%时,当前数据帧输出显示,否则(大于等于10%)不显示。其中数值为0时,代表只要有错误宏块都将不输出显示;数值为100时,代表不管有多少错误宏块当前数据帧都将会显示。

      • u8ErrMBPercentThreshold数值是以宏块为基本单位计算比率值。


    3.20. MI_VDEC_CropCfg_t

    • 说明

      定义裁剪属性结构体。

    • 定义

      typedef struct MI_VDEC_CropCfg_s
      {
          MI_BOOL             bEnable; /* Crop region enable */
          MI_SYS_WindowRect_t stRect;  /* Crop region */
      } MI_VDEC_CropCfg_t;
      
    • 成员

      成员名称 描述
      bEnable 开启/关闭裁剪功能。
      stRect 裁剪属性。结构体MI_SYS_WindowRect_t参考mi_sys数据类型定义。
    • 注意事项

      • 取值范围:u16X:[0,8192-16],u16Y:[0,8192-2],u16Width:[16,8192],u16Height:[2,8192]。注意:设置的裁剪宽和高需小于码流原始图像宽高,否则裁剪功能将不生效。

      • 对齐要求:u16X和u16Width需要按一定长度对齐(芯片mHera为按2对齐,其余支持裁剪功能的芯片按16对齐),u16Y和u16Height需按2对齐。

      • 若裁剪和缩放同时开启,则裁剪宽和高不能小于缩放的宽和高。


    3.21. MI_VDEC_SeqChgEvtInfo_t

    • 说明

      定义码流信息变化事件详细信息结构体。

    • 定义

      typedef struct MI_VDEC_SeqChgEvtInfo_s
      {
          MI_U8               u8RefFrameNum;
          MI_U16              u16PicWidth;
          MI_U16              u16PicHeight;
          MI_SYS_WindowRect_t stCropInfo;
      } MI_VDEC_SeqChgEvtInfo_t;
      
    • 成员

      成员名称 描述
      u8RefFrameNum 码流参数帧个数。
      u16PicWidth 码流宽度信息。
      u16PicHeight 码流高度信息。
      stCropInfo 码流裁剪信息,参考MI_SYS_WindowRect_t定义。

    3.22. MI_VDEC_DecErrEvtInfo_t

    • 说明

      定义解码错误事件详细信息结构体。

    • 定义

      typedef struct MI_VDEC_DecErrEvtInfo_s
      {
          MI_VDEC_ErrCode_e eErrCode;
      } MI_VDEC_DecErrEvtInfo_t;
      
    • 成员

      成员名称 描述
      eErrCode 发生的错误事件,参考MI_VDEC_ErrCode_e定义。

    3.23. MI_VDEC_DecEosEvtInfo_t

    • 说明

      定义解码结束事件详细信息结构体。

    • 定义

      typedef struct MI_VDEC_DecEosEvtInfo_s
      {
          MI_BOOL bAbnormal;
      } MI_VDEC_DecEosEvtInfo_t;
      
    • 成员

      成员名称 描述
      bAbnormal 是否为异常结束,TRUE:异常结束。

    3.24. MI_VDEC_FrameDroppedEvtInfo_t

    • 说明

      定义解码丢帧事件详细信息结构体。

    • 定义

      typedef struct MI_VDEC_FrameDroppedEvtInfo_s
      {
          MI_BOOL bRemainDroppedData;
          MI_U8   u8FrameDroppedCnt;
          MI_U64  au64FrameDroppedPts[2];
      } MI_VDEC_FrameDroppedEvtInfo_t;
      
    • 成员

      成员名称 描述
      bRemainDroppedData 是否还残留丢帧数据,TRUE:残留。
      u8FrameDroppedCnt 丢帧的帧数,最多2帧。
      au64FrameDroppedPts[2] 被丢弃帧的PTS。

    3.25. MI_VDEC_EventData_t

    • 说明

      定义通道事件详细信息结构体。

    • 定义

      typedef struct MI_VDEC_EventData_s
      {
          union
          {
              MI_VDEC_SeqChgEvtInfo_t       stSeqChgEvtInfo;
              MI_VDEC_DecErrEvtInfo_t       stDecErrEvtInfo;
              MI_VDEC_DecEosEvtInfo_t       stDecEosEvtInfo;
              MI_VDEC_FrameDroppedEvtInfo_t stFrameDroppedEvtInfo;
          } value;
      } MI_VDEC_EventData_t;
      
    • 成员

      成员名称 描述
      stSeqChgEvtInfo 码流信息变化事件结构体,参考MI_VDEC_SeqChgEvtInfo_t定义。
      stDecErrEvtInfo 解码错误事件结构体,参考MI_VDEC_DecErrEvtInfo_t定义。
      stDecEosEvtInfo 解码结束事件结构体,参考MI_VDEC_DecEosEvtInfo_t定义。
      stFrameDroppedEvtInfo 解码丢帧事件结构体,参考MI_VDEC_FrameDroppedEvtInfo_t定义。

    3.26. MI_VDEC_RotateConfig_t

    • 说明

      定义旋转属性。

    • 定义

      typedef struct MI_VDEC_RotateConfig_s
      {
          MI_SYS_Rotate_e eRotateMode;
      } MI_VDEC_RotateConfig_t;
      
    • 成员

      成员名称 描述
      eRotateMode 旋转角度枚举,参考MI_SYS_Rotate_e定义。

    4. 错误码

    视频解码错误码如下表所示:

    错误代码 宏定义 描述
    0xA0082001 MI_ERR_VDEC_INVALID_DEVID 设备ID超出合法范围
    0xA0082002 MI_ERR_VDEC_INVALID_CHNID 通道ID超出合法范围
    0xA0082003 MI_ERR_VDEC_ILLEGAL_PARAM 非法参数或输入参数超过通道解码能力
    0xA0082004 MI_ERR_VDEC_CHN_EXIST 试图创建已经存在的通道
    0xA0082005 MI_ERR_VDEC_CHN_UNEXIST 通道不存在
    0xA0082006 MI_ERR_VDEC_NULL_PTR 输入参数为空指针
    0xA0082007 MI_ERR_VDEC_NOT_CONFIG 使用前未配置
    0xA0082008 MI_ERR_VDEC_NOT_SUPPORT 该操作或者功能不支持
    0xA0082009 MI_ERR_VDEC_NOT_PERM 非法操作
    0xA008200C MI_ERR_VDEC_NOMEM 分配内存失败,如系统内存不足
    0xA008200D MI_ERR_VDEC_NOBUF 分配缓存失败,如申请的数据缓冲区太大
    0xA008200E MI_ERR_VDEC_BUF_EMPTY 缓冲区中无数据
    0xA008200F MI_ERR_VDEC_BUF_FULL 缓冲区中数据满
    0xA0082010 MI_ERR_VDEC_SYS_NOTREADY 系统没有初始化或者相关 依赖的模块没有加载
    0xA0082011 MI_ERR_VDEC_BADADDR 地址错误
    0xA0082012 MI_ERR_VDEC_BUSY 系统忙
    0xA0082013 MI_ERR_VDEC_CHN_NOT_START 通道未使能
    0xA0082014 MI_ERR_VDEC_CHN_NOT_STOP 通道未禁用
    0xA0082015 MI_ERR_VDEC_NOT_INIT 模块没有成功加载
    0xA0082016 MI_ERR_VDEC_INITED 模块已成功加载
    0xA0082017 MI_ERR_VDEC_NOT_ENABLE 解码器未使能
    0xA0082018 MI_ERR_VDEC_NOT_DISABLE 解码器未禁用
    0xA0082019 MI_ERR_VDEC_SYS_TIMEOUT 系统超时
    0xA008201A MI_ERR_VDEC_NOT_STARTED 未开始解码
    0xA008201B MI_ERR_VDEC_NOT_STOPED 未结束解码
    0xA008201C MI_ERR_VDEC_CHN_NO_CONTENT 码流buffer无有效数据
    0xA008201F MI_ERR_VDEC_FAILED 失败

    5. PROCFS介绍


    5.1. cat

    • 调试信息

      查看vdec device 0:

      # cat /proc/mi_modules/mi_vdec/mi_vdec0
      

    • 调试信息分析

      打印分为两部分,使用Private Vdec0 Info分隔开。上半部分为common信息,下半部分为vdec模块信息。主要记录了解码通道的使用情况及配置属性,可用于检查属性配置和当前通道的工作状态,便于debug。

    • 参数说明

      参数 描述
      DEV Info DevID 硬件设备号。
      UUID UUID号。
      MaxChnNum 最大支持通道个数。
      MaxChnId 最大支持通道号。
      TotEnqCnt 解码硬件队列排队帧数。
      InitSeqBitmapIdx 序列初始化中断通道号位图索引。
      InitSeqBitmap 序列初始化中断通道号位图。
      SeqChgCnt 序列变化计数。
      CHN ATTR Info DevID  硬件设备号。
      ChnID 通道号。
      CodecType  解码协议类型
      0:H264;
      1:H265;
      Width  解码图像最大宽度。
      Height   解码图像最大高度。
      BufSize  VDEC码流缓存大小,单位:byte。
      VideoMode  发送码流方式。
      FRAME:按帧发送。
      DpbBufMode  解码模式
      INPLACE1:DBP_MODE_INPLACE_ONE_BUF;
      INPLACE2:DBP_MODE_INPLACE_TWO_BUF;
      NORMAL: DBP_MODE_NORMAL;
      RefFrmNum 最大分配参考帧个数。
      CHN PARAM Info DevID  硬件设备号。
      ChnID  通道号。
      bCusPolicy 是否由客户设置丢帧策略
      Y:客户设置;
      N:客户不设置,使用默认;
      ErrMBDropThrd 丢帧策略生效时,错误宏块占整张数据帧的比例。
      DisplayMode 显示模式。
      PREVIEW:  预览模式
      PLAYBACK:回放模式
      bDisableLowLatency 通道是否支持B帧播放。
      0:不支持B帧播放。
      1:支持B帧播放。
      DecMode 通道解码模式。
      0:解码IPB数据帧模式。
      1:只解I帧模式。
      2:只解IP帧,跳过B帧。
      Scale & Crop & Rotate & Compress Info DevID 硬件设备号。
      ChnID 通道号。
      PortID 输出Port号。
      bCrop 是否设置裁剪功能。
      N:不设置。
      Y:设置。
      CropX 裁剪源图开始的X坐标。
      CropY 裁剪源图开始的Y坐标。
      CropW 裁剪源图的宽度。
      CropH 裁剪源图的高度。
      bScale 是否设置缩小功能。
      N:不设置。
      Y:设置。
      ScaleW 设置缩小输出的宽度。
      ScaleH 设置缩小输出的高度。
      Rotate 输出图像旋转角度。
      0:不旋转。
      1:顺时针旋转90°。
      2:顺时针旋转180°。
      3:顺时针旋转270°。
      Compress 输出图像压缩模式。
      0:不压缩。
      10:LSYC压缩。
      Decode Frame Info DevID 硬件设备号。
      ChnID  通道号。
      SeqW 源码流SPS宽度。
      SeqH 源码流SPS高度。
      SeqCropX 源码流SPS携带的crop信息裁剪开始的X坐标。
      SeqCropY 源码流SPS携带的crop信息裁剪开始的Y坐标。
      SeqCropW 源码流SPS携带的crop信息裁剪宽度。
      SeqCropH 源码流SPS携带的crop信息裁剪高度。
      RefRecFrmCnt 当前源码流解码所需要分配参考帧个数。
      LinearFrmCnt Output Buffer分配的个数。
      Output Frame Info DevID 硬件设备号。
      ChnID  通道号。
      bTileMode 是否打开tilemode输出格式。
      Y:是。
      N:否。
      TileFormat TileMode开启后对齐的格式。
      128x64:128x64字节对齐。
      128x32:128x32字节对齐。
      32x32:32x32字节对齐。
      Invalid:不支持。
      NA:没有开启tilemode输出格式。
      DispW 输出数据帧的宽度。
      DispH 输出数据帧的高度。
      PixelFmt 输出数据帧的像素格式。
      YUV420SP:NV12数据帧格式输出。
      CHN STATE DevID 硬件设备号。
      ChnID  通道号。
      bStart  解码器是否启动。
      Y:启动,进入解码状态。
      N:停止解码状态。
      bPause 解码器是否暂停。
      0:非暂停解码状态。
      1:暂停解码状态。
      bEnableSys 解码线程调度是否使能。
      0:非使能状态。
      1:使能状态。
      DecState 当前通道解码状态。
      0:未定义。
      1:通道刚创建。
      2:等待sps,pps等关键数据帧。
      3:获取关键sps,pps信息完成状态。
      4:解码前申请参考帧等内存状态。
      5:申请到解码所需内存,正常解码状态。
      6:通道关闭状态。
      PlayState 当前通道播放状态。
      0:正常播放状态。
      1:暂停播放状态。
      2:refresh播放状态。
      3:step播放状态。
      SendCnt 应用层推流次数。
      SendStrmSize 应用层推流字节数。
      LeftStrmBytes  码流缓存中待解码的byte数。
      LeftCnt     相应于SendCnt参数,待解码的次数。
      Unread/Total 码流缓存中未读取/总共的数据笔数。
      DecFrmCnt 成功解码输出的帧数。
      fps 当前解码帧率。
      EOS 码流数据帧传送完毕标记。
      CHN STATE DevID 硬件设备号。
      ChnID  通道号。
      Start 开始解码次数。
      Get 获取解码结果的次数。
      GetOK 成功获取到解码结果的次数。
      Done 成功解码并输出显示的次数。
      Drop 丢弃不输出显示的次数。
      DropNoVCL 丢弃无效数据帧的次数。
      Run 申请硬件解码次数。
      SeqChange 图像序列发生变化的次数。例如:SPS。
      CHN STATE DevID 硬件设备号。
      ChnID 通道号。
      SeqInitCnt 序列初始化任务计数。
      EnqueCnt 解码任务计数。
      RefreshCnt Refresh任务计数。
      StepCnt Step任务计数。
      DispCnt 显示帧数量计数。
      CHN STATE DevID 硬件设备号。
      ChnID 通道号。
      Issue 请求解码器解析码流头信息的次数。
      Complete 解码器完成解析码流头信息的次数,对应Issue请求。
      InitSeq 解码器完成解析码流头信息后,对应Issue请求,返回中断次数。
      VlcInsuff VLC Buffer不足的中断次数。
      FrmDone 解码器返回解码成功的中断的次数。
      ChkInitSeq 对应InitSeq,解码器返回完成解释码流头信息成功的中断后,对应VDEC检查中断并处理的次数。
      ChkVlcInsuff 对应VlcInsuff,解码器返回vlc buffer不足的中断后,对应VDEC检查中断并处理的次数。
      ChkFrmDone 对应FrmDone,解码器返回解码成功的中断后,对应VDEC检查中断并处理的次数。
      RcvRstCB 接收到解码器请求Reset的中断的次数。
      ChkRstCB 对应RcvRstCB中断请求,VDEC处理解码器Resset请求的次数。
      ResetChnCnt 重置channel计数。
      ISR STATE IsrCnt 解码器上报中断的总次数。
      InitSeq 解码器上报解析码流头信息中断的总次数。
      VlcInsuff 解码器上报VLC Buffer不足的中断总次数。
      FrmDone 解码器上报解码完成的中断总次数。
      UnderRun 解码器上报任务线程还未解码完成的总次数。
      HwTimeout 解码器上报硬件解码超时的总次数。
      Other 解码器上报硬件其他中断总次数。
      History Task Info DevID 硬件设备号。
      ChnID 通道号。
      EnqueueTime 解码任务入队的时间。
      CheckOutputTime 解码任务检查输出状态的时间。
      DequeueTime 解码任务出队的时间。
      EsLength 解码任务送入的码流数据长度。
      NextDecFlow 解码任务下一次触发的解码流程。
      TriggerSeqChange 解码任务是否触发了图像序列发生变化流程。


    5.2. echo

    vdec device 0:

    /proc/mi_modules/mi_vdec/mi_vdec0
    
    功能 打开抓图或静帧功能的debug log相关信息到/proc/kmsg
    命令 echo log [capture/refresh] [on/off] > /proc/mi_modules/mi_vdec/mi_vdec0
    参数说明 capture/refresh:capture抓图,refresh 静帧
    on/off:on打开,off 关闭
    举例 echo log refresh on > /proc/mi_modules/mi_vdec/mi_vdec0
    打开静帧功能的debug log相关信息到/proc/kmsg
    功能 将指定通道输入的bitstream数据存储到指定路径
    命令 echo dumpbs [chn] [path] > /proc/mi_modules/mi_vdec/mi_vdec0
    参数说明 chn:通道号 [0~63]
    path:dump文件输出路径,输入off代表停止存储码流。
    举例 echo dumpbs 3 /mnt/dump/ > /proc/mi_modules/mi_vdec/mi_vdec0
    dump通道3的应用推送到bitstream buffer的码流数据到/mnt/dump目录下
    功能 将指定通道的当前码流buffer的所有数据存储到指定路径。(整个码流buffer包含有效数据和无效数据,注意与前面dumpbs的区别)
    命令 echo dumpbsb [chn] [path] > /proc/mi_modules/mi_vdec/mi_vdec0
    参数说明 chn:通道号 [0~63]
    path:dump文件输出路径。
    举例 echo dumpbsb 3 /mnt/dump/ > /proc/mi_modules/mi_vdec/mi_vdec0
    dump通道3的整个码流buffer的数据到/mnt/dump目录下
    功能 将指定通道及指定端口解码后的输出数据帧存储指定路径
    命令 echo dumpfb [chn] [port] [path] [frmcnt] [bDumpAll] [bDetile] > /proc/mi_modules/mi_vdec/mi_vdec0
    参数说明 chn:通道号 [0~63]
    port:端口号
    path:dump文件输出路径
    Frmcnt:dump的帧数
    bDumpAll:
    0:只存储yuv buffer。
    1:同时存储Y buffer,UV buffer和YUV buffer。
    bDetile:
    0:不对将要存储的YUV做detile(tilemode模式下存储tile格式数据)。
    1:对将要存储的YUV做detile(tilemode模式下存储YUV格式数据)。
    举例 通道3,端口0,存储路径为/mnt/dump/,存储99帧,不单独保存Y buffer和UV buffer,对将要存储的YUV做detile
    echo dumpfb 3 0 /mnt/dump/ 99 0 1 > /proc/mi_modules/mi_vdec/mi_vdec0
    功能 打开/关闭flow checkpoint,检查解码任务运行状态。
    命令 echo flowdbg [Status] > /proc/mi_modules/mi_vdec/mi_vdec0
    参数说明 Status:on 打开 off 关闭
    举例 echo flowdbg on >/proc/mi_modules/mi_vdec/mi_vdec0
    打开vdec flow checkpoint,然后再敲cat /proc/mi_modules/mi_vdec/mi_vdec0可以在vdec procfs查看当前多个函数的checkpoint
    功能 打开/关闭丢帧开关,丢弃所有的解码输出数据帧,不输出到解码后端。
    命令 echo dropoutbuf [Status] > /proc/mi_modules/mi_vdec/mi_vdec0
    参数说明 Status:on 打开 off 关闭
    举例 echo dropoutbuf on > /proc/mi_modules/mi_vdec/mi_vdec0
    丢弃将要输出的frame buffer
    功能 打开/关闭vdec性能统计开关。将输出更详细的proc debug信息。
    命令 echo setperf [Status] >/proc/mi_modules/mi_vdec/mi_vdec0
    参数说明 Status:on 打开 off 关闭
    举例 echo setperf on >/proc/mi_modules/mi_vdec/mi_vdec0
    打开vdec性能统计开关,然后再敲cat /proc/mi_modules/mi_vdec/mi_vdec0可以在vdec procfs查看当前解码耗时等数据。
    功能 检查解码过程各状态消耗时间间隔。
    命令 echo flowstat [chn] [on/off] > /proc/mi_modules/mi_vdec/mi_vdec0
    参数说明 chn:通道号 [0~63]
    on/off:on 打开 off 关闭
    举例 echo flowstat 3 on >/proc/mi_modules/mi_vdec/mi_vdec0
    打开通道3的检查解码过程各状态消耗时间间隔功能。
    功能 静帧功能内部debug。(仅用于系统故障排查,请在技术支持人员的指导配合下使用)
    命令 echo refresh [chn] [pattern/dumpref/md5/clroutbuf] [on/off] [path] > /proc/mi_modules/mi_vdec/mi_vdec0
    参数说明 chn:通道号 [0~63]
    pattern/dumpref/md5/clroutbuf:
    pattern:不使用解码器的参考帧,使用本地文件解码输出NV12数据帧。
    dumpref:存储解码器用于解码输出NV12的参考帧。
    md5:检查静帧整个流程所有的md5值是否一致,检查踩内存问题debug打开。
    clroutbuf:转码前清空SCL输出buffer的数据。
    on/off:打开与关闭。
    path:本地文件与存储文件的路径。
    举例 echo refresh 3 md5 on /mnt/dump/ > /proc/mi_modules/mi_vdec/mi_vdec0
    通道3,打开静帧功能检查输出md5值。
    功能 强制重置channel。(等价于先StopChn然后重新StartChn,仅用于系统故障排查,请在技术支持人员的指导配合下使用)
    命令 echo reset_chn [chn] > /proc/mi_modules/mi_vdec/mi_vdec0
    参数说明 chn:通道号 [0~63]
    举例 echo reset_chn 0 > /proc/mi_modules/mi_vdec/mi_vdec0
    强制重置通道0。