第一次搞海思的嵌入式芯片,买的海思单板给的资料pack很多很多,花了一个月磕文档熟悉代码、框架。海思定义了reference层,middleware层,mpp层 一堆堆,reference 连产品形态都定义好了,比如行车记录仪,通过配置就可以已经实现如循环录像,紧急录像,WIFI+RTSP视频流。
海思的东东像其它文章说的那样它有自己一套理念,我们的目标就是说服自己接受这套理念然后装进大脑运用它,然后快速造出自己的ID产品。
MAPI 层内部处理流程如下图 所示,主要分为视频捕获(VCap)、视频处理
(VProc)、视频编码(VENC)、显示预览(DISP)、音频输入(AI)、音频输出(AO)、音
频编码(AENC)等模块。主要的处理流程介绍如下:
现在回过头来分析middleware/ndk/sample_venc.c 的代码。
function :SAMPLE_VENC_Record(HI_VOID)
实现功能:1080p30fps H.264 record
PS:启动VENC录像对于应用层来说其实就是一堆绑定再启动,绑定包括:DEV和VCAP的绑定,VCAP和VPSS的绑定,VPSS和VENC的绑定。
VCap { pipe { channel } }
Vpss { vport }
Venc { .0 .1 .2 .3 }
//------------------Vcap----------------------//
HI_HANDLE VcapDev0 = SAMPLE_MAPI_VCAP_DEV_0;
HI_HANDLE VcapPipe0 = SAMPLE_MAPI_VCAP_PIPE_0;
HI_HANDLE PipeChn0 = SAMPLE_MAPI_PIPE_CHN_0;
HI_MAPI_VCAP_ATTR_S stVcapAttr; //定义 VCAP 通路的属性
HI_MAPI_SENSOR_ATTR_S stVcapSensorAttr; //定义 Sensor 的模式(时序)属性。
SAMPLE_COMM_INITATTR_S stSampleCommAttr;
FILE* pFd[HI_MAPI_VENC_MAX_CHN_NUM] = {NULL};
//-----------------Vpss----------------------//
HI_HANDLE VpssHdl0 = 0;
HI_HANDLE VPortHdl0 = 0;
HI_BOOL bStitch = HI_FALSE;
HI_MAPI_VPSS_ATTR_S stVpssAttr; //定义 VPSS 输入属性的结构体。
HI_MAPI_VPORT_ATTR_S stVPortAttr; //VPort 输出图像信息
//----------------Venc-----------------------//
HI_HANDLE VencHdl0 = 0;
HI_HANDLE VencHdl1 = 1;
HI_S32 s32FrameCnt = -1;
HI_MAPI_VENC_ATTR_S stVencAttr; //定义视频编码属性结构体。
HI_MAPI_VENC_CALLBACK_S stVencBigStreamCb; //定义视频编码回调函数结构体。
2.1 sensor0 属性结构体的相关参数赋值 。
//-----------获取SAMPLE_SENSOR_1080P30模式的参数------------------//
SAMPLE_CHECK_GOTO(SAMPLE_COMM_GetSensorCfg(SAMPLE_SENSOR_1080P30, &stVcapSensorAttr)); //镜头采集配置模式
//---------------------------------------------------------------//
Sensor 的模式(时序)属性结构体:
typedef struct hiMAPI_SENSOR_ATTR_S {
HI_U32 u32SnsMode;//Sensor 的模式参数,用以区分不同时序。
WDR_MODE_E enWdrMode;//WDR 模式枚举,详情参考《HiMPP V4.0 媒体处理软件开发参考.pdf》 3518ev300不支持此参数。
SIZE_S stSize; //Sensor 的分辨率结构体
HI_MAPI_INPUT_DEV_ATTR_S stInputDevAttr;//前端输入设备的属性。
} HI_MAPI_SENSOR_ATTR_S;
//Sensor 所有模式下的序列通过配置文件 sensor_interface_cfg_params.c 中配置.
//----------SAMPLE_SENSOR_1080P30-----结构体成员赋值如下--------------------------//
const HI_MAPI_SENSOR_ATTR_S g_stSensor1080PMode0 = {
.u32SnsMode = 0,
.enWdrMode = WDR_MODE_NONE,
.stSize = {
.u32Width = 1920,
.u32Height = 1080,
}
};
2.2、[vcap.dev]结构体属性成员 赋值
SAMPLE_CHECK_GOTO(memcpy_s(&stVcapAttr.stVcapDevAttr, sizeof(HI_MAPI_VCAP_DEV_ATTR_S), &g_stDev1080P,
sizeof(HI_MAPI_VCAP_DEV_ATTR_S)));
相关结构体:
typedef struct hiMAPI_VCAP_ATTR_S {
HI_MAPI_VCAP_DEV_ATTR_S stVcapDevAttr; /* //VCAP DEV 的属性
HI_U32 u32PipeBindNum; //与 VCAP DEV 绑定的 VCAP PIPE 的总个数。 /*
HI_HANDLE aPipeIdBind[HI_MAPI_VCAP_MAX_PIPE_NUM]; //该 VCAP DEV 锁绑定的 PIPE 号 /*
HI_MAPI_VCAP_PIPE_ATTR_S
astVcapPipeAttr[HI_MAPI_VCAP_MAX_PIPE_NUM]; /* 与 VCAP PIPE 相关的属性
} HI_MAPI_VCAP_ATTR_S;
//定义 VCAP DEV 的属性。
typedef struct hiMAPI_VCAP_DEV_ATTR_S {
SIZE_S stBasSize; /*
//Bayer 域缩放之后的宽、高。BAS 只支持 1 倍,2 倍或者 3 倍缩小。静态属性。
//不过文档提了 Hi3559V200/Hi3518EV300 不支持 BAS。
VI_WDR_ATTR_S stWDRAttr;//WDR 属性,详情参考《HiMPP V4.0 媒体处理软件开发参考.pdf》
VI_INTF_MODE_E enIntfMode; /* //视频设备的接口模式
HI_U32 au32ComponentMask[VI_COMPMASK_NUM]; /* //分量掩码配置详情参考
VI_YUV_DATA_SEQ_E enDataSeq; /* //输入数据顺序(仅支持 yuv 格式) 详情参考《HiMPP V4.0 媒体处理软件开发参考.pdf》
VI_DATA_TYPE_E enInputDataType; /* //输入数据类型,Sensor 输入一般为 RGB,AD 输入一般为 YUV,详情参考《HiMPP V4.0 媒体处理软件开发参考.pdf》
} HI_MAPI_VCAP_DEV_ATTR_S;
//---------------------结构体变量赋值如下--------------------------//
const HI_MAPI_VCAP_DEV_ATTR_S g_stDev1080P = {
.stBasSize = { //估计这里没用的。。因为3518EV300不支持BAS。
.u32Width = 1920,
.u32Height = 1080,
},
.stWDRAttr = {
.enWDRMode = WDR_MODE_NONE,
}
};
2.3、[vcap.pipe.0] 理解为pipe输入结构体属性赋值
SAMPLE_CHECK_GOTO(memcpy_s(&stVcapAttr.astVcapPipeAttr[VcapPipe0], sizeof(HI_MAPI_VCAP_PIPE_ATTR_S),
&g_stPipe1080P30Fps, sizeof(HI_MAPI_VCAP_PIPE_ATTR_S)));
//----------------相关相关结构体-------------------------------//
typedef struct hiMAPI_VCAP_PIPE_ATTR_S {
HI_MAPI_PIPE_TYPE_E enPipeType; /*
FRAME_RATE_CTRL_S stFrameRate; /*
COMPRESS_MODE_E enCompressMode; /*
HI_BOOL bIspBypass; /*
VI_PIPE_BYPASS_MODE_E enPipeBypassMode; /*
#ifndef __HI3559AV100__
/* the attr is not support in current version */
FRAME_INTERRUPT_ATTR_S stFrameIntAttr; /*
#endif
HI_MAPI_PIPE_ISP_ATTR_S stIspPubAttr; /*
HI_MAPI_PIPE_CHN_ATTR_S astPipeChnAttr[HI_MAPI_PIPE_MAX_CHN_NUM]; /*
} HI_MAPI_VCAP_PIPE_ATTR_S;
//---------------------结构体变量赋值如下--------------------------//
const HI_MAPI_VCAP_PIPE_ATTR_S g_stPipe1080P30Fps = {
.stFrameRate = {//VCAP PIPE 的帧率控制结构体,详见《HiMPPV4.0 媒体处理软件开发参考》
.s32SrcFrameRate = -1,
.s32DstFrameRate = -1,
},
.enCompressMode = COMPRESS_MODE_NONE, //VCAP PIPE 的数据压缩格式
.bIspBypass = HI_FALSE,
.enPipeBypassMode = VI_PIPE_BYPASS_NONE,
.stIspPubAttr = {
.f32FrameRate = 30.0f, //!!!输入图像帧率。低于 sensor 时序最大帧率。动态属性。
.stSize = {//ISP 裁剪后的宽高,结构体详见《HiMPPV4.0 媒体处理软件开发参考.pdf》静态属性。
.u32Width = 1920,
.u32Height = 1080,
},
.enBayer = BAYER_RGGB,//Bayer 数据格式。枚举详见《Hi ISP 开发参考.pdf》静态属性。
}
};
2.4 、[vcap.pipe.0.chn.0] 理解为channel输出结构体属性赋值
SAMPLE_CHECK_GOTO(memcpy_s(&stVcapAttr.astVcapPipeAttr[VcapPipe0].astPipeChnAttr[PipeChn0],
sizeof(HI_MAPI_PIPE_CHN_ATTR_S), &g_stChn1080P30Fps, sizeof(HI_MAPI_PIPE_CHN_ATTR_S)));
//----------------相关相关结构体-------------------------------//
typedef struct hiMAPI_PIPE_CHN_ATTR_S {
SIZE_S stDestSize; /*
FRAME_RATE_CTRL_S stFrameRate; /*
COMPRESS_MODE_E enCompressMode; /*
PIXEL_FORMAT_E enPixelFormat; /*
} HI_MAPI_PIPE_CHN_ATTR_S;
//---------------------结构体变量赋值如下--------------------------//
const HI_MAPI_PIPE_CHN_ATTR_S g_stChn1080P30Fps = {
.stDestSize = { //目标分辨率
.u32Width = 1920,
.u32Height = 1080,
},
.stFrameRate = { //帧率控制结构体
.s32SrcFrameRate = 30,
.s32DstFrameRate = 30,
},
.enCompressMode = COMPRESS_MODE_NONE,//不压缩
.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420, //像素格式
};
2.5、 VB and media Attr 赋值
/* VB and media Attr */
SAMPLE_CHECK_GOTO(memset_s(&stSampleCommAttr, sizeof(SAMPLE_COMM_INITATTR_S), 0, sizeof(SAMPLE_COMM_INITATTR_S)));//清空结构体
SAMPLE_CHECK_GOTO(memset_s(&stSampleCommAttr.stViVpssMode, sizeof(VI_VPSS_MODE_S), 0, sizeof(VI_VPSS_MODE_S)));//清空结构体
//--------------------------------共用初始化属性赋值-------------------------------------------------------------//
stSampleCommAttr.stResolution.u32Width = stVcapSensorAttr.stSize.u32Width; //将sensor的分辨率给 stResolution分辨率
stSampleCommAttr.stResolution.u32Height = stVcapSensorAttr.stSize.u32Height; //
stSampleCommAttr.stViVpssMode.aenMode[VcapPipe0] = VI_ONLINE_VPSS_ONLINE; //PIPE 在线指的是 VI_ONLINE_VPSS_OFFLINE
stSampleCommAttr.u8SnsCnt = u8SnsCnt;
/* init VB and media */
//VB_MODE_1:not stitch Stitch 是对多路图像拼接,有四种拼接模式 3518EV300 不支持
SAMPLE_CHECK_GOTO(SAMPLE_COMM_InitBufWrap(stSampleCommAttr, VB_MODE_1, NULL));
//--------------函数内部------------------------//
HI_S32 SAMPLE_COMM_InitBufWrap(SAMPLE_COMM_INITATTR_S stSampleCommAttr, SAMPLE_VB_CFG_MODE_E enVbMode,
VPSS_CHN_BUF_WRAP_S *pstVpssChnBufWrap)
{
HI_S32 s32Ret = HI_SUCCESS;
/* start media */
HI_MAPI_MEDIA_ATTR_S stMediaAttr; //定义媒体配置属性结构体。
HI_U32 u32BlkSize;
SAMPLE_CHECK_RET(memset_s(&stMediaAttr, sizeof(HI_MAPI_MEDIA_ATTR_S), 0, sizeof(HI_MAPI_MEDIA_ATTR_S)));//清空stMediaAttr
SAMPLE_CHECK_RET(memset_s(&stMediaAttr.stMediaConfig.stVIVPSSMode, sizeof(VI_VPSS_MODE_S), 0,/*清空stMediaAttr.stMediaConfig.stVIVPSSMode*/
sizeof(VI_VPSS_MODE_S)));
SAMPLE_CHECK_RET(memcpy_s(&stMediaAttr.stMediaConfig.stVIVPSSMode, sizeof(VI_VPSS_MODE_S),
&stSampleCommAttr.stViVpssMode, sizeof(VI_VPSS_MODE_S))); //赋值 VIVPSS模式
//--------------------------VB 配置参数------------------------------------------------------//
/* typedef struct hiVB_CONFIG_S
{
HI_U32 u32MaxPoolCnt; // max count of pools, (0,VB_MAX_POOLS] 整个系统中可容纳的缓存池个数。
VB_POOL_CONFIG_S astCommPool[VB_MAX_COMM_POOLS]; 公共缓存池属性结构体。
} VB_CONFIG_S;
*/
stMediaAttr.stMediaConfig.stVbConfig.u32MaxPoolCnt = 32; //整个系统中可容纳的缓存池个数。
if (VB_MODE_1 == enVbMode) {
//视频缓存池大小计算接口 接口简介
//VI_GetRawBufferSize VI 写出的 Raw 数据缓存池
//COMMON_GetPicBufferSize 一般 linear(线性存储)) 格式的 YUV 各部分数据大小
u32BlkSize = VI_GetRawBufferSize(stSampleCommAttr.stResolution.u32Width, /* 原始数据RGB*/
stSampleCommAttr.stResolution.u32Height, PIXEL_FORMAT_RGB_BAYER_12BPP, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
stMediaAttr.stMediaConfig.stVbConfig.astCommPool[0].u64BlkSize = u32BlkSize; //缓存块 大小,以 Byte 位单位。
stMediaAttr.stMediaConfig.stVbConfig.astCommPool[0].u32BlkCnt = 2; //每个缓存池的 缓存块 个数。
u32BlkSize = COMMON_GetPicBufferSize(stSampleCommAttr.stResolution.u32Width,
stSampleCommAttr.stResolution.u32Height, PIXEL_FORMAT_YVU_SEMIPLANAR_420,
DATA_BITWIDTH, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
stMediaAttr.stMediaConfig.stVbConfig.astCommPool[1].u64BlkSize = u32BlkSize;
stMediaAttr.stMediaConfig.stVbConfig.astCommPool[1].u32BlkCnt = 2;
u32BlkSize = COMMON_GetPicBufferSize(640, 480, PIXEL_FORMAT_YVU_SEMIPLANAR_420, DATA_BITWIDTH,
COMPRESS_MODE_NONE, DEFAULT_ALIGN);
stMediaAttr.stMediaConfig.stVbConfig.astCommPool[2].u64BlkSize = u32BlkSize;
stMediaAttr.stMediaConfig.stVbConfig.astCommPool[2].u32BlkCnt = 3;
}
stMediaAttr.stVencModPara.u32H264eLowPowerMode = 1; //H264 低功耗模式
stMediaAttr.stVencModPara.u32H265eLowPowerMode = 1; //H265 低功耗模式
//初始化媒体相关各模块的资源。
//包括:读取 Sensor,DIS 相关配置文件,设置 VI 和 VPSS 在线离线模式、VB 个数和大小、VENC 相关模块低功耗模式,然后做媒体业务的初始化工作
s32Ret = HI_MAPI_Media_Init(&stMediaAttr);
if (s32Ret != HI_SUCCESS) {
printf("HI_MAPI_Media_Init error:%#x.\n", s32Ret);
return HI_FAILURE;
}
return HI_SUCCESS;
}
2.6、vcap通路属性的参数通过上面的赋值,现在开始初始化和启动 vcap!
//----------------venc调用的接口--------------------------------------//
SAMPLE_VCAP_CreateSingle(VcapDev0, VcapPipe0, PipeChn0, &stVcapSensorAttr, &stVcapAttr)
//--------------- 函数内部功能----------------------------------------------//
HI_S32 SAMPLE_VCAP_CreateSingle(HI_HANDLE VcapDevHdl, HI_HANDLE VcapPipeHdl, HI_HANDLE PipeChnHdl,
HI_MAPI_SENSOR_ATTR_S* pstVcapSensorAttr, HI_MAPI_VCAP_ATTR_S* pstVcapAttr)
{
HI_S32 s32Ret = HI_SUCCESS;
//功能:初始化 sensor,包含以什么样的 sensor 属性(时序)进行 sensor 的初始化。其中,Sensor 所有模式下的序列通过配置文件 sensor_interface_cfg_params.c 中配置 .
//VcapDevHdl:Sensor 所在的 VCAP DEV 的 Handle 号。pstSensorAttr:Sensor 属性(或称时序)。bResetSensor:是否需要复位 Sensor 时钟标志位。bResetSensor 只有在 IPC 业务下置为 False,正常流程下传入 True。
SAMPLE_CHECK_RET(HI_MAPI_VCAP_InitSensor(VcapDevHdl, pstVcapSensorAttr, HI_TRUE));
//功能:设置 VCAP 通路属性。
//注意:1、必须先初始化 Sensor 才能设置 VCAP 属性。
// 2、这个接口将设置 VCAP 整个通路的属性以及绑定关系包括:VCAP DEV 属性、VCAP PIPE 属性、ISP PUB 属性、VCAP CHN 属性、VCAP DEV 与 VCAP PIPE的绑定关系
//VcapDevHdl :VCAP DEV 的 Handle 号。 pstVCapAttr:VCAP 属性。
SAMPLE_CHECK_RET(HI_MAPI_VCAP_SetAttr(VcapDevHdl, pstVcapAttr));
//启动 VCAP DEV
SAMPLE_CHECK_RET(HI_MAPI_VCAP_StartDev(VcapDevHdl));
//启动 VCAP CHN
SAMPLE_CHECK_RET(HI_MAPI_VCAP_StartChn(VcapPipeHdl, PipeChnHdl));
//初始化 ISP
SAMPLE_CHECK_RET(HI_MAPI_VCAP_InitISP(VcapPipeHdl));
//启动 VCAP PIPE
SAMPLE_CHECK_RET(HI_MAPI_VCAP_StartPipe(VcapPipeHdl));
//启动 ISP 处理单元
SAMPLE_CHECK_RET(HI_MAPI_VCAP_StartISP(VcapPipeHdl));
return s32Ret;
}
这里其实我有点蒙圈的,stVcapSensorAttr理解为给sensor的初始化用, stVcapAttr.stVcapDevAttr 理解为 给 Vcap(通路属性这个抽象概念)定义的dev对象用。 通过 VcapDevHdl 把它们链接了起来。
typedef struct hiMAPI_VPSS_ATTR_S {
HI_U32 u32MaxW; // 需要处理的 VPSS 输入数据的最大宽度。
HI_U32 u32MaxH; // 需要处理的 VPSS 输入数据的最大高度。
FRAME_RATE_CTRL_S stFrameRate; //帧率控制结构体,其中-1 代表不做帧率控制,详情请参考《HiMPP V4.0 媒体处理软件开发参考》
PIXEL_FORMAT_E enPixelFormat; //输入图像的像素格式
HI_BOOL bNrEn;//NR 去噪开关。
VPSS_NR_ATTR_S stNrAttr;//NR 属性结构体,详情请参考《HiMPP V4.0 媒体处理软件开发参考》。
} HI_MAPI_VPSS_ATTR_S;
######################配置VPSS 输入数据######################
const HI_MAPI_VPSS_ATTR_S g_stVpss1080P30Fps = {
.u32MaxW = 1920,
.u32MaxH = 1080,
.stFrameRate = {
.s32SrcFrameRate = 30,
.s32DstFrameRate = 30,
},
.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420,
.bNrEn = HI_TRUE,
.stNrAttr = {
.enCompressMode = COMPRESS_MODE_NONE,
.enNrMotionMode = NR_MOTION_MODE_NORMAL,
},
};
typedef struct hiMAPI_VPORT_ATTR_S {
HI_U32 u32Width;//VPort 输出宽度取值范围:[32, 8192]。
HI_U32 u32Height;//VPort 输出高度取值范围:[32, 8192]。
HI_BOOL bSupportBufferShare;//是否支持输入输出复用 buffer。
//只有 Hi3559V200 与 Hi3518EV300 支持 bSupportBufferShare。
FRAME_RATE_CTRL_S stFrameRate;//帧率控制结构体,其中-1 代表不做帧率控制,详情请参考《HiMPP V4.0 媒体处理软件开发参考》。
VIDEO_FORMAT_E enVideoFormat;//VPort 输出的视频存储格式,详情请参考《HiMPPV4.0 媒体处理软件开发参考》。
PIXEL_FORMAT_E enPixelFormat;//VPort 输出的像素格式,详情请参考《HiMPP V4.0媒体处理软件开发参考》。
COMPRESS_MODE_E enCompressMode;//VPort 输出的压缩格式。支持HI_COMPRESS_MODE_NONE 和HI_COMPRESS_MODE_SEG,详情请参考《HiMPP V4.0 媒体处理软件开发参考》
ASPECT_RATIO_S stAspectRatio;//视频层内视频的幅型比,详情请参考《HiMPP V4.0媒体处理软件开发参考》。
} HI_MAPI_VPORT_ATTR_S;
######################配置VPSS的 vport输出######################
const HI_MAPI_VPORT_ATTR_S g_stVport1080P30Fps = {
.u32Width = 1920,
.u32Height = 1080,
.stFrameRate = {
.s32SrcFrameRate = 30,
.s32DstFrameRate = 30,
},
.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420,
.enVideoFormat = VIDEO_FORMAT_LINEAR, //线性存储的视频格式
.enCompressMode = COMPRESS_MODE_NONE, //非压缩的视频格式
};
图像模式 YUV 数据 enVideoFormat 必须为 VIDEO_FORMAT_LINEAR。
图像模式 YUV 数据 enCompressMode 必须为非压 COMPRESS_MODE_NONE。
初始化、绑定和启动工作( 绑定是后者(vpss)绑定前者(vcap)).
//初始化一个 vpss 处理单元 VpssHdl:vpss handle 号,pstVpssAttr:vpss 属性指针。
SAMPLE_CHECK_GOTO(HI_MAPI_VPROC_InitVpss(VpssHdl0, &stVpssAttr));
//将 VPROC 和 Vcap 绑定,用于接收 Vcap 的图像。VcapPipeHdl:capPipe handle 号
//PipeChnHdl:PipeChn handle 号。 VpssHdl :vpss handle 号
SAMPLE_CHECK_GOTO(HI_MAPI_VPROC_BindVcap(VcapPipe0, PipeChn0, VpssHdl0));
//配置 VPort 输出的图像属性。 VpssHdl:vpss handle 号.
//VPortHdl :VPort handle 号。 pstVPortAttr:VPort 输出图像属性信息结构体。
SAMPLE_CHECK_GOTO(HI_MAPI_VPROC_SetPortAttr(VpssHdl0, VPortHdl0, &stVPortAttr));
//启动 VPort,输出图像。VpssHdl:vpss handle 号。 VPortHdl: VPort handle 号。
SAMPLE_CHECK_GOTO(HI_MAPI_VPROC_StartPort(VpssHdl0, VPortHdl0));
相关结构体如下:
/* the attribute of video encode */
typedef struct hiMAPI_VENC_ATTR_S {
HI_MAPI_VENC_TYPE_ATTR_S stVencPloadTypeAttr; /*
HI_MAPI_VENC_RC_ATTR_S stRcAttr; /*
} HI_MAPI_VENC_ATTR_S;
/*
the attribute of encoder type */
typedef struct hiMAPI_VENC_TYPE_ATTR_S {
HI_MAPI_PAYLOAD_TYPE_E enType; /* //编码类型
HI_U32 u32Width; /*
HI_U32 u32Height; /*
HI_U32 u32BufSize; /*
HI_U32 u32Profile; /*
HI_MAPI_VENC_SCENE_MODE_E enSceneMode; /*
union {
HI_MAPI_VENC_ATTR_H264_S stAttrH264e; /*
HI_MAPI_VENC_ATTR_H265_S stAttrH265e; /*
HI_MAPI_VENC_ATTR_JPEG_S stAttrJpege; /*
HI_MAPI_VENC_ATTR_MJPEG_S stAttrMjpeg; /*
};
} HI_MAPI_VENC_TYPE_ATTR_S;
/* the attribute of rate control */
typedef struct hiMAPI_VENC_RC_ATTR_S {
HI_MAPI_VENC_RC_MODE_E enRcMode; /*
union {
HI_MAPI_VENC_ATTR_CBR_S stAttrCbr; /*
HI_MAPI_VENC_ATTR_VBR_S stAttrVbr; /*
HI_MAPI_VENC_ATTR_QVBR_S stAttrQVbr; /*
HI_MAPI_VENC_ATTR_CVBR_S stAttrCVbr; /*
HI_MAPI_VENC_ATTR_AVBR_S stAttrAVbr; /*
};
} HI_MAPI_VENC_RC_ATTR_S;
typedef struct hiVENC_H264_CBR_S
HI_MAPI_VENC_ATTR_CBR_S;
/* the attribute of h264e cbr */
typedef struct hiVENC_H264_CBR_S {
HI_U32 u32Gop; /* RW; Range:[1, 65536]; the interval of I Frame. */
HI_U32 u32StatTime; /* RW; Range:[1, 60]; the rate statistic time, the unit is senconds(s) *///CBR 码率统计时间,以秒为单位。
HI_U32 u32SrcFrameRate; /* RW; Range:[1, 240]; the input frame rate of the venc chnnel */
HI_FR32 fr32DstFrameRate ; /* RW; Range:[0.015625, 240]; the target frame rate of the venc chnnel,can not be larger than u32SrcFrameRate */
HI_U32 u32BitRate; /* RW; Range:[2, 614400]; average bitrate */
} VENC_H264_CBR_S;
typedef enum hiMAPI_VENC_SCENE_MODE_E
{
HI_MAPI_VENC_SCENE_MODE_NORMAL, /**
HI_MAPI_VENC_SCENE_MODE_DV, /**
HI_MAPI_VENC_SCENE_MODE_CAR, /**
HI_MAPI_VENC_SCENE_MODE_BUTT,
}HI_MAPI_VENC_SCENE_MODE_E;
//-------HI_MAPI_VENC_ATTR_S 视频编码属性结构体:定义H264参数配置。-----------//
const HI_MAPI_VENC_ATTR_S g_stVenc1080P30FpsVideoH264 = {
.stVencPloadTypeAttr = {
.enType = HI_MAPI_PAYLOAD_TYPE_H264,
.u32Width = 1920,
.u32Height = 1080,
.u32BufSize = 1920 * 1080 * 3 / 2,
.u32Profile = 0,
.enSceneMode = HI_MAPI_VENC_SCENE_MODE_DV,//dv scene mode
},
.stRcAttr = {
.enRcMode = HI_MAPI_VENC_RC_MODE_CBR, //constant bit rate
.stAttrCbr = {
.u32Gop = 30,
.u32StatTime = 2,
.u32SrcFrameRate = 30,
.fr32DstFrameRate = 30,
.u32BitRate = 4096,
}
}
};
/* venc 0 H264 big stream */
SAMPLE_CHECK_GOTO(memcpy_s(&stVencAttr, sizeof(HI_MAPI_VENC_ATTR_S), &g_stVenc1080P30FpsVideoH264,
sizeof(HI_MAPI_VENC_ATTR_S)));
初始化、绑定和启动工作( 绑定是后者(VENC)绑定前者(vpss)).
//aFilePath : /sharefs/SAMPLE_VENC_Record_chn0.h264
pFd[VencHdl0] = SAMPLE_AUDIO_OpenVideoFile(aFilePath); //返回已经打开文件的句柄
stVencBigStreamCb.pfnDataCB = SMAPLE_COMM_VENC_DataProc;//回调处理函数。用于获取编码数据。
stVencBigStreamCb.pPrivateData = pFd[VencHdl0]; //私有数据指针。作为参数,在 PFN_VENC_DataProc 中被调用。
//初始化编码通道。 VencHdl:VENC 通道号。 pstVencAttr: VENC 通道属性指针。
SAMPLE_CHECK_GOTO(HI_MAPI_VENC_Init(VencHdl0, &stVencAttr));
//注册编码通道回调函数,用于编码数据的获取(stVencBigStreamCb会将.h264数据流写到文件)。
//VencHdl:VENC 通道号。 pstVencCB:编码器回调函数结构体指针。
SAMPLE_CHECK_GOTO(HI_MAPI_VENC_RegisterCallback(VencHdl0, &stVencBigStreamCb));
//绑定 VProc 输入端。 bStitch=0 非拼接
SAMPLE_CHECK_GOTO(HI_MAPI_VENC_BindVProc(VpssHdl0, VPortHdl0, VencHdl0, bStitch));
//启动编码通道。
SAMPLE_CHECK_GOTO(HI_MAPI_VENC_Start(VencHdl0, s32FrameCnt));
至此启动步骤就分析得7788了;在单板上运行例程,成功运行情况下文件存储路径就会看到生成的SAMPLE_VENC_Record_chn0.h264文件。
END!