Lynnon/cvi_mmf_sdk: testforimageburning (github.com)
Overview
【IPC网络摄像机】,是IP Camera的简称。它是在前一代模拟摄像机的基础上,集成了编码模块后的摄像机。它和模拟摄像机的区别,就是在新增的“编码模块”上。
模拟摄像机,顾名思义,输出的是模拟视频信号。模拟信号比较容易受到干扰,所以传输距离有限。哪里有瓶颈,哪里就有创新。把模拟信号变为数字信号,传输距离就变远了。因此这个新增的编码模块就出现了,就是为了把原来模拟视频编码压缩后,变为数字视频,为了方便在网络上传输,把数字视频封装为网络格式的,以适合在以太网上传输。我们就叫这新的摄像机为“网络摄像机”,简称IPC。
Code flow
#define CVI_MAX_BIND_NUM 10
typedef struct APP_PARAM_VB_CFG_T {
CVI_BOOL bEnable;
uint32_t size;
uint32_t width;
uint32_t height;
PIXEL_FORMAT_E fmt;
DATA_BITWIDTH_E enBitWidth;
COMPRESS_MODE_E enCmpMode;
uint32_t vb_blk_num;
} APP_PARAM_VB_CFG_S;
#define APP_IPCAM_VB_POOL_MAX_NUM (16)
typedef struct APP_PARAM_SYS_CFG_T {
APP_PARAM_VB_CFG_S vb_pool[APP_IPCAM_VB_POOL_MAX_NUM];
uint32_t vb_pool_num;
VI_VPSS_MODE_S stVIVPSSMode;
VPSS_MODE_S stVPSSMode;
} APP_PARAM_SYS_CFG_S;
main 函数主要结构,做一系列的初始化之后启动模块。初始化过程与CVI_TEST的初始化过程有一定的相似度。
1.参数读取。 首先查看模块参数读取函数,在这个函数当中需要读取IPC的配置值文件,将文件加载到程序的结构体当中,便于之后的各个模块的init。下面以_Load_Param_Vi_Load_Param_Vi函数为例子,我们可以看到程序基本上是按照配置文件所提供的参数进行初始化。
函数框架如下:
2.模块初始化。 经过前面的参数读取之后,获取到各个模块的配置参数在此函数中对Sys、VI、VB、OSD、Venc、AI、如果拥有音频也可以对Audio进行初始化。
2.1 外设的设置
2.2 app_ipcam_Sys_Init,设置启动的设备号,对VB pool进行初始化,循环对所有的池子内的config进行初始化。然后调用COMM_SYS_Init(将之前的状态销毁掉再对VB初始化;设置VPSS状态;设置VPSS扩展模式)
2.3 app_ipcam_Vi_Init,启动VI、摄像头启动、屏幕启动、设备启动、Pipe start、Isp的初始化以及启动Isp、Chn的获取并使能。
2.4 app_ipcam_Vpss_Init,创造组并做组初始化,然后进行判断是否为online模式然后进行crop的组设置,之后的操作与vi的chn设置流程基本一致,设置Vpss chn信息以及crop chn,然后使之使能,之后设置通道以从指定池中获取 VB,启动VPSS group,判断是否要绑定然后调用CVI_SYS_Bind进行两个chn的绑定。
2.5 app_ipcam_Osd_Init,获取VPSS的模式之后,创造OSD,在创造OSD的需要根据enType以及VPSSMODE去设置不同的宽高,然后创造RGN,RGN 应用于chn,然后对OSD上的位图进行更新。
2.6 app_ipcam_Cover_Init,本模块初始化过程与OSD过程相似。
2.7 app_ipcam_Osdc_Init,同样的模块的初始化过程与OSD相似。
2.8 app_ipcam_WebSocket_Init,创建一个线程简建立LWS并且对里面的一些属性进行配置,创建lws上下文,设立context的一个延迟时间1000ms,在进行销毁。
2.7 app_ipcam_Venc_Init,创建模块内存,进行VENC chn的设置,进行GOP的设置,进行码率设置,然后就是创建ENC的chn,在使之与vb的内存相互连接。然后根据编码模式设置码率参数,接着设置Mjpeg码率编码通道的模式最后绑定VI的两个chn。
3.RTSP服务器的初始化。 RTSP(Real Time Streaming Protocol)是由Real Network和Netscape共同提出的如何有效地在IP网络上传输流媒体数据的应用层协议。RTSP对流媒体提供了诸如暂停,快进等控制,而它本身并不传输数据,RTSP的作用相当于流媒体服务器的远程控制。服务器端可以自行选择使用TCP或UDP来传送串流内容,它的语法和运作跟HTTP 1.1类似,但并不特别强调时间同步,所以比较能容忍网络延迟。
数据结构:
模块代码结构:
先从视频属性更新视频流编解码器类型,创建RTSP,设置互斥锁启动RTSP、创建RTSP会话、并设置为监听状态,然后释放掉当前的锁。
5.关于AI模块——运动检测初始化。
5.1 app_ipcam_Ai_Param_dump 做参数转存
5.1 CVI_AI_CreateHandle创建一个cviai_handle_t,会自动找一个vpss group id。
5.2 CVI_AI_Service_CreateHandle创建一个 cviai_service_handle_t,然后设置摄像机状态。
6.关于SD卡的创建。
另外起一个线程,启动Thread_Record_Proc函数通过打开proc/mounts并且判断是否有文件的访问权限之后,判断SD卡是都已经挂载然后调用create函数,在该函数中先使用fsck检测存储卡状态,然后初始化存储库,获取卡的状态判断其是已经进行初始化不是则自己在进行初始化,然乎设置号好存储状态。
7.app_ipcam_CmdTask_Create,启用从另一个测试 ipcam 的进度接收命令。
SYS
框架
初始化系统。 包括视频输入输出、视频编解码、视频叠加区域、视频处理、音频输入输出等模块都会被初始化。
Code trace
系统配置相关:
typedef struct APP_PARAM_VB_CFG_T {
CVI_BOOL bEnable;//被使用否
uint32_t size;
uint32_t width;
uint32_t height;
PIXEL_FORMAT_E fmt;// 像素格式
DATA_BITWIDTH_E enBitWidth;// 位深?
COMPRESS_MODE_E enCmpMode;//压缩格式
uint32_t vb_blk_num;//块数
} APP_PARAM_VB_CFG_S;
#define APP_IPCAM_VB_POOL_MAX_NUM (16)
typedef struct APP_PARAM_SYS_CFG_T {
APP_PARAM_VB_CFG_S vb_pool[APP_IPCAM_VB_POOL_MAX_NUM];// 池子里的配置 16个
uint32_t vb_pool_num;// 池子数量
VI_VPSS_MODE_S stVIVPSSMode;//
VPSS_MODE_S stVPSSMode;//VPSS 模式
CVI_BOOL bSBMEnable;
} APP_PARAM_SYS_CFG_S;
SDK_VB_配置
/*
* u32BlkSize: size of blk in the pool.
* u32BlkCnt: number of blk in the pool.
* enRemapMode: remap mode.
*/
#define MAX_VB_POOL_NAME_LEN (32)
typedef struct _VB_POOL_CONFIG_S {
CVI_U32 u32BlkSize;
CVI_U32 u32BlkCnt;
VB_REMAP_MODE_E enRemapMode;
CVI_CHAR acName[MAX_VB_POOL_NAME_LEN];
} VB_POOL_CONFIG_S;
/*
* u32MaxPoolCnt: number of common pools used.
* astCommPool: pool cfg for the pools.
*/
typedef struct _VB_CONFIG_S {
CVI_U32 u32MaxPoolCnt;
VB_POOL_CONFIG_S astCommPool[VB_MAX_COMM_POOLS];
} VB_CONFIG_S;
(关注点:前面起始已经有了VB 后面为什么还需要这个呢?)对前面的进行初始化后转移到这个的VB结构体文件里。
CVI_VI_SetDevNum,对于 vi 设备 设置 vi 设备号,使用函数获取到的对象。
COMMON_GetPicBufferSize,通过像素模式,宽高等信息获取VB大小。
COMM_SYS_Init
CVI_VB_SetConfig,配置配置區塊池属性,设置VB,初始化过程与VPSS相关类似定义驱动的cvi_vb_cfg,获取fd之后,使用驱动的cfg接受参数的配置使用ioctl进行创建。
CVI_VB_Init,初始化MMF 视频區塊池。
CVI_SYS_Init,初始化系统。 包括视频输入输出、视频编解码、视频叠加区域、视频处理、音频输入输出等模块都会被初始化 。
CVI_SYS_SetVIVPSSMode,设置VI—VPSS模式
CVI_SYS_SetVPSSModeEx,设置VPSS扩展模式
VI
框架
视频输入(VI)模块实现的功能:通过 MIPI Rx(含 MIPI 接口、LVDS 接口和 HISPI 接口),BT.1120,BT.656,BT.601 等接口接收视频数据。VI 将接收到的数据存入到指定的内存区域,VI 可以对接收到的原始视频图像数据进行处理,实现视频数据的采集。
Code trace
最大的结构体分析:
typedef` `struct` `APP_PARAM_VI_CFG_T {`
CVI_U32 u32WorkSnsCnt;
APP_PARAM_SNS_CFG_T astSensorCfg[VI_MAX_DEV_NUM];// SNS属性
APP_PARAM_DEV_CFG_T astDevInfo[VI_MAX_DEV_NUM];// 设备属性
APP_PARAM_PIPE_CFG_T astPipeInfo[VI_MAX_DEV_NUM];// PIPE 属性
APP_PARAM_CHN_CFG_T astChnInfo[VI_MAX_DEV_NUM];// CHN 属性
APP_PARAM_SNAP_INFO_T astSnapInfo[VI_MAX_DEV_NUM];//
APP_PARAM_ISP_CFG_S astIspCfg[VI_MAX_DEV_NUM];// ISP
CVI_U32 u32Depth;
SIZE_S stSize;
} APP_PARAM_VI_CTX_S;
CVI_SYS_VI_Open,打开VI 设备
app_ipcam_Vi_Sensor_Start,启动摄像头
pfnPatchRxAttr、pfnSetInit、pfnSetBusInfo、pfnPatchI2cAddr、pfnRegisterCallback、pfnExpSensorCb
使用应用层的摄像机属性对rx_init_attr进行赋值,赋值完成之后使用pfnSnsObj的函数指针进行赋值RX。
之后分别设置总线地址、I2C地址、2A算法回调、关于摄像头的其他模式设置。
app_ipcam_Vi_Mipi_Start,启动屏幕
获取一个屏幕的对象,重置一下色摄像头,对屏幕进行重置、设置时钟信息、设置屏幕的属性(使用ioctl对combo_dev_attr进行设置)、UNset摄像机
app_ipcam_Vi_Dev_Start,启动VI设备
Vi 设备属性
typedef struct _VI_DEV_ATTR_S {
VI_INTF_MODE_E enIntfMode; /* Sensor 接口模式 */
VI_WORK_MODE_E enWorkMode; /* 1、2、4 路复合工作模式 */
VI_SCAN_MODE_E enScanMode; /* 输入扫描模式 (逐行、隔行)*/
CVI_S32 as32AdChnId[VI_MAX_ADCHN_NUM]; /* RW取值范围[-1, 3],推荐统㇐设置为默认值-1,此参数无意 义。 */
/* 以下成员必须在BT.601模式或DC模式下配置,在其他模式下无效 */
VI_YUV_DATA_SEQ_E enDataSeq; /* 输入数据顺序 (仅支持 yuv 格式) */
VI_SYNC_CFG_S stSynCfg; /* 同步时序配置,BT.601 模式时必须配置,其它模式时无效。 */
VI_DATA_TYPE_E enInputDataType;//输入数据类型,Sensor 输入㇐般为 RGB,AD 输入㇐般为 YUV。
SIZE_S stSize; /* RW;Input size */
VI_WDR_ATTR_S stWDRAttr; /* RW;Attribute of WDR */
BAYER_FORMAT_E enBayerFormat; /* RW;Bayer format of Device */
CVI_U32 chn_num; /* R; 设备的通道数 */
CVI_U32 snrFps; /* R; snr init fps from isp pub attr */
} VI_DEV_ATTR_S;
app_ipcam_Vi_DevAttr_Get,使用memcpy 将vi_dev_attr_base基本配置赋值到VI_DEV_ATTR_S *pstViDevAtt,然后对enBayerFormat进行赋值,在使用APP 的宽高对VI 设备的宽高赋值
CVI_VI_SetDevAttr,设置 VI 设备属性
CVI_VI_EnableDev,使能设备。先检查是否SetDevAttr,通过宽高的检查判断是否进行初始化,然后使用vi_sdk_enable_dev调用底层ioctl进行初始化设备。
app_ipcam_Vi_Pipe_Start,启动Pipe
app_ipcam_Vi_PipeAttr_Get,使用vi_pipe_attr_base,利用memcpy进行拷贝赋值,在依据sensor的格式对bYuvBypassPath进行取值。
CVI_VI_CreatePipe,在创建和Startd的时候APP_PARAM_PIPE_CFG_T与VI_PIPE_ATTR_S的作用不一,在APP层面是为了得到chn的ID 但是在实际的初始化过程使用VI_PIPE_ATTR_S传参进行初始化。
CVI_VI_StartPipe,创建VI Pipe
app_ipcam_Vi_Isp_Init,初始化ISP
向 ISP 注册 AWB 库、注册AE库。注册完毕之后会检查是否已经安装完毕
CVI_ISP_SetBindAttr,设置 ISP 库与 3A 库、 sensor 的绑定关系。
CVI_ISP_MemInit,初始化 ISP 外部寄存器。
app_ipcam_Isp_PubAttr_Get,内部其实还是利用事先定义好的结构体数值进行赋值
CVI_ISP_SetPubAttr,设置ISP的公共属性
CVI_ISP_SetStatisticsConfig,设置 ISP 统计讯息配置,在此之前会对很多的库的参数进行配置。
CVI_ISP_Init,初始化 ISP firmware。
CVI_BIN_SetBinName,设置PQBIN 存放的路径和文件名
app_ipcam_PQBin_Load =====>CVI_BIN_ImportBinData,从PQBin 中解析所有模块的数据
app_ipcam_Vi_Isp_Start,启动ISP
app_ipcam_Vi_Chn_Start,启动vi chn
app_ipcam_SnsObj_Get ,获取摄像头类型
app_ipcam_Vi_DevAttr_Get,通过获取摄像头的类型设置设备的 Bayer 格式,同时使用利用memcpy进行拷贝赋值。
app_ipcam_Vi_ChnAttr_Get,通过摄像头类型设置设备的像素格式。
CVI_VI_SetChnAttr,设置 VI 通道属性。设置的过程中需要保持现有、目的帧率的相同,使用IOCTL进行设置。
CVI_VI_EnableChn,使能chn,物理chn 有三个
VPSS
框架
Code trace
typedef struct APP_PARAM_VPSS_CFG_S {
CVI_U32 u32GrpCnt;
APP_VPSS_GRP_CFG_T astVpssGrpCfg[CVI_MAX_VPSS_GRP];
} APP_PARAM_VPSS_CFG_T;
typedef struct APP_VPSS_GRP_CFG_S {
VPSS_GRP VpssGrp;
CVI_BOOL bEnable; /* update by ini file */
CVI_BOOL bCreate; /* update by coding */
VPSS_GRP_ATTR_S stVpssGrpAttr;
VPSS_CROP_INFO_S stVpssGrpCropInfo;
CVI_BOOL abChnEnable[VPSS_MAX_PHY_CHN_NUM]; /* update by ini file */
CVI_BOOL abChnCreate[VPSS_MAX_PHY_CHN_NUM]; /* update by coding */
VPSS_CHN_ATTR_S astVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];
VPSS_CROP_INFO_S stVpssChnCropInfo[VPSS_MAX_PHY_CHN_NUM];
CVI_U32 aAttachEn[VPSS_MAX_PHY_CHN_NUM];
CVI_U32 aAttachPool[VPSS_MAX_PHY_CHN_NUM];
CVI_BOOL bBindMode;
MMF_CHN_S astChn[2];//定义模块通道结构体
} APP_VPSS_GRP_CFG_T;
CVI_VPSS_CreateGrp 创建GRP函数
typedef struct APP_PARAM_SYS_CFG_T {
APP_PARAM_VB_CFG_S vb_pool[APP_IPCAM_VB_POOL_MAX_NUM];
uint32_t vb_pool_num;
VI_VPSS_MODE_S stVIVPSSMode;
VPSS_MODE_S stVPSSMode;
} APP_PARAM_SYS_CFG_S;
获取一个存放VB以及关于VPSS模块的一个结构体,再获取一个关于组的结构体的配置。里面包含着组的一些属性,通道属性,绑定模式。
typedef struct APP_VPSS_GRP_CFG_S {
VPSS_GRP VpssGrp;
CVI_BOOL bEnable; /* update by ini file */
CVI_BOOL bCreate; /*创建的标志位 */
VPSS_GRP_ATTR_S stVpssGrpAttr;//定义 VPSS GROUP 属性。
VPSS_CROP_INFO_S stVpssGrpCropInfo;//定义 CROP 功能所需信息。
CVI_BOOL abChnEnable[VPSS_MAX_PHY_CHN_NUM]; /* update by ini file */
CVI_BOOL abChnCreate[VPSS_MAX_PHY_CHN_NUM]; /* update by coding */
VPSS_CHN_ATTR_S astVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];//定义 VPSS 物理通道属性。
VPSS_CROP_INFO_S stVpssChnCropInfo[VPSS_MAX_PHY_CHN_NUM];//定义 裁剪功能所需信息
CVI_U32 aAttachEn[VPSS_MAX_PHY_CHN_NUM];// 与VB之间的数量管关系
CVI_U32 aAttachPool[VPSS_MAX_PHY_CHN_NUM];// 对VPSS 创建内存池的时候会使用到
CVI_BOOL bBindMode;
MMF_CHN_S astChn[2];// 后期绑定使用
} APP_VPSS_GRP_CFG_T;
再创建一个Grp的过程中需要我们使用一个vpss_crt_grp_cfg这样的第一结构体去接受传入的组的结构体参数,并且使用传入的组号对内核的Grp进行创建,最后使用IOCTL来创建GRP。
CVI_VPSS_ResetGrp创建完毕之后进行复位,我理解的让组进行复位的目的就是为了让GRP进入某种状态
使用IOCT进行复位设置。
CHN的属性配置
CVI_VPSS_SetChnAttr函数,通过传入的GRPID,分别对内部的CHN进行初始化。
VPSS_MAX_PHY_CHN_NUM = 3
和创建组的时候一样,会使用vpss_chn_attr去接收用户传递进来的一些属性然后调用IOCTL setchn,处理用户空间中的浮动定位这是啥意思?
CVI_VPSS_SetChnCrop设置 VPSS 通道裁剪功能属性
这里就应用到了stVpssChnCropInfo裁剪相关的属性,使用vpss_chn_crop_cfg去接受参数的赋值然后传入IOCTL中进行属性的创建。
CVI_VPSS_EnableChn,启动VPSS 通道
CVI_VPSS_AttachVbPool,将 VPSS 的通道绑定到某个视频缓存VB 池中
针对于每一个CHN都会获取相应的vbpool,使用vpss_vb_pool_cfg作为驱动的结构体参数接收函数的参数,使用ioctl与vb 进行连接获取内存。
CVI_VPSS_StartGrp,启动组
BIND过程
typedef struct _MMF_CHN_S {
MOD_ID_E enModId;
CVI_S32 s32DevId;
CVI_S32 s32ChnId;
} MMF_CHN_S;
s32Ret = CVI_SYS_Bind(&pstVpssGrpCfg->astChn[0], &pstVpssGrpCfg->astChn[1]);
VENC
模块构成
视频经过VI VPSS 之后会有三种状态的输出,分别是H.265、H.264、JPEG视频编码标准。以下内容主要分析编解码的初始化以及启动过程。
code trace
(Start)使用数据结构:
typedef struct APP_VENC_CHN_CFG_T {
CVI_BOOL bEnable; /* set by param_config.ini , DO NOT update by coding */
CVI_BOOL bStart;
VENC_CHN VencChn;
PAYLOAD_TYPE_E enType;//编码类型
CVI_U32 StreamTo;
CVI_U32 u32Duration;
CVI_BOOL bRtspEn;
CVI_U32 u32Width;
CVI_U32 u32Height;
CVI_U32 u32SrcFrameRate;//输入帧率
CVI_U32 fr32DstFrameRate;//输出
CVI_U32 u32BitRate;//平均 bitrate
CVI_U32 u32MaxBitRate;// 最大bitrate
CVI_U32 VpssGrp;//VPSS GROUP 号 几个?
CVI_U32 VpssChn;//VPSS chn 号 几个?
CVI_U32 u32Profile;//编码的等级
CVI_BOOL bSingleCore;//只使用H264/H265
CVI_U32 u32Gop;//H.264 gop 值。
CVI_U32 u32IQp;//I 帧所有宏块 Qp 值
CVI_U32 u32PQp;//P 帧所有宏块 Qp 值
CVI_U32 statTime;
CVI_U32 enBindMode;
MMF_CHN_S astChn[2];
VENC_GOP_MODE_E enGopMode;//编码 GOP 类型。
APP_GOP_PARAM_U unGopParam;
VENC_RC_MODE_E enRcMode;//RC 模式
APP_RC_PARAM_S stRcParam;
APP_JPEG_CODEC_PARAM_S stJpegCodecParam;
FILE *pFile;
CVI_U32 frameNum;
CVI_U32 fileNum;
CVI_CHAR SavePath[32];
volatile CVI_S32 savePic;
} APP_VENC_CHN_CFG_S;
(Thread_Jpg_Proc)中结构体:
typedef struct _VIDEO_FRAME_S {
CVI_U32 u32Width;
CVI_U32 u32Height;
PIXEL_FORMAT_E enPixelFormat;//图像像素格式
BAYER_FORMAT_E enBayerFormat;//图像RAW 格式
VIDEO_FORMAT_E enVideoFormat;//图像格式
COMPRESS_MODE_E enCompressMode;//
DYNAMIC_RANGE_E enDynamicRange;//动态I范围
COLOR_GAMUT_E enColorGamut;//色域范围
u32Stride
CVI_U32 u32Stride[3];//图像行跨度
CVI_U64 u64PhyAddr[3];//物理地址
CVI_U8 *pu8VirAddr[3];//虚拟地址
#ifdef __arm__
__u32 u32VirAddrPadding[3];
#endif
CVI_U32 u32Length[3];//图像空間大小
CVI_S16 s16OffsetTop;//图像顶部剪裁宽度
CVI_S16 s16OffsetBottom;
CVI_S16 s16OffsetLeft;
CVI_S16 s16OffsetRight;
CVI_U32 u32TimeRef;//图像帧序列号
CVI_U64 u64PTS;//【图像时间戳
void *pPrivateData;//私有·数据·
#ifdef __arm__
__u32 u32PrivateDataPadding;
#endif
CVI_U32 u32FrameFlag;// 当钱帧标记·
} VIDEO_FRAME_S;
(thread/CVI_VENC_GetStream)VENC_STREAM_S:定义帧码流类型结构体。
typedef struct _VENC_STREAM_S {
VENC_PACK_S ATTRIBUTE *pstPack; // 帧码流包结构。
#ifdef __arm__
__u32 u32stPackPadding;
#endif
CVI_U32 ATTRIBUTE u32PackCount; //㇐帧码流的所有包的个数
CVI_U32 u32Seq; ///VENC码流序列号
//码流信息
union {
VENC_STREAM_INFO_H264_S stH264Info; ///< TODO VENC
VENC_STREAM_INFO_JPEG_S stJpegInfo; ///< The information of JPEG bitstream
VENC_STREAM_INFO_H265_S stH265Info; ///< TODO VENC
VENC_STREAM_INFO_PRORES_S stProresInfo; ///< TODO VENC
};
//码流进阶信息
union {
VENC_STREAM_ADVANCE_INFO_H264_S
stAdvanceH264Info; ///< TODO VENC
VENC_STREAM_ADVANCE_INFO_JPEG_S
stAdvanceJpegInfo; ///< TODO VENC
VENC_STREAM_ADVANCE_INFO_H265_S
stAdvanceH265Info; ///< TODO VENC
VENC_STREAM_ADVANCE_INFO_PRORES_S
stAdvanceProresInfo;///< TODO VENC
};
} VENC_STREAM_S;
数据源VI->数据接收者VPSS/VENC/VO
数据源VPSS->数据接收者VO/VENC/VPSS
有两个绑定
如果启用的是Thread_Streaming_Proc线程:
没有绑定就往venc frame里面发。
typedef struct _VIDEO_FRAME_S {
CVI_U32 u32Width;
CVI_U32 u32Height;
PIXEL_FORMAT_E enPixelFormat;//图像像素格式
BAYER_FORMAT_E enBayerFormat;//图像RAW 格式
VIDEO_FORMAT_E enVideoFormat;//图像格式
COMPRESS_MODE_E enCompressMode;//
DYNAMIC_RANGE_E enDynamicRange;//动态I范围
COLOR_GAMUT_E enColorGamut;//色域范围
u32Stride
CVI_U32 u32Stride[3];//图像行跨度
CVI_U64 u64PhyAddr[3];
CVI_U8 *pu8VirAddr[3];
#ifdef __arm__
__u32 u32VirAddrPadding[3];
#endif
CVI_U32 u32Length[3];//图像空間大小
CVI_S16 s16OffsetTop;//图像顶部剪裁宽度
CVI_S16 s16OffsetBottom;
CVI_S16 s16OffsetLeft;
CVI_S16 s16OffsetRight;
CVI_U32 u32TimeRef;//图像帧序列号
CVI_U64 u64PTS;//图像时间戳
void *pPrivateData;//私有数据
#ifdef __arm__
__u32 u32PrivateDataPadding;
#endif
CVI_U32 u32FrameFlag;// 当前帧标记
} VIDEO_FRAME_S;
对于已经初始化的编码通道开始往里面发送数据,失败的时候对创建的通道进行释放。
之后就先初始化一个码流包,将编码信息输出至码流包,获得到编码数据之后将数据发送至RTSP或则FLASH,发送完之后需要及时释放缓存。(用户获取码流后必须及时释放已经获取的码流缓存,否则可能会导致码流buffer 满,影响编码器编码。)
如果启用的是static void *Thread_Jpg_Proc(void *pArgs)线程:过程基本一致,只不过最后存放在flash 之中。
WebSocket
简介
WebSocket 是一种网络传输协议,可在单个 TCP 连接上进行全双工通信,位于 OSI 模型的应用层。WebSocket 协议在 2011 年由 IETF 标准化为 RFC 6455,后由 RFC 7936 补充规范。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。
WebSocket 优点
普遍认为,WebSocket的优点有如下几点:
- 较少的控制开销:在连接创建后,服务器和客户端之间交换数据时,用于协议控制的数据包头部相对较小;
- 更强的实时性:由于协议是全双工的,所以服务器可以随时主动给客户端下发数据。相对于 HTTP 请求需要等待客户端发起请求服务端才能响应,延迟明显更少;
- 保持连接状态:与 HTTP 不同的是,WebSocket 需要先创建连接,这就使得其成为一种有状态的协议,之后通信时可以省略部分状态信息;
- 更好的二进制支持:WebSocket 定义了二进制帧,相对 HTTP,可以更轻松地处理二进制内容;
- 可以支持扩展:WebSocket 定义了扩展,用户可以扩展协议、实现部分自定义的子协议。
由于 WebSocket 拥有上述的优点,所以它被广泛地应用在即时通讯、实时音视频、在线教育和游戏等领域。
过程
创建一个新的线程
启动线程的过程会对里面的参数进行配置,在protocols的结构体中会有回调函数的配置,在进入到某种状态会自动进行不同的处理。