rtsp 基于RTP 解包代码

buf_in 一般是由 live555 client 获得的数据,buf_out是解包成 H264编码格式的数据,该数据直接发给解码器 就完成了解码的流程。

rtp解包代码流程 

#define MEDIA_RTP_HEADER_LEN 12

typedef struct nalu_tag {
 unsigned char forbidden_bit;           //Should always be FALSE  
 unsigned char nal_reference_idc;       //NALU_PRIORITY_xxxx  
 unsigned char nal_unit_type;           //NALU_TYPE_xxxx    
 unsigned int startcodeprefix_len;      //前缀字节数  
 unsigned int len;                      //包含nal 头的nal 长度,从第一个00000001到下一个000000001的长度  
 unsigned int max_size;                 //做多一个nal 的长度  
 unsigned char * buf;                   //包含nal 头的nal 数据  
 unsigned int lost_packets;             //预留  
} nalu_t;

/*
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI|  Type   |
+---------------+
*/
typedef struct nalu_header_tag {
 unsigned char Type : 5;
 unsigned char NRI : 2;
 unsigned char F : 1;
}nalu_header_t; 

/*
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI|  Type   |
+---------------+
*/
typedef struct fu_indicator_tag {
 unsigned char Type : 5;
 unsigned char NRI : 2;
 unsigned char F : 1;
}fu_indicator_t;

/*
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|S|E|R|  Type   |
+---------------+
*/
typedef struct fu_header_tag {
 unsigned char Type : 5;
 unsigned char R : 1;
 unsigned char E : 1;
 unsigned char S : 1;
}fu_header_t;

typedef struct rtp_header_tag {
 unsigned char cc : 4;       /**< CSRC count             */
 unsigned char x : 1;        /**< header extension flag      */
 unsigned char p : 1;        /**< padding flag           */
 unsigned char v : 2;        /**< packet type/version        */
 unsigned char pt : 7;       /**< payload type           */
 unsigned char m : 1;        /**< marker bit             */
 unsigned short seq;        /**< sequence number            */
 unsigned int ts;     /**< timestamp              */
 unsigned int ssrc;       /**< synchronization source     */
}rtp_header_t; //12bytes



//rtp解包出原始数据
int rtsp_unpackage(unsigned char *buf_in, int len, unsigned char *buf_out)
{
	nalu_header_t *nalu_hdr = NULL;
	fu_indicator_t *fu_ind = NULL;
	fu_header_t *fu_hdr = NULL;
	int i = 0;

	nalu_hdr = (nalu_header_t*)(buf_in + MEDIA_RTP_HEADER_LEN);
	if (nalu_hdr->Type > 0 && nalu_hdr->Type < 24)  
	{
		//NALU单包
		//写起始字节
		buf_out[i++] = 0x00;
		buf_out[i++] = 0x00;
		buf_out[i++] = 0x01;
		//写NAL_HEADER
		memcpy(&buf_out[i++], nalu_hdr, 1);
		memcpy(&buf_out[i], buf_in + MEDIA_RTP_HEADER_LEN + 1, len - MEDIA_RTP_HEADER_LEN - 1);
		i += len - MEDIA_RTP_HEADER_LEN - 1;
	}
	else if (nalu_hdr->Type == 28 || nalu_hdr->Type == 29)
	{
		//FU-A或FU-B分片包,解码顺序和传输顺序相同
		fu_ind = (fu_indicator_t*)(buf_in + MEDIA_RTP_HEADER_LEN);
		fu_hdr = (fu_header_t*)(buf_in + MEDIA_RTP_HEADER_LEN + 1);
		if (fu_hdr->E == 1)	{
			//分片包最后一个包
			memcpy(&buf_out[i], buf_in + MEDIA_RTP_HEADER_LEN + 2, len - MEDIA_RTP_HEADER_LEN - 2);
			i += len - MEDIA_RTP_HEADER_LEN - 2;
		}
		else {
			//分片包,但不是最后一个包
			if (fu_hdr->S == 1) {
				//分片的第一个包
				//写起始字节
				buf_out[i++] = 0x00;
				buf_out[i++] = 0x00;
				buf_out[i++] = 0x01;
				unsigned char F;
				unsigned char NRI;
				unsigned char TYPE;
				unsigned char nh;
				F = fu_ind->F << 7;
				NRI = fu_ind->NRI << 5;
				TYPE = fu_hdr->Type;
				nh = F | NRI | TYPE;
				//写NAL_HEADER
				buf_out[i++] = nh;
				memcpy(&buf_out[i], buf_in + MEDIA_RTP_HEADER_LEN + 2, len - MEDIA_RTP_HEADER_LEN - 2);
				i += len - MEDIA_RTP_HEADER_LEN - 2;
			}
			else {
				//如果不是第一个包
				memcpy(&buf_out[i], buf_in + MEDIA_RTP_HEADER_LEN + 2, len - MEDIA_RTP_HEADER_LEN - 2);
				i += len - MEDIA_RTP_HEADER_LEN - 2;
			}
		}
	}

	return i;
}



//此代码忽略了组合包,一般没有组合包

 

 

 

RTP 数据封包分析

https://zhuanlan.zhihu.com/p/25685166

https://blog.csdn.net/machh/article/details/52165292

 

 

二, h264 rtp 封包详解

H.264 视频 RTP 负载格式

1. 网络抽象层单元类型 (NALU)

NALU 头由一个字节组成, 它的语法如下:

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

F: 1 个比特.
forbidden_zero_bit. 在 H.264 规范中规定了这一位必须为 0.

NRI: 2 个比特.
nal_ref_idc. 取 00 ~ 11, 似乎指示这个 NALU 的重要性, 如 00 的 NALU 解码器可以丢弃它而不影响图像的回放. 不过一般情况下不太关心

这个属性.

Type: 5 个比特.
nal_unit_type. 这个 NALU 单元的类型. 简述如下:

0 没有定义
1-23 NAL单元 单个 NAL 单元包.
24 STAP-A 单一时间的组合包
25 STAP-B 单一时间的组合包
26 MTAP16 多个时间的组合包
27 MTAP24 多个时间的组合包
28 FU-A 分片的单元
29 FU-B 分片的单元
30-31 没有定义

2. 打包模式

下面是 RFC 3550 中规定的 RTP 头的结构.

0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X| CC |M| PT | sequence number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| synchronization source (SSRC) identifier |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
| contributing source (CSRC) identifiers |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

负载类型 Payload type (PT): 7 bits
序列号 Sequence number (SN): 16 bits
时间戳 Timestamp: 32 bits

H.264 Payload 格式定义了三种不同的基本的负载(Payload)结构. 接收端可能通过 RTP Payload 
的第一个字节来识别它们. 这一个字节类似 NALU 头的格式, 而这个头结构的 NAL 单元类型字段
则指出了代表的是哪一种结构,

这个字节的结构如下, 可以看出它和 H.264 的 NALU 头结构是一样的.
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
字段 Type: 这个 RTP payload 中 NAL 单元的类型. 这个字段和 H.264 中类型字段的区别是, 当 type
的值为 24 ~ 31 表示这是一个特别格式的 NAL 单元, 而 H.264 中, 只取 1~23 是有效的值.

24 STAP-A 单一时间的组合包
25 STAP-B 单一时间的组合包
26 MTAP16 多个时间的组合包
27 MTAP24 多个时间的组合包
28 FU-A 分片的单元
29 FU-B 分片的单元
30-31 没有定义

可能的结构类型分别有:

1. 单一 NAL 单元模式
即一个 RTP 包仅由一个完整的 NALU 组成. 这种情况下 RTP NAL 头类型字段和原始的 H.264的
NALU 头类型字段是一样的.

2. 组合封包模式
即可能是由多个 NAL 单元组成一个 RTP 包. 分别有4种组合方式: STAP-A, STAP-B, MTAP16, MTAP24.
那么这里的类型值分别是 24, 25, 26 以及 27.

3. 分片封包模式
用于把一个 NALU 单元封装成多个 RTP 包. 存在两种类型 FU-A 和 FU-B. 类型值分别是 28 和 29.

 

分片封包
h264包在传输的时候,如果包太大,会被分成多个片。NALU头会被如下的2个自己代替。
Type=28 FU-A
+---------------+---------------+---------------
|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++-+-+
|F|NRI| Type:28 |S|E|R| Type |
+---------------+---------------+-----------------

例:
0x7C85=01111100 10000101 (开始包)
0x7C05=01111100 00000101 (中间包)
0x7C45=01111100 01000101 (结束包)

 

组合封包

https://blog.csdn.net/jwybobo2007/article/details/7054140
Type=24 STAP-A

rtsp 基于RTP 解包代码_第1张图片

RTP 封包 解包 协议理解

https://blog.csdn.net/jwybobo2007/article/details/7054140

https://blog.csdn.net/jwybobo2007/article/details/7054140

https://blog.csdn.net/jwybobo2007/article/details/7054140

 

你可能感兴趣的:(流媒体)