RPC
RPC指远程过程调用(Remote Procedure Call),通俗一些理解就是两台服务器A、B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。(远程过程调用是相对于本地过程调用来说的)
RPC要解决的两个问题
1、解决分布式系统中,服务之间的调用问题。
2、远程调用时,要能够像本地调用一样方便,让调用者感知不到远程调用的逻辑。
远程过程调用过程中有哪些步骤和问题:
1、要解决通讯的问题。客户端和服务端之间要建立连接,远程过程调用的所有交换的数据都在这个连接里传输。连接可以是按需连接,调用结束后就断掉,也可以是长连接,多个远程过程调用共享同一个连接。
2、要解决寻址的问题。A服务器上的应用要想办法告诉底层的RPC框架,如何连接到B服务器(如主机或IP地址)以及特定的端口,方法的名称是什么,这样才能完成调用
3、序列化发送参数请求。当A服务器上的应用发起远程过程调用时,方法的参数要通过底层的网络协议如TCP传递到B服务器,由于网络协议是基于二进制的,内存中的参数的值要序列化成二进制的形式,通过寻址和传输将序列化的二进制发送给B服务器。
4、对参数进行反序列化。B服务器收到请求后,需要对参数进行反序列化(序列化的逆操作),恢复为内存中的表达式,然后找到对应的方法(寻址的一部分)进行本地调用,然后得到返回值。
5、返回值序列化回传。返回值还要发送会服务器A上的应用,也要经过序列化的方式发送,服务器A接到后,再反序列号,恢复为内存中的表达方式,交给A服务器上的应用。
VDEC
VDEC是视频解码器,参考海思mpp的VDEC接口调用学习到:
一、初始化系统:
HI_MPI_SYS_Exit();
HI_MPI_VB_Exit();
HI_MPI_VB_SetConfig(pstVbConfig);//整个系统中可以容纳缓存池的个数,每个缓存池缓存块的个数,缓存块的大小
HI_MPI_VB_Init();
HI_MPI_SYS_Init();
二、VDEC初始化并获取VB:
1.根据每个解码通道的需要解码的视频的宽高,像素格式,位宽 以及不同的解码方式(如:h.264 h.265等)计算每个通道需要的VB大小。
2. 模块公共视频缓存池
HI_MPI_VB_ExitModCommPool(VB_UID_VDEC);
HI_MPI_VB_SetModPoolConfig(VB_UID_VDEC, &stVbConf);//设置模块公共视频缓存池属性
HI_MPI_VB_InitModCommPool(VB_UID_VDEC);
三、start VDEC:
HI_MPI_VDEC_SetModParam(&stModParam);//主要是设置VB 来源选择
以下的操作,在每个解码通道都需要操作一遍。
HI_MPI_VDEC_CreateChn(i, &stChnAttr[i])//创建视频解码的通道。
HI_MPI_VDEC_SetChnParam(i, &stChnParam)//设置解码通道i参数stChnParam
HI_MPI_VDEC_StartRecvStream(i)//使能解码通道i
四、start VPSS:
每个解码通道一个VPSSgroup,每个VPSSgroup中有4个phy通道
HI_MPI_VPSS_SetModParam(&stModParam);//hdr支持
以下的操作,在每个解码通道都需要操作一遍。
HI_MPI_VPSS_CreateGrp(VpssGrp, pstVpssGrpAttr);
for (j = 0; j < VPSS_MAX_PHY_CHN_NUM; j++)// VPSS_MAX_PHY_CHN_NUM = 4
VpssChn = j;
HI_MPI_VPSS_SetChnAttr(VpssGrp, VpssChn, &pastVpssChnAttr[VpssChn]);
HI_MPI_VPSS_EnableChn(VpssGrp, VpssChn);
HI_MPI_VPSS_StartGrp(VpssGrp);
五、start VO:
简称 | 全称 | 中文名 | 备注 |
---|---|---|---|
DHD0 | Device HD0 | 超高清设备 0 | |
DHD1 | Device HD1 | 高清设备 1 | |
VHD0 | Video layer of HD0 | 超高清视频层 0 | 隶属于 DHD0 |
VHD1 | Video layer of HD1 | 高清视频层 1 | 隶属于 DHD1 |
VHD2 | Video layer of HD 2 | 高清视频层 2 | Hi3559AV100 上隶属于 DHD0 |
Hi3519AV100/Hi3556AV100 上可以绑定至 DHD0 或者 DHD1, 用作 PIP 层。
WD: Write Back Channel Device, 回写通道设备。
图形层 G3: Graphic layer 3, 用作鼠标层, DHD0 和 DHD1 中均有此项, 但只能绑定其中一个设备,
G3 默认绑定在 DHD1 上。
HI_MPI_VO_SetPubAttr(VoDev, pstPubAttr);// 配置视频输出设备VoDev(根据不同的芯片,有所不同)的公共属性(hdmi或者mipi,视频的输出格式如1080P60)。
HI_MPI_VO_Enable(VoDev);//使能视频输出设备
HI_MPI_VO_GetVideoLayerAttr(VoLayer, &stLayerAttr);// VoLayer(0.1.2即高清视频层0.1.2)获取视频层属性
HI_MPI_VO_SetChnAttr(VoLayer, i, &stChnAttr);//同一个图层VoLayer中,不同的视频输出通道i的属性
HI_MPI_VO_EnableChn(VoLayer, i);//使能同一个图层的不同的视频输出通道。
HI_MPI_VO_SetVideoLayerPartitionMode(VoLayer, enVoPartMode);// 设置当前视频层VoLayer的分割模式(VO_PART_MODE_MULTI,VO_PART_MODE_SINGLE)。
HI_MPI_VO_SetDisplayBufLen(VoLayer, pstVoConfig->u32DisBufLen);
HI_MPI_VO_SetVideoLayerAttr(VoLayer, pstLayerAttr);// 设备分辨率、显示分辨率和图像分辨率
HI_MPI_VO_EnableVideoLayer(VoLayer);
以下是视频输出的硬件接口的使能:
HDMI:
HI_MPI_HDMI_Init();
HI_MPI_HDMI_Open(enHdmiId);
HI_MPI_HDMI_GetAttr(enHdmiId, &stAttr);
HI_MPI_HDMI_SetAttr(enHdmiId, &stAttr) ;//属性中比较重要的一点是输出的视频的格式。
如:1080P60。
HI_MPI_HDMI_Start(enHdmiId);
MIPI:
fd = open("/dev/hi_mipi_tx", O_RDWR);
s32Ret = ioctl(fd, HI_MIPI_TX_SET_DEV_CFG, pstMipiTxConfig);//视频的输出格式。
如:MIPI_TX_1080X1920_60_CONFIG。
/中间部分为现实屏的初始化操作。主要区别和显示屏的分辨率有关。直接参考代码中的sample中的ioctl操作/
s32Ret = ioctl(fd, HI_MIPI_TX_ENABLE);
六、VDEC bind VPSS:
stSrcChn.enModId = HI_ID_VDEC;
stSrcChn.s32DevId = 0;
stSrcChn.s32ChnId = VdecChn;
stDestChn.enModId = HI_ID_VPSS;
stDestChn.s32DevId = VpssGrp;
stDestChn.s32ChnId = 0;
HI_MPI_SYS_Bind(&stSrcChn, &stDestChn)
七、VPSS bind VO:
stSrcChn.enModId = HI_ID_VPSS;
stSrcChn.s32DevId = VpssGrp;
stSrcChn.s32ChnId = VpssChn;//固定为0
stDestChn.enModId = HI_ID_VO;
stDestChn.s32DevId = VoLayer;//Vodev
stDestChn.s32ChnId = VoChn;//对应于VpssGrp
HI_MPI_SYS_Bind(&stSrcChn, &stDestChn)
八、send stream to vdec
(选定需要解码的文件路径和文件名)
每个解码通道创建一个相对应的线程,当应用程序退出时,直接退出线程即可。
pthread_join(pVdecThread[i], HI_NULL);
pthread_create(&pVdecThread[i], 0, SAMPLE_COMM_VDEC_SendStream, (HI_VOID *)&pstVdecSend[i]);
SAMPLE_COMM_VDEC_SendStream:
fpStrm = fopen(cStreamFile, "rb");//打开视频文件
while(1)
{
fseek(fpStrm, s32UsedBytes, SEEK_SET);
s32ReadLen = fread(pu8Buf, 1, pstVdecThreadParam->s32MinBufSize, fpStrm);
有区别于vdec,按stream和frame
HI_MPI_VDEC_SendStream(pstVdecThreadParam->s32ChnId, &stStream, pstVdecThreadParam->s32MilliSec);
}
/* send the flag of stream end */
memset(&stStream, 0, sizeof(VDEC_STREAM_S) );
stStream.bEndOfStream = HI_TRUE;
HI_MPI_VDEC_SendStream(pstVdecThreadParam->s32ChnId, &stStream, -1); //在发送完所有码流后,可以发送 bEndOfStream 为 1 的空码流包,表示当前码流文件结束,解码器会把所有码流全部解完并输出全部图像。
九、应用退出:
pthread_join(pVdecThread[i], HI_NULL);
vpss vo unbind:HI_MPI_SYS_UnBind(&stSrcChn, &stDestChn);
vdec vpss unbind
HI_MPI_HDMI_Stop(enHdmiId)
HI_MPI_HDMI_Close(enHdmiId)
HI_MPI_HDMI_DeInit()
HI_MPI_VO_DisableChn(VoLayer, i);
HI_MPI_VO_DisableVideoLayer(VoLayer);
HI_MPI_VO_Disable(VoDev);
HI_MPI_VPSS_StopGrp(VpssGrp);//停止每个vpssgroup
HI_MPI_VPSS_DisableChn(VpssGrp, VpssChn);//禁止vpss下的通道
HI_MPI_VPSS_DestroyGrp(VpssGrp);//销毁VpssGrp
//多个解码通道的话,每个通道都要分别执行
HI_MPI_VDEC_StopRecvStream(i)//解码通道i停止接收数据流
HI_MPI_VDEC_DestroyChn(i)//销毁解码通道i
HI_MPI_VB_ExitModCommPool(VB_UID_VDEC);//VDEC退出模块公共视频缓存池
HI_MPI_SYS_Exit();
HI_MPI_VB_Exit();
至此整个视频的解码流程就到此结束
关于面向海思芯片VDEC的学习还可以看视频编解码(二):海思VDEC模块视频解码代码解析
VBM
暂时搞不懂
VMN
暂时搞不懂