一,在进行音视频解码前,进行平台初始化工作:
InitPlatform(){
...
}
该函数主要完成如下工作:
先清空系统控制信息,视频缓冲区的信息
HI_MPI_SYS_Exit()
HI_MPI_VB_Exit()
接下来设置视频缓冲区
先配置几个视频缓冲区的大小
stVbConf.astCommPool[0].u32BlkSize = 720 * 576 * 2;/*D1*/
stVbConf.astCommPool[0].u32BlkCnt = 10;
stVbConf.astCommPool[1].u32BlkSize = 704 * 576 * 2;/*D1*/
stVbConf.astCommPool[1].u32BlkCnt = 52;
stVbConf.astCommPool[2].u32BlkSize = 384 * 576 * 2;/*2CIF*/
stVbConf.astCommPool[2].u32BlkCnt = 64;
stVbConf.astCommPool[3].u32BlkSize = 384 * 288 * 2;/*CIF*/
stVbConf.astCommPool[3].u32BlkCnt = 20;
设置系统中使用图像的字节对齐数,开发文档推荐配置成16 or 64就可以了,此时不是很明白。
stSysConf.u32AlignWidth=64;
HI_MPI_VB_SetConf(&stVbConf);
视频缓冲区初始化
HI_MPI_VB_Init
二,完成了系统平台的初始化,接下来进行音视频的输入处理。
在视频输入处理中有一个概念必须明确,vi设备端口,hi3520有4个vi设备端口,最大同时支持16ch视频输入。
也就是说1个vi设备端口对应4个视频输入端口。
视频输入的初始化得完成以下几个工作。
设置vi设备端口的属性 HI_MPI_VI_SetPubAttr
|
|
V
vi设备使能 HI_MPI_VI_Enable(ViDev)
|
|
设置vi设备端口接入各个vi通道的属性
在hi3520系统中,3520芯片外的数据是通过ITU-R BT656/601/1120接口或digital camera接口,存入芯片外的内存区域的,
当数据接口为ITU_R BT656时,一个vi设备能支持多个通道,最多支持4个,我们称之为ViChn0,ViChn1,ViChn2,ViChn3.
1,设置vi设备端口属性
设置属性接口函数,VI_DEV ViDevId vi输入设备端口,pstPubAttr设置属性值
HI_S32 HI_MPI_VI_SetPubAttr(VI_DEV ViDevId,const VI_PUB_ATTR_S *pstPubAttr);
typedef struct HiVI_PUB_ATTR_S
{
VI_INPUT_MODE_E enInputMode; /* video input mode */
VI_WORK_MODE_E enWorkMode; /* work mode(only for BT.601) */
VIDEO_NORM_E enViNorm; /* video input normal(only for BT.601) */
HI_BOOL bIsChromaChn; /* whether this device capture chroma data(only for BT.1120) */
HI_BOOL bChromaSwap; /* whether exchange U/V of chroma channel(only for BT.1120) */
} VI_PUB_ATTR_S;
HI_MPI_VI_Enable(ViDev);
2,设置完视频输入设备,接下来设置视频输入通道。
一个视频输入设备对应4个通道。
和视频输入设备设置一样,先设置通道属性
s32Ret=HI_MPI_VI_SetChnAttr(ViDev,ViChn,pstViChnAttr);
再接下来使能通道
s32Ret=HI_MPI_VI_EnableChn(ViDev,ViChn);
设置通道的每秒的帧数,N制下为30,PAL制下为25帧。
s32Ret=HI_MPI_VI_SetSrcFrameRate(ViDev,ViChn,u32SrcFrmRate);
整体上把握一下视频解码的流程,至少也得知道数据是如何采集的
STEP1:模拟信号的采集
模拟信号通过2866芯片采集,转换为数字信号。2866芯片是标准的AD,DA数据转换芯片。在我们的系统中主要实现模拟信号转数字信号输入,数字信号转模拟信号的输出。
2866最大可以同时采集4CH视频信号。
STEP2:模数转换
2866采集的4CH视频信号(模拟)转换为1CH数字信号送3520芯片。对于像本人这样的新手来说,此处可能会有点理解困难,为什么4CH模拟信号
输入2866转换输出的仅仅只是1CH数字信号。这就涉及到点点数电的知识了,数字信号简单讲就是高低电平,高电平代表1,低电平代表0,如何在1CH数字信号
里包括4路VI视频呢?假设下图是2866送出的视频数字信号一个时钟周期内的波形图,
-_--_-_--__---_--_-_--__---_--_-_--__----_--_-_--__----_--_-_--__-----_-
周期的前四个信号 -_-- 第一个信号值为VI1的视频信号,第二信号值为VI2的视频信号,第三个信号值得为VI3的视频信号,第四个信号值得为VI4的视频信号。
STEP3:2866输出视频数据到3520
此时引入一个概念,VI设备,什么是VI设备,对于3520来说,上一步2866采集的4CH模拟信号转换后的一路视频信号就是1个VI设备,该VI设备同时处理包括4路视频数据。
海思的VI模块所做的主要工作就是处理VI设备的4CH视频数据,将视频数据放入内存区域。至于以后这些内存数据是用于视频输出,还是视频编码,就另当别论了。
看了几天的视频输入和视频输出部分的代码,自已也写了一些自已的DEMO程序,慢慢对这一块有了自已的认识,争取早点将一只脚迈入门内吧。
前几次的笔记大多谈到视频输入的处理, 这次想重点谈谈视频输出的处理。
3520支持三种视频输出设备,HD设备,AD设备,SD设备。
typedef enum hiVO_DEV_E
{
VO_DEV_HD = 0, /* high definition device */
VO_DEV_AD = 1, /* assistant device */
VO_DEV_SD = 2, /* spot device */
VO_DEV_BUTT
} VO_DEV_E;
视频输出模块所做的工作大约就是将视频数据从内存中取出来,送相应的显示设备输出。
接下来准备以我们的产品为例,写写视频输出的处理过程。
机器起动是16画面输出,这点是如何实现的?
1 不同的视频输出设备(HD,AD,SD)的视频输出大小是不一样的, 所以我们必须设置进行VI和VO的绑定处理,16画面输出,要求VI视频通道数据分别与16个通道依次绑定
2视频输出设备图形层的大小,AD设备与SD设备设置图像的大小为D1(PAL为720*576, ntsc为720*480),HD设备根据用户设置的分辨率大小设定.
3因为我们的视频输出的是16个画面,所以要求设置VO通道的属性值,主要是大小和坐标,叠加优先级。
当进行切换画面时又是如何处理的?
主要处理过程和上述基本相同, 但还是有些不一样。
1 首先你必须 Disable VO输出
假设你上一次视频为16画面输出,行,先Disable 16个vo通道。
for(i = 0; i < ibind; i ++)//最大通道数
{
if(iRet = (HI_MPI_VO_DisableChn(VoDev,i)) != 0)
{
DEBUG_INFO(("DisableVideoOutput HI_MPI_VO_DisableChn err (0x%x) vochn=%d /n",iRet, i));
//return -1;
}
}
2 设置VI属性。
当切换到单画面时,设置VI采集数据的大小为D1
/*设置VI通道属性,设置为D1大小显示*/
retvalue = HI_MPI_VI_GetChnAttr(channel/4, channel%4, &stViChnAttr);
FAIL_RETURN(retvalue);
stViChnAttr.stCapRect.u32Width = 704;
stViChnAttr.stCapRect.u32Height = (TS_PAL == system)?288:240;
stViChnAttr.bDownScale = HI_FALSE;
stViChnAttr.enCapSel = VI_CAPSEL_BOTH;
retvalue = HI_MPI_VI_SetChnAttr(channel/4, channel%4, &stViChnAttr);
FAIL_RETURN(retvalue);
当切换到四画面,9画面,16画面,设置VI采集数据的大小为CIF.
/*设置VI通道属性,设置为CIF大小显示*/
retvalue = HI_MPI_VI_GetChnAttr(chn/4, chn%4, &stViChnAttr);
FAIL_RETURN(retvalue);
stViChnAttr.stCapRect.u32Width = 704;
stViChnAttr.stCapRect.u32Height = (TS_PAL==system)?288:240;
stViChnAttr.bDownScale = HI_TRUE;
stViChnAttr.enCapSel = VI_CAPSEL_BOTH;
retvalue = HI_MPI_VI_SetChnAttr(chn/4, chn%4, &stViChnAttr);
FAIL_RETURN(retvalue);
1.什么是"帧"?
在最早的电影里面,一幅静止的图像被称做一"帧(Frame)",影片里的画面是每一秒钟有24帧,为什么是24帧,这个数字是怎么来的,因为人类眼睛的视觉暂留现象正好符合每秒24帧的标准,所以用多也没有意义还会浪费电影胶片,增加成本,所以就是24帧。
2.什么是"行"?
在我们用的传统CRT模似电视里面,一个电子束在水平方向的扫描被称之为行,或行扫描。
3.什么是"场"?
在我们用的传统CRT模似电视里面,一个行扫描,按垂直的方向扫描被称之为场,或场扫描。
4. 什么是NTSC制式?
NTSC(National Television System Committee)制式是1952年由美国国家电视制定委员会制定的彩色电视广播标准。美国、加拿大、以及中国台湾、韩国、菲律宾等国家采用的是这种制式。这种制式的彩色带宽为3.58Mhz,伴音带宽为6.0Mhz,每秒30帧画面。
5. 什么是PAL制式?
PAL(Phase Alternating Line),是1965年制定的电视制,主要应用于中国、香港、中东地区和欧洲一带。这种制式的彩色带宽为4.43Mhz伴音带宽为6.5Mhz,每秒 25帧画面,还有一种是SECAM制式德国地区采用的制式,因为应用比较少,就不多做介绍了。
6. 为何NTSC制为每秒30帧,而PAL制式每秒25帧?
这是因为采用NTSC的国家的市电为110V60HZ,所以电视里的场频信号直接就取样了交流电源的频率60HZ,因为两场组成一帧,所以60除以2等于30正好就是电视的帧数了,而我国的市电为220V50HZ,所以原因同上就是每秒25帧了。
7.什么是逐行?
电视的每帧画面是由若干条水平方向的扫描线组成的、PAL制为625行/帧,NTSC制为525行/帧。如果这一帧画面中所有的行是从上到下一行接一行地连续完成的,或者说扫描顺序是1、2、3……525,我们就称这种扫描方式为逐行扫描。
8.什么是隔行?
实际上,普通电视的一帧画面需要由两遍扫描来完成,第一遍只扫描奇数行,即第l、3、5……525行,第二遍扫描则只扫描偶数行,即第2、4、6……524行,这种扫描方式就是隔行扫描。一幅只含奇数行或偶数行的画面称为一“场(Field)”,其中只含奇数行的场称为奇数场或前场 (Top Field), 只含偶数行的场称为偶数场或后场(Bottom Field)。也就是说一个奇数场加上一个偶数场等于一帧(一幅图象)。