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

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章