java ps h264_关于对H264码流的PS的封装的相关代码实现

转自:http://www.cnblogs.com/lidabo/p/6604988.html

1、写在开始之前:

最近因为新工作要维护别人留下的GB模块代码,先熟悉了流程,然后也试着封装了下ps流,结果也能通过测试正常预览了,当然,其中开发读文档的头疼,预览花屏,卡帧的事情都有遇到,当时慢慢的看文档,整理逻辑,也就都顺利解决了,下面把大致的一些流程代码贴出来分享下。既然是对接国标,自然少不了通读它的标准文档和相关的RFC文档了!具体的我就不说了,可以用百度google下的。

注意:因为是GB要求ps封装后再加上rtp头的格式来的, 所以下面代码中我也加上了rtp头,如果不需要的话,直接屏蔽代码中的rtp即可。

2、封装的重点

当我们从读缓冲区中取得一帧音视频数据的时候,封装时其实每一帧数据有且只有一个ps头和psm头,如果是I帧的话,就还多一个system头,一个或者多个pes头和rtp头,

像如果帧数据过长的话,就得进行分片,每片都会包含一个pes头,rtp负载最好长度1460,所以会进行再分包操作!所以每一个包数据至少一个rtp+databuf,每一片数据,至少有个rtp+pes+databuf,每一帧数据至少有rtp+ps+psm+pes+databuf(关键帧的话:多一个system头)

3、具体的各个封装的代码实现

首先给去一个整体的封装rtp->ps->sys->psm->pes(如果只要ps的话,则为ps->sys->psm->pes)的大致流程,

然后再一一罗列出各个部件的封装接口

/***

*@remark:  音视频数据的打包成ps流,并封装成rtp

*@param :  pData      [in] 需要发送的音视频数据

*          nFrameLen  [in] 发送数据的长度

*          pPacker    [in] 数据包的一些信息,包括时间戳,rtp数据buff,发送的socket相关信息

*          stream_type[in] 数据类型 0 视频 1 音频

*@return:  0 success others failed

*/

int gb28181_streampackageForH264(char *pData, int nFrameLen, Data_Info_s* pPacker, int stream_type)

{

char szTempPacketHead[256];

int  nSizePos = 0;

int  nSize = 0;

char *pBuff = NULL;

memset(szTempPacketHead, 0, 256);

// 1 package for ps header

gb28181_make_ps_header(szTempPacketHead + nSizePos, pPacker->s64CurPts);

nSizePos += PS_HDR_LEN;

//2 system header

if( pPacker->IFrame == 1 )

{

// 如果是I帧的话,则添加系统头

gb28181_make_sys_header(szTempPacketHead + nSizePos);

nSizePos += SYS_HDR_LEN;

//这个地方我是不管是I帧还是p帧都加上了map的,貌似只是I帧加也没有问题

//      gb28181_make_psm_header(szTempPacketHead + nSizePos);

//      nSizePos += PSM_HDR_LEN;

}

// psm头 (也是map)

gb28181_make_psm_header(szTempPacketHead + nSizePos);

nSizePos += PSM_HDR_LEN;

//加上rtp发送出去,这样的话,后面的数据就只要分片分包就只有加上pes头和rtp头了

if(gb28181_send_rtp_pack(szTempPacketHead, nSizePos, 0, pPacker) != 0 )

return -1;

// 这里向后移动是为了方便拷贝pes头

//这里是为了减少后面音视频裸数据的大量拷贝浪费空间,所以这里就向后移动,在实际处理的时候,要注意地址是否越界以及覆盖等问题

pBuff = pData - PES_HDR_LEN;

while(nFrameLen > 0)

{

//每次帧的长度不要超过short类型,过了就得分片进循环行发送

nSize = (nFrameLen > PS_PES_PAYLOAD_SIZE) ? PS_PES_PAYLOAD_SIZE : nFrameLen;

// 添加pes头

gb28181_make_pes_header(pBuff, stream_type ? 0xC0:0xE0, nSize, (pPacker->s64CurPts / 100), (pPacker->s64CurPts/300));

//最后在添加rtp头并发送数据

if( gb28181_send_rtp_pack(pBuff, nSize + PES_HDR_LEN, ((nSize == nFrameLen)?1:0), pPacker) != 0 )

{

printf("gb28181_send_pack failed!\n");

return -1;

}

//分片后每次发送的数据移动指针操作

nFrameLen -= nSize;

//这里也只移动nSize,因为在while向后移动的pes头长度,正好重新填充pes头数据

pBuff     += nSize;

}

return 0;

}

上面列出来了整个打包发包的过程,接下来一个一个接口的看

/***

*@remark:   ps头的封装,里面的具体数据的填写已经占位,可以参考标准

*@param :   pData  [in] 填充ps头数据的地址

*           s64Src [in] 时间戳

*@return:   0 success, others failed

*/

int gb28181_make_ps_header(char *pData, unsigned long long s64Scr)

{

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值