RTP载荷H264视频

音视频应用开发系列文章目录

编码RTP over H264的大致过程

1.判断H264的NALU数据大小和MTU(Maximum Transmission Unit[normal 1500bytes])的关系

  小于MTU:发送整个NALU

  大于MTU:分片发送NALU

2.添加RTP12字节的头

3.case小于MTU:添加payload(NALU数据)

4.case大于MTU:根据NALU的第一个字节添加FUindicator,FUheader两个字节,最后添加payload(NALU数据移除第一字节)

NALU结构

NALU由NAL头(占1byte)+RBSP(Raw Byte Sequence Payload)组成。RBSP的结构为原始编码数据的后面填充1 bit'1'和n bit'0',为了字节对齐。NALU头如下格式。

+-------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-
|F|NRI|  Type   |
+-------------+

F:forbidden_zero_bit,1位,如果有语法冲突,则为1。当网络识别此单元存在比特错误时,可将其设为 1,以便接收方丢掉该单元。

NRI:nal_ref_idc,2位,用来指示该NALU的重要性等级。值越大,表示当前NALU越重要。

Type:5位,NALU的类型。Type值为7和8的NALU分别为序列参数集sps和图像参数集pps。参数集是一组很少改变的,为大量VCL NALU 提供解码信息的数据。其中序列参数集作用于一系列连续的编码图像,而图像参数集作用于编码视频序列中一个或多个独立的图像。如果解码器没能正确接收到这两个参数集,那么其他NALU也是无法解码的。因此它们一般在发送其它NALU之前发送,并且使用不同的信道或者更加可靠的传输协议TCP进行传输,也可以重复传输。

Type取值和含义如下表:

0没有定义 
1SLICE不分区、非IDR图像的片
2DPA片分区A
3DPB片分区B
4DPC片分区C
5IDR_SLICEIDR图像中的片
6SEI补充增强信息单元
7SPS序列参数集
8PPS图像参数集
9AUD分界符
10END_SEQUENCE序列结束
11END_STREAM码流结束
12FILLER_DATA填充
24STAP-A单一时间的组合包
25STAP-B单一时间的组合包
26MTAP16多个时间的组合包
27MTAP24多个时间的组合包
28FU-A分片的单元
29FU-B分片的单元
30没有定义 
31没有定义 

RTP打包图-case小于MTU

RTP打包图-case大于MTU

伪代码

void rtp_send_h264(char *data, int len){
	
	if(len <= MTU){
		
		rtp_send_h264_nalu(data, len);
	}else{
		
		rtp_send_h264_nalu_fu(data, len);
	}
}

void rtp_send_h264_nalu(char *data, int len){
	
	char buf[MTU];
	// fix buf[0~11] for rtp head
	memcpy(&buf[0], &rtp_head, 12); 
	// fix nalu data
	memcpy(&buf[12], data, len);
	rtp_send(buf, len + 12);
}

void rtp_send_h264_nalu_fu(char *data, int len){
	
	char buf[MTU];
	// fix buf[0~11] for rtp head
	memcpy(&buf[0], &rtp_head, 12); 
	// fix FUindicator(1 byte)
	// 指示indicator的Type=28为FU-A
	// indicator结构
	// +---------------+
	// |0|1|2|3|4|5|6|7|
	// +-+-+-+-+-+-+-+-+
	// |F|NRI|  Type   |
	// +---------------+
	char fu_indicator = ((data[0] & 0b11100000) | 28); 
	// fix FUheader(1 byte)
	// 指示header的Type为原NALU的Type
	// iheader结构
	// +---------------+
	// |0|1|2|3|4|5|6|7|
	// +-+-+-+-+-+-+-+-+
	// |S|E|R|  Type   |
	// +---------------+
	// S=1,E=0表示NALU分片的开始
	// S=0,E=1表示NALU分片的结束
	// R为保留位
	char fu_header = (data[0] & 0b00011111);
	// skip raw NALU head(1 byte)
	data += 1; 
	len -= 1;
    // fill fu_indicator and fu_header
	buf[12] = fu_indicator;
	buf[13] = fu_header;
	// start send:S=1 E=0 R=0
	// middle send:S=0 E=0 R=0
	// end send:S=0 E=1 R=0
	while(1){
	
		if(MTU < len){
		
			// fix payload
			memcpy(&buf[14], data, MTU);
			rtp_head.mark = 0;
			rtp_send(buf, MTU + 14);
			len -= MTU;
			data += MTU;
		}else{ // it's end
			
			// fix last payload and set rtp mark the frame end
			memcpy(&buf[14], data, len);
			rtp_head.mark = 1;
			rtp_send(buf, len + 14);
			break;
		}
	}
}

RTSP->SDP

v=0
o=username 1291468791 1 IN IP4 
s=h264
c=IN IP4 0.0.0.0
t=0 0
a=range:npt=0-
a=sendonly
a=control:*
m=video 0 RTP/AVP 96
a=rtpmap:96 H264/90000
a=control:track0

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值