H264码流分NUL包

来源:互联网 发布:淘宝常用文案 编辑:程序博客网 时间:2024/06/06 16:30
while(!feof(bits)) 
{
GetAnnexbNALU(n);//每执行一次,文件的指针指向本次找到的NALU的末尾,下一个位置即为下个NALU的起始码0x000001
dump(n);//输出NALU长度和TYPE

memset(sendbuf,0,1500);//清空sendbuf;此时会将上次的时间戳清空,因此需要ts_current来保存上次的时间戳值

//rtp固定包头,为12字节,该句将sendbuf[0]的地址赋给rtp_hdr,以后对rtp_hdr的写入操作将直接写入sendbuf。
rtp_hdr =(RTP_FIXED_HEADER*)&sendbuf[0]; 

//设置RTP HEADER,
rtp_hdr->version = 2;   //版本号,此版本固定为2

rtp_hdr->marker  = 0;   //标志位,由具体协议规定其值。
rtp_hdr->payload = H264;//负载类型号,

rtp_hdr->ssrc    = htonl(10);//随机指定为10,并且在本RTP会话中全局唯一

//当一个NALU小于1400字节的时候,采用一个单RTP包发送
if(n->len<=1400){
//设置rtp M 位;
rtp_hdr->marker=1;
rtp_hdr->seq_no = htons(seq_num ++); //序列号,每发送一个RTP包增1

//设置NALU HEADER,并将这个HEADER填入sendbuf[12]
nalu_hdr =(NALU_HEADER*)&sendbuf[12]; //将sendbuf[12]的地址赋给nalu_hdr,之后对nalu_hdr的写入就将写入sendbuf中;
nalu_hdr->F=n->forbidden_bit;
nalu_hdr->NRI=n->nal_reference_idc>>5;//有效数据在n->nal_reference_idc的第6,7位,需要右移5位才能将其值赋给nalu_hdr->NRI。
nalu_hdr->TYPE=n->nal_unit_type;

nalu_payload=&sendbuf[13];//同理将sendbuf[13]赋给nalu_payload
memcpy(nalu_payload,n->buf+1,n->len-1);//去掉nalu头的nalu剩余内容写入sendbuf[13]开始的字符串。

ts_current=ts_current+timestamp_increse;
rtp_hdr->timestamp=htonl(ts_current);
bytes=n->len + 12 ; //获得sendbuf的长度,为nalu的长度(包含NALU头但除去起始前缀)加上rtp_header的固定长度12字节
send(socket1,sendbuf,bytes,0);//发送RTP包
// Sleep(100);
}else{
//得到该nalu需要用多少长度为1400字节的RTP包来发送
int k=0,l=0;
k=n->len/1400;//需要k个1400字节的RTP包
l=n->len%1400;//最后一个RTP包的需要装载的字节数
int t=0;//用于指示当前发送的是第几个分片RTP包
ts_current=ts_current+timestamp_increse;
rtp_hdr->timestamp=htonl(ts_current);
while(t<=k)
{
rtp_hdr->seq_no = htons(seq_num ++); //序列号,每发送一个RTP包增1
if(!t)//发送一个需要分片的NALU的第一个分片,置FU HEADER的S位
{
//设置rtp M 位;
rtp_hdr->marker=0;
//设置FU INDICATOR,并将这个HEADER填入sendbuf[12]
fu_ind =(FU_INDICATOR*)&sendbuf[12]; //将sendbuf[12]的地址赋给fu_ind,之后对fu_ind的写入就将写入sendbuf中;
fu_ind->F=n->forbidden_bit;
fu_ind->NRI=n->nal_reference_idc>>5;
fu_ind->TYPE=28;

//设置FU HEADER,并将这个HEADER填入sendbuf[13]
fu_hdr =(FU_HEADER*)&sendbuf[13];
fu_hdr->S=1;
fu_hdr->E=0;
fu_hdr->R=0;
fu_hdr->TYPE=n->nal_unit_type;

nalu_payload=&sendbuf[14];//同理将sendbuf[14]赋给nalu_payload
memcpy(nalu_payload,n->buf+1,1400);//去掉NALU头

bytes=1400+14; //获得sendbuf的长度,为nalu的长度(除去起始前缀和NALU头)加上rtp_header,fu_ind,fu_hdr的固定长度14字节
send( socket1, sendbuf, bytes, 0 );//发送RTP包
t++;
}
//发送一个需要分片的NALU的非第一个分片,清零FU HEADER的S位,如果该分片是该NALU的最后一个分片,置FU HEADER的E位
else if(k==t)//发送的是最后一个分片,注意最后一个分片的长度可能超过1400字节(当l>1386时)。
{
//设置rtp M 位;当前传输的是最后一个分片时该位置1
rtp_hdr->marker=1;
//设置FU INDICATOR,并将这个HEADER填入sendbuf[12]
fu_ind =(FU_INDICATOR*)&sendbuf[12]; //将sendbuf[12]的地址赋给fu_ind,之后对fu_ind的写入就将写入sendbuf中;
fu_ind->F=n->forbidden_bit;
fu_ind->NRI=n->nal_reference_idc>>5;
fu_ind->TYPE=28;

//设置FU HEADER,并将这个HEADER填入sendbuf[13]
fu_hdr =(FU_HEADER*)&sendbuf[13];
fu_hdr->S=0;
fu_hdr->E=1;
fu_hdr->R=0;
fu_hdr->TYPE=n->nal_unit_type;

nalu_payload=&sendbuf[14];//同理将sendbuf[14]的地址赋给nalu_payload
memcpy(nalu_payload,n->buf+t*1400+1,l-1);//将nalu最后剩余的l-1(去掉了一个字节的NALU头)字节内容写入sendbuf[14]开始的字符串。
bytes=l-1+14;//获得sendbuf的长度,为剩余nalu的长度l-1加上rtp_header,FU_INDICATOR,FU_HEADER三个包头共14字节
send( socket1, sendbuf, bytes, 0 );//发送rtp包
t++;
// Sleep(100);
}
else
{
//设置rtp M 位;
rtp_hdr->marker=0;
//设置FU INDICATOR,并将这个HEADER填入sendbuf[12]
fu_ind =(FU_INDICATOR*)&sendbuf[12]; //将sendbuf[12]的地址赋给fu_ind,之后对fu_ind的写入就将写入sendbuf中;
fu_ind->F=n->forbidden_bit;
fu_ind->NRI=n->nal_reference_idc>>5;
fu_ind->TYPE=28;

//设置FU HEADER,并将这个HEADER填入sendbuf[13]
fu_hdr =(FU_HEADER*)&sendbuf[13];
fu_hdr->S=0;
fu_hdr->E=0;
fu_hdr->R=0;
fu_hdr->TYPE=n->nal_unit_type;

nalu_payload=&sendbuf[14];//同理将sendbuf[14]的地址赋给nalu_payload
memcpy(nalu_payload,n->buf+t*1400+1,1400);//去掉起始前缀的nalu剩余内容写入sendbuf[14]开始的字符串。
bytes=1400+14; //获得sendbuf的长度,为nalu的长度(除去原NALU头)加上rtp_header,fu_ind,fu_hdr的固定长度14字节
send( socket1, sendbuf, bytes, 0 );//发送rtp包
t++;
}
}
}
}

原创粉丝点击