GB28181中RTP封包C语言实现

来源:互联网 发布:arstan 软件 制作年表 编辑:程序博客网 时间:2024/06/08 01:04
今天带来一点rtp封包的代码,分享一下,很多刚刚入门音视频行业的新人都为此困惑,对于传输层,以及应用层的协议都有很多的疑问,也希望大家遇到困难可以向我提问:qq:1015787417while(!feof(bits)) {GetAnnexbNALU(nal);//每执行一次,文件的指针指向本次找到的NALU的末尾,memset(sendbuf,0,1500);//清空sendbuf;\//rtp固定包头,为12字节,rtp_hdr =(RTP_FIXED_HEADER*)&sendbuf[0]; rtp_hdr->version = 2;   //版本号,此版本固定为2rtp_hdr->marker  = 0;   //标志位,由具体协议规定其值。rtp_hdr->payload = H264;//负载类型号,rtp_hdr->ssrc    = htonl(10);//随机指定为10,并且在本RTP会话中全局唯一//当一个NALU小于1400字节的时候,采用一个单RTP包发送if( nal->len<=UDP_MAX_SIZE){//设置rtp M 位;rtp_hdr->marker=1;rtp_hdr->seq_no = htons(seq_num ++); //序列号,每发送一个RTP包增1//设置NALU HEADER,并将这个HEADER填入sendbuf[12]//将sendbuf[12]的地址赋给nalu_hdr,之后对nalu_hdr的写入就将写入sendbuf中;nalu_hdr =(NALU_HEADER*)&sendbuf[12]; nalu_hdr->F=nal->forbidden_bit;//有效数据在nal->nal_reference_idc的第6,7位,需要右移5位才能将其值赋给nalu_hdr->NRI。nalu_hdr->NRI=nal->nal_reference_idc>>5;nalu_hdr->TYPE= nal->nal_unit_type;nalu_payload =&sendbuf[13]; //同理将sendbuf[13]赋给nalu_payloadmemcpy(nalu_payload,nal->buf+1,nal->len-1);//去掉nalu头的nalu剩余内容写入sendbuf[13]开始的字符串。ts_current = ts_current+timestamp_increse;rtp_hdr->timestamp = htonl(ts_current);bytes= nal->len + 12 ; //获得sendbuf的长度,为nalu的长度(包含NALU头但除去起始前缀)加上rtp_header的固定长度12字节res = send(socket1,sendbuf,bytes,0);//发送RTP包if (res > 0) {g_iSendCount+=res;}//Sleep(100);}else //FU-A{int packetNum = nal->len/UDP_MAX_SIZE;if ( nal->len%UDP_MAX_SIZE != 0 )packetNum ++;int lastPackSize = nal->len - (packetNum-1)*UDP_MAX_SIZE;int packetIndex = 1 ;ts_current = ts_current+timestamp_increse;rtp_hdr->timestamp = htonl( ts_current);//发送第一个的FU,S=1,E=0,R=0rtp_hdr->seq_no = htons(seq_num ++); //序列号,每发送一个RTP包增1//设置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 = nal->forbidden_bit;fu_ind->NRI = nal->nal_reference_idc>>5;fu_ind->TYPE = 28;//设置FU HEADER,并将这个HEADER填入sendbuf[13]fu_hdr =(FU_HEADER*)&sendbuf[13];fu_hdr->S= 1; // ***** 1.第一包fu_hdr->E= 0;fu_hdr->R= 0;fu_hdr->TYPE = nal->nal_unit_type;nalu_payload = &sendbuf[14];//同理将sendbuf[14]赋给nalu_payloadmemcpy( nalu_payload,nal->buf+1,UDP_MAX_SIZE);//去掉NALU头bytes = UDP_MAX_SIZE+14;//获得sendbuf的长度,为nalu的长度(除去起始前缀和NALU头)加上rtp_header,fu_ind,fu_hdr的固定长度14字节res = send( socket1, sendbuf, bytes, 0 );//发送RTP包if (res > 0) {g_iSendCount+=res;}//****  2。 发送中间的FU,S=0,E=0,R=0for( packetIndex=2;packetIndex<packetNum;packetIndex++){rtp_hdr->seq_no = htons(seq_num ++); //序列号,每发送一个RTP包增1//设置rtp M 位;rtp_hdr->marker=0;//设置FU INDICATOR,并将这个HEADER填入sendbuf[12]fu_ind =(FU_INDICATOR*)&sendbuf[12]; fu_ind->F=nal->forbidden_bit;fu_ind->NRI=nal->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=nal->nal_unit_type;nalu_payload = &sendbuf[14]; memcpy( nalu_payload,nal->buf+(packetIndex-1)*UDP_MAX_SIZE+1,UDP_MAX_SIZE);//去掉起始前缀的nalu剩余内容写入sendbuf[14]开始的字符串。bytes = UDP_MAX_SIZE+14;//获得sendbuf的长度,为nalu的长度(除去原NALU头)加上rtp_header,fu_ind,fu_hdr的固定长度14字节res = send( socket1, sendbuf, bytes, 0 );//发送rtp包if (res > 0) {g_iSendCount+=res;}}//3.发送最后一个的FU,S=0,E=1,R=0rtp_hdr->seq_no = htons(seq_num ++);rtp_hdr->marker=1; //设置rtp M 位;当前传输的是最后一个分片时该位置1//设置FU INDICATOR,并将这个HEADER填入sendbuf[12]fu_ind =(FU_INDICATOR*)&sendbuf[12]; //将sendbuf[12]的地址赋给fu_ind,之后对fu_ind的写入就将写入sendbuf中;fu_ind->F = nal->forbidden_bit;fu_ind->NRI = nal->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=nal->nal_unit_type;nalu_payload=&sendbuf[14];memcpy( nalu_payload, nal->buf+( packetIndex-1)*UDP_MAX_SIZE+1, lastPackSize-1);//将nalu最后剩余的-1(去掉了一个字节的NALU头)字节内容写入sendbuf[14]开始的字符串。bytes=lastPackSize-1+14;//获得sendbuf的长度,为剩余nalu的长度l-1加上rtp_header,FU_INDICATOR,FU_HEADER三个包头共14字节res = send( socket1, sendbuf, bytes, 0 );//发送rtp包if (res > 0) {g_iSendCount+=res;}}Sleep(10);}
原创粉丝点击