1///<summary> 2/// RTP(RFC3550)協議數據包
3///</summary> 4///<remarks> 5/// The RTP header has the following format:
6/// 0 1 2 3
7/// 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
8/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
9/// |V=2|P|X| CC |M| PT | sequence number |
10/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
11/// | timestamp |
12/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13/// | synchronization source (SSRC) identifier |
14/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
15/// | contributing source (CSRC) identifiers |
16/// | .... |
17/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18///</remarks> 19publicclass RtpPacket
20 {
21///<summary> 22/// version (V): 2 bits
23/// RTP版本標識,當前規范定義值為2.
24/// This field identifies the version of RTP. The version defined by this specification is two (2).
25/// (The value 1 is used by the first draft version of RTP and the value 0 is used by the protocol
26/// initially implemented in the \vat" audio tool.)
27///</summary> 28publicint Version { get { return2; } }
29 30///<summary> 31/// padding (P):1 bit
32/// 如果設定padding,在報文的末端就會包含一個或者多個padding 字節,這不屬于payload。
33/// 最后一個字節的padding 有一個計數器,標識需要忽略多少個padding 字節(包括自己)。
34/// 一些加密算法可能需要固定塊長度的padding,或者是為了在更低層數據單元中攜帶一些RTP 報文。
35/// If the padding bit is set, the packet contains one or more additional padding octets at the
36/// end which are not part of the payload. The last octet of the padding contains a count of
37/// how many padding octets should be ignored, including itself. Padding may be needed by
38/// some encryption algorithms with fixed block sizes or for carrying several RTP packets in a
39/// lower-layer protocol data unit.
40///</summary> 41publicint Padding { get { return0; } }
42 43///<summary> 44/// extension (X):1 bit
45/// 如果設定了extension 位,定長頭字段后面會有一個頭擴展。
46/// If the extension bit is set, the fixed header must be followed by exactly one header extensio.
47///</summary> 48publicint Extension { get { return0; } }
49 50///<summary> 51/// CSRC count (CC):4 bits
52/// CSRC count 標識了定長頭字段中包含的CSRC identifier 的數量。
53/// The CSRC count contains the number of CSRC identifiers that follow the fixed header.
54///</summary> 55publicint CC { get { return0; } }
56 57///<summary> 58/// marker (M):1 bit
59/// marker 是由一個profile 定義的。用來允許標識在像報文流中界定幀界等的事件。
60/// 一個profile 可能定義了附加的標識位或者通過修改payload type 域中的位數量來指定沒有標識位.
61/// The interpretation of the marker is defined by a profile. It is intended to allow significant
62/// events such as frame boundaries to be marked in the packet stream. A profile may define
63/// additional marker bits or specify that there is no marker bit by changing the number of bits
64/// in the payload type field.
65///</summary> 66publicint Marker { get { return0; } }
67 68///<summary> 69/// payload type (PT):7 bits
70/// 這個字段定一個RTPpayload 的格式和在應用中定義解釋。
71/// profile 可能指定一個從payload type 碼字到payload format 的默認靜態映射。
72/// 也可以通過non-RTP 方法來定義附加的payload type 碼字(見第3 章)。
73/// 在 RFC 3551[1]中定義了一系列的默認音視頻映射。
74/// 一個RTP 源有可能在會話中改變payload type,但是這個域在復用獨立的媒體時是不同的。(見5.2 節)。
75/// 接收者必須忽略它不識別的payload type。
76/// This field identifies the format of the RTP payload and determines its interpretation by the
77/// application. A profile may specify a default static mapping of payload type codes to payload
78/// formats. Additional payload type codes may be defined dynamically through non-RTP means
79/// (see Section 3). A set of default mappings for audio and video is specified in the companion
80/// RFC 3551 [1]. An RTP source may change the payload type during a session, but this field
81/// should not be used for multiplexing separate media streams (see Section 5.2).
82/// A receiver must ignore packets with payload types that it does not understand.
83///</summary> 84public RtpPayloadType PayloadType { get; privateset; }
85 86///<summary> 87/// sequence number:16 bits
88/// 每發送一個RTP 數據報文序列號值加一,接收者也可用來檢測丟失的包或者重建報文序列。
89/// 初始的值是隨機的,這樣就使得known-plaintext 攻擊更加困難, 即使源并沒有加密(見9。1),
90/// 因為要通過的translator 會做這些事情。關于選擇隨機數方面的技術見[17]。
91/// The sequence number increments by one for each RTP data packet sent, and may be used
92/// by the receiver to detect packet loss and to restore packet sequence. The initial value of the
93/// sequence number should be random (unpredictable) to make known-plaintext attacks on
94/// encryption more dificult, even if the source itself does not encrypt according to the method
95/// in Section 9.1, because the packets may flow through a translator that does. Techniques for
96/// choosing unpredictable numbers are discussed in [17].
97///</summary> 98publicint SequenceNumber { get; privateset; }
99100///<summary>101/// timestamp:32 bits
102/// timestamp 反映的是RTP 數據報文中的第一個字段的采樣時刻的時間瞬時值。
103/// 采樣時間值必須是從恒定的和線性的時間中得到以便于同步和jitter 計算(見第6.4.1 節)。
104/// 必須保證同步和測量保溫jitter 到來所需要的時間精度(一幀一個tick 一般情況下是不夠的)。
105/// 時鐘頻率是與payload 所攜帶的數據格式有關的,在profile 中靜態的定義或是在定義格式的payload format 中,
106/// 或通過non-RTP 方法所定義的payload format 中動態的定義。如果RTP 報文周期的生成,就采用虛擬的(nominal)
107/// 采樣時鐘而不是從系統時鐘讀數。例如,在固定比特率的音頻中,timestamp 時鐘會在每個采樣周期時加一。
108/// 如果音頻應用中從輸入設備中讀入160 個采樣周期的塊,the timestamp 就會每一塊增加160,
109/// 而不管塊是否傳輸了或是丟棄了。
110/// 對于序列號來說,timestamp 初始值是隨機的。只要它們是同時(邏輯上)同時生成的,
111/// 這些連續的的 RTP 報文就會有相同的timestamp,
112/// 例如,同屬一個視頻幀。正像在MPEG 中內插視頻幀一樣,
113/// 連續的但不是按順序發送的RTP 報文可能含有相同的timestamp。
114/// The timestamp reflects the sampling instant of the first octet in the RTP data packet. The
115/// sampling instant must be derived from a clock that increments monotonically and linearly
116/// in time to allow synchronization and jitter calculations (see Section 6.4.1). The resolution
117/// of the clock must be suficient for the desired synchronization accuracy and for measuring
118/// packet arrival jitter (one tick per video frame is typically not suficient). The clock frequency
119/// is dependent on the format of data carried as payload and is specified statically in the profile
120/// or payload format specification that defines the format, or may be specified dynamically for
121/// payload formats defined through non-RTP means. If RTP packets are generated periodically,
122/// the nominal sampling instant as determined from the sampling clock is to be used, not a
123/// reading of the system clock. As an example, for fixed-rate audio the timestamp clock would
124/// likely increment by one for each sampling period. If an audio application reads blocks covering
125/// 160 sampling periods from the input device, the timestamp would be increased by 160 for
126/// each such block, regardless of whether the block is transmitted in a packet or dropped as silent.
127///</summary>128publiclong Timestamp { get; privateset; }
129130///<summary>131/// SSRC:32 bits
132/// SSRC 域識別同步源。為了防止在一個會話中有相同的同步源有相同的SSRC identifier,
133/// 這個identifier 必須隨機選取。
134/// 生成隨機 identifier 的算法見目錄A.6 。雖然選擇相同的identifier 概率很小,
135/// 但是所有的RTP implementation 必須檢測和解決沖突。
136/// 第8 章描述了沖突的概率和解決機制和RTP 級的檢測機制,根據唯一的 SSRCidentifier 前向循環。
137/// 如果有源改變了它的源傳輸地址,
138/// 就必須為它選擇一個新的SSRCidentifier 來避免被識別為循環過的源(見第8.2 節)。
139/// The SSRC field identifies the synchronization source. This identifier should be chosen
140/// randomly, with the intent that no two synchronization sources within the same RTP session
141/// will have the same SSRC identifier. An example algorithm for generating a random identifier
142/// is presented in Appendix A.6. Although the probability of multiple sources choosing the same
143/// identifier is low, all RTP implementations must be prepared to detect and resolve collisions.
144/// Section 8 describes the probability of collision along with a mechanism for resolving collisions
145/// and detecting RTP-level forwarding loops based on the uniqueness of the SSRC identifier. If
146/// a source changes its source transport address, it must also choose a new SSRC identifier to
147/// avoid being interpreted as a looped source (see Section 8.2).
148///</summary>149publicint SSRC { get { return0; } }
150151///<summary>152/// 每一個RTP包中都有前12個字節定長的頭字段
153/// The first twelve octets are present in every RTP packet
154///</summary>155publicconstint HeaderSize = 12;
156///<summary>157/// RTP消息頭
158///</summary>159privatebyte[] _header;
160///<summary>161/// RTP消息頭
162///</summary>163publicbyte[] Header { get { return _header; } }
164165///<summary>166/// RTP有效載荷長度
167///</summary>168privateint _payloadSize;
169///<summary>170/// RTP有效載荷長度
171///</summary>172publicint PayloadSize { get { return _payloadSize; } }
173174///<summary>175/// RTP有效載荷
176///</summary>177privatebyte[] _payload;
178///<summary>179/// RTP有效載荷
180///</summary>181publicbyte[] Payload { get { return _payload; } }
182183///<summary>184/// RTP消息總長度,包括Header和Payload
185///</summary>186publicint Length { get { return HeaderSize + PayloadSize; } }
187188///<summary>189/// RTP(RFC3550)協議數據包
190///</summary>191///<param name="playloadType">數據報文有效載荷類型</param>192///<param name="sequenceNumber">數據報文序列號值</param>193///<param name="timestamp">數據報文采樣時刻</param>194///<param name="data">數據</param>195///<param name="dataSize">數據長度</param>196public RtpPacket(
197 RtpPayloadType playloadType,
198int sequenceNumber,
199long timestamp,
200byte[] data,
201int dataSize)
202 {
203// fill changing header fields204 SequenceNumber = sequenceNumber;
205 Timestamp = timestamp;
206 PayloadType = playloadType;
207208// build the header bistream209 _header = newbyte[HeaderSize];
210211// fill the header array of byte with RTP header fields212 _header[0] = (byte)((Version << 6) | (Padding << 5) | (Extension << 4) | CC);
213 _header[1] = (byte)((Marker << 7) | (int)PayloadType);
214 _header[2] = (byte)(SequenceNumber >> 8);
215 _header[3] = (byte)(SequenceNumber);
216for (int i = 0; i < 4; i++)
217 {
218 _header[7 - i] = (byte)(Timestamp >> (8 * i));
219 }
220for (int i = 0; i < 4; i++)
221 {
222 _header[11 - i] = (byte)(SSRC >> (8 * i));
223 }
224225// fill the payload bitstream226 _payload = newbyte[dataSize];
227 _payloadSize = dataSize;
228229// fill payload array of byte from data (given in parameter of the constructor)230 Array.Copy(data, 0, _payload, 0, dataSize);
231 }
232233///<summary>234/// RTP(RFC3550)協議數據包
235///</summary>236///<param name="playloadType">數據報文有效載荷類型</param>237///<param name="sequenceNumber">數據報文序列號值</param>238///<param name="timestamp">數據報文采樣時刻</param>239///<param name="frame">圖片</param>240public RtpPacket(
241 RtpPayloadType playloadType,
242int sequenceNumber,
243long timestamp,
244 Image frame)
245 {
246// fill changing header fields247 SequenceNumber = sequenceNumber;
248 Timestamp = timestamp;
249 PayloadType = playloadType;
250251// build the header bistream252 _header = newbyte[HeaderSize];
253254// fill the header array of byte with RTP header fields255 _header[0] = (byte)((Version << 6) | (Padding << 5) | (Extension << 4) | CC);
256 _header[1] = (byte)((Marker << 7) | (int)PayloadType);
257 _header[2] = (byte)(SequenceNumber >> 8);
258 _header[3] = (byte)(SequenceNumber);
259for (int i = 0; i < 4; i++)
260 {
261 _header[7 - i] = (byte)(Timestamp >> (8 * i));
262 }
263for (int i = 0; i < 4; i++)
264 {
265 _header[11 - i] = (byte)(SSRC >> (8 * i));
266 }
267268// fill the payload bitstream269using (MemoryStream ms = new MemoryStream())
270 {
271 frame.Save(ms, ImageFormat.Jpeg);
272 _payload = ms.ToArray();
273 _payloadSize = _payload.Length;
274 }
275 }
276277///<summary>278/// RTP(RFC3550)協議數據包
279///</summary>280///<param name="packet">數據包</param>281///<param name="packetSize">數據包長度</param>282public RtpPacket(byte[] packet, int packetSize)
283 {
284//check if total packet size is lower than the header size285if (packetSize >= HeaderSize)
286 {
287//get the header bitsream288 _header = newbyte[HeaderSize];
289for (int i = 0; i < HeaderSize; i++)
290 {
291 _header[i] = packet[i];
292 }
293294//get the payload bitstream295 _payloadSize = packetSize - HeaderSize;
296 _payload = newbyte[_payloadSize];
297for (int i = HeaderSize; i < packetSize; i++)
298 {
299 _payload[i - HeaderSize] = packet[i];
300 }
301302//interpret the changing fields of the header303 PayloadType = (RtpPayloadType)(_header[1] & 127);
304 SequenceNumber = UnsignedInt(_header[3]) + 256 * UnsignedInt(_header[2]);
305 Timestamp = UnsignedInt(_header[7])
306 + 256 * UnsignedInt(_header[6])
307 + 65536 * UnsignedInt(_header[5])
308 + 16777216 * UnsignedInt(_header[4]);
309 }
310 }
311312///<summary>313/// 將消息轉換成byte數組
314///</summary>315///<returns>消息byte數組</returns>316publicbyte[] ToArray()
317 {
318byte[] packet = newbyte[Length];
319320 Array.Copy(_header, 0, packet, 0, HeaderSize);
321 Array.Copy(_payload, 0, packet, HeaderSize, PayloadSize);
322323return packet;
324 }
325326///<summary>327/// 將消息體轉換成圖片
328///</summary>329///<returns>圖片</returns>330public Bitmap ToBitmap()
331 {
332returnnew Bitmap(new MemoryStream(_payload));
333 }
334335///<summary>336/// 將消息體轉換成圖片
337///</summary>338///<returns>圖片</returns>339public Image ToImage()
340 {
341return Image.FromStream(new MemoryStream(_payload));
342 }
343344///<summary>345/// 將圖片轉換成消息
346///</summary>347///<param name="playloadType">數據報文有效載荷類型</param>348///<param name="sequenceNumber">數據報文序列號值</param>349///<param name="timestamp">數據報文采樣時刻</param>350///<param name="frame">圖片幀</param>351///<returns>352/// RTP消息
353///</returns>354publicstatic RtpPacket FromImage(
355 RtpPayloadType playloadType,
356int sequenceNumber,
357long timestamp,
358 Image frame)
359 {
360returnnew RtpPacket(playloadType, sequenceNumber, timestamp, frame);
361 }
362363///<summary>364/// return the unsigned value of 8-bit integer nb
365///</summary>366///<param name="nb"></param>367///<returns></returns>368privatestaticint UnsignedInt(int nb)
369 {
370if (nb >= 0)
371return (nb);
372else373return (256 + nb);
374 }
375 }