• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
12 
13 #include <assert.h>
14 #include <math.h>  // ceil
15 #include <string.h>  // memcpy
16 
17 #if defined(_WIN32)
18 // Order for these headers are important
19 #include <Windows.h>  // FILETIME
20 
21 #include <WinSock.h>  // timeval
22 
23 #include <MMSystem.h>  // timeGetTime
24 #elif ((defined WEBRTC_LINUX) || (defined WEBRTC_MAC))
25 #include <sys/time.h>  // gettimeofday
26 #include <time.h>
27 #endif
28 #if (defined(_DEBUG) && defined(_WIN32) && (_MSC_VER >= 1400))
29 #include <stdio.h>
30 #endif
31 
32 #include "webrtc/system_wrappers/interface/tick_util.h"
33 #include "webrtc/system_wrappers/interface/logging.h"
34 
35 #if (defined(_DEBUG) && defined(_WIN32) && (_MSC_VER >= 1400))
36 #define DEBUG_PRINT(...)           \
37   {                                \
38     char msg[256];                 \
39     sprintf(msg, __VA_ARGS__);     \
40     OutputDebugString(msg);        \
41   }
42 #else
43 // special fix for visual 2003
44 #define DEBUG_PRINT(exp)        ((void)0)
45 #endif  // defined(_DEBUG) && defined(_WIN32)
46 
47 namespace webrtc {
48 
NullObjectRtpData()49 RtpData* NullObjectRtpData() {
50   static NullRtpData null_rtp_data;
51   return &null_rtp_data;
52 }
53 
NullObjectRtpFeedback()54 RtpFeedback* NullObjectRtpFeedback() {
55   static NullRtpFeedback null_rtp_feedback;
56   return &null_rtp_feedback;
57 }
58 
NullObjectRtpAudioFeedback()59 RtpAudioFeedback* NullObjectRtpAudioFeedback() {
60   static NullRtpAudioFeedback null_rtp_audio_feedback;
61   return &null_rtp_audio_feedback;
62 }
63 
NullObjectReceiveStatistics()64 ReceiveStatistics* NullObjectReceiveStatistics() {
65   static NullReceiveStatistics null_receive_statistics;
66   return &null_receive_statistics;
67 }
68 
69 namespace RtpUtility {
70 
71 enum {
72   kRtcpExpectedVersion = 2,
73   kRtcpMinHeaderLength = 4,
74   kRtcpMinParseLength = 8,
75 
76   kRtpExpectedVersion = 2,
77   kRtpMinParseLength = 12
78 };
79 
80 /*
81  * Time routines.
82  */
83 
GetCurrentRTP(Clock * clock,uint32_t freq)84 uint32_t GetCurrentRTP(Clock* clock, uint32_t freq) {
85   const bool use_global_clock = (clock == NULL);
86   Clock* local_clock = clock;
87   if (use_global_clock) {
88     local_clock = Clock::GetRealTimeClock();
89   }
90   uint32_t secs = 0, frac = 0;
91   local_clock->CurrentNtp(secs, frac);
92   if (use_global_clock) {
93     delete local_clock;
94   }
95   return ConvertNTPTimeToRTP(secs, frac, freq);
96 }
97 
ConvertNTPTimeToRTP(uint32_t NTPsec,uint32_t NTPfrac,uint32_t freq)98 uint32_t ConvertNTPTimeToRTP(uint32_t NTPsec, uint32_t NTPfrac, uint32_t freq) {
99   float ftemp = (float)NTPfrac / (float)NTP_FRAC;
100   uint32_t tmp = (uint32_t)(ftemp * freq);
101   return NTPsec * freq + tmp;
102 }
103 
ConvertNTPTimeToMS(uint32_t NTPsec,uint32_t NTPfrac)104 uint32_t ConvertNTPTimeToMS(uint32_t NTPsec, uint32_t NTPfrac) {
105   int freq = 1000;
106   float ftemp = (float)NTPfrac / (float)NTP_FRAC;
107   uint32_t tmp = (uint32_t)(ftemp * freq);
108   uint32_t MStime = NTPsec * freq + tmp;
109   return MStime;
110 }
111 
112 /*
113  * Misc utility routines
114  */
115 
116 #if defined(_WIN32)
StringCompare(const char * str1,const char * str2,const uint32_t length)117 bool StringCompare(const char* str1, const char* str2,
118                    const uint32_t length) {
119   return (_strnicmp(str1, str2, length) == 0) ? true : false;
120 }
121 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
StringCompare(const char * str1,const char * str2,const uint32_t length)122 bool StringCompare(const char* str1, const char* str2,
123                    const uint32_t length) {
124   return (strncasecmp(str1, str2, length) == 0) ? true : false;
125 }
126 #endif
127 
128 /* for RTP/RTCP
129     All integer fields are carried in network byte order, that is, most
130     significant byte (octet) first.  AKA big-endian.
131 */
AssignUWord32ToBuffer(uint8_t * dataBuffer,uint32_t value)132 void AssignUWord32ToBuffer(uint8_t* dataBuffer, uint32_t value) {
133 #if defined(WEBRTC_ARCH_LITTLE_ENDIAN)
134   dataBuffer[0] = static_cast<uint8_t>(value >> 24);
135   dataBuffer[1] = static_cast<uint8_t>(value >> 16);
136   dataBuffer[2] = static_cast<uint8_t>(value >> 8);
137   dataBuffer[3] = static_cast<uint8_t>(value);
138 #else
139   uint32_t* ptr = reinterpret_cast<uint32_t*>(dataBuffer);
140   ptr[0] = value;
141 #endif
142 }
143 
AssignUWord24ToBuffer(uint8_t * dataBuffer,uint32_t value)144 void AssignUWord24ToBuffer(uint8_t* dataBuffer, uint32_t value) {
145 #if defined(WEBRTC_ARCH_LITTLE_ENDIAN)
146   dataBuffer[0] = static_cast<uint8_t>(value >> 16);
147   dataBuffer[1] = static_cast<uint8_t>(value >> 8);
148   dataBuffer[2] = static_cast<uint8_t>(value);
149 #else
150   dataBuffer[0] = static_cast<uint8_t>(value);
151   dataBuffer[1] = static_cast<uint8_t>(value >> 8);
152   dataBuffer[2] = static_cast<uint8_t>(value >> 16);
153 #endif
154 }
155 
AssignUWord16ToBuffer(uint8_t * dataBuffer,uint16_t value)156 void AssignUWord16ToBuffer(uint8_t* dataBuffer, uint16_t value) {
157 #if defined(WEBRTC_ARCH_LITTLE_ENDIAN)
158   dataBuffer[0] = static_cast<uint8_t>(value >> 8);
159   dataBuffer[1] = static_cast<uint8_t>(value);
160 #else
161   uint16_t* ptr = reinterpret_cast<uint16_t*>(dataBuffer);
162   ptr[0] = value;
163 #endif
164 }
165 
BufferToUWord16(const uint8_t * dataBuffer)166 uint16_t BufferToUWord16(const uint8_t* dataBuffer) {
167 #if defined(WEBRTC_ARCH_LITTLE_ENDIAN)
168   return (dataBuffer[0] << 8) + dataBuffer[1];
169 #else
170   return *reinterpret_cast<const uint16_t*>(dataBuffer);
171 #endif
172 }
173 
BufferToUWord24(const uint8_t * dataBuffer)174 uint32_t BufferToUWord24(const uint8_t* dataBuffer) {
175   return (dataBuffer[0] << 16) + (dataBuffer[1] << 8) + dataBuffer[2];
176 }
177 
BufferToUWord32(const uint8_t * dataBuffer)178 uint32_t BufferToUWord32(const uint8_t* dataBuffer) {
179 #if defined(WEBRTC_ARCH_LITTLE_ENDIAN)
180   return (dataBuffer[0] << 24) + (dataBuffer[1] << 16) + (dataBuffer[2] << 8) +
181       dataBuffer[3];
182 #else
183   return *reinterpret_cast<const uint32_t*>(dataBuffer);
184 #endif
185 }
186 
pow2(uint8_t exp)187 uint32_t pow2(uint8_t exp) {
188   return 1 << exp;
189 }
190 
RtpHeaderParser(const uint8_t * rtpData,const size_t rtpDataLength)191 RtpHeaderParser::RtpHeaderParser(const uint8_t* rtpData,
192                                  const size_t rtpDataLength)
193     : _ptrRTPDataBegin(rtpData),
194       _ptrRTPDataEnd(rtpData ? (rtpData + rtpDataLength) : NULL) {
195 }
196 
~RtpHeaderParser()197 RtpHeaderParser::~RtpHeaderParser() {
198 }
199 
RTCP() const200 bool RtpHeaderParser::RTCP() const {
201   // 72 to 76 is reserved for RTP
202   // 77 to 79 is not reserver but  they are not assigned we will block them
203   // for RTCP 200 SR  == marker bit + 72
204   // for RTCP 204 APP == marker bit + 76
205   /*
206   *       RTCP
207   *
208   * FIR      full INTRA-frame request             192     [RFC2032]   supported
209   * NACK     negative acknowledgement             193     [RFC2032]
210   * IJ       Extended inter-arrival jitter report 195     [RFC-ietf-avt-rtp-toff
211   * set-07.txt] http://tools.ietf.org/html/draft-ietf-avt-rtp-toffset-07
212   * SR       sender report                        200     [RFC3551]   supported
213   * RR       receiver report                      201     [RFC3551]   supported
214   * SDES     source description                   202     [RFC3551]   supported
215   * BYE      goodbye                              203     [RFC3551]   supported
216   * APP      application-defined                  204     [RFC3551]   ignored
217   * RTPFB    Transport layer FB message           205     [RFC4585]   supported
218   * PSFB     Payload-specific FB message          206     [RFC4585]   supported
219   * XR       extended report                      207     [RFC3611]   supported
220   */
221 
222   /* 205       RFC 5104
223    * FMT 1      NACK       supported
224    * FMT 2      reserved
225    * FMT 3      TMMBR      supported
226    * FMT 4      TMMBN      supported
227    */
228 
229   /* 206      RFC 5104
230   * FMT 1:     Picture Loss Indication (PLI)                      supported
231   * FMT 2:     Slice Lost Indication (SLI)
232   * FMT 3:     Reference Picture Selection Indication (RPSI)
233   * FMT 4:     Full Intra Request (FIR) Command                   supported
234   * FMT 5:     Temporal-Spatial Trade-off Request (TSTR)
235   * FMT 6:     Temporal-Spatial Trade-off Notification (TSTN)
236   * FMT 7:     Video Back Channel Message (VBCM)
237   * FMT 15:    Application layer FB message
238   */
239 
240   const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
241   if (length < kRtcpMinHeaderLength) {
242     return false;
243   }
244 
245   const uint8_t V  = _ptrRTPDataBegin[0] >> 6;
246   if (V != kRtcpExpectedVersion) {
247     return false;
248   }
249 
250   const uint8_t  payloadType = _ptrRTPDataBegin[1];
251   bool RTCP = false;
252   switch (payloadType) {
253     case 192:
254       RTCP = true;
255       break;
256     case 193:
257       // not supported
258       // pass through and check for a potential RTP packet
259       break;
260     case 195:
261     case 200:
262     case 201:
263     case 202:
264     case 203:
265     case 204:
266     case 205:
267     case 206:
268     case 207:
269       RTCP = true;
270       break;
271   }
272   return RTCP;
273 }
274 
ParseRtcp(RTPHeader * header) const275 bool RtpHeaderParser::ParseRtcp(RTPHeader* header) const {
276   assert(header != NULL);
277 
278   const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
279   if (length < kRtcpMinParseLength) {
280     return false;
281   }
282 
283   const uint8_t V = _ptrRTPDataBegin[0] >> 6;
284   if (V != kRtcpExpectedVersion) {
285     return false;
286   }
287 
288   const uint8_t PT = _ptrRTPDataBegin[1];
289   const uint16_t len = (_ptrRTPDataBegin[2] << 8) + _ptrRTPDataBegin[3];
290   const uint8_t* ptr = &_ptrRTPDataBegin[4];
291 
292   uint32_t SSRC = *ptr++ << 24;
293   SSRC += *ptr++ << 16;
294   SSRC += *ptr++ << 8;
295   SSRC += *ptr++;
296 
297   header->payloadType  = PT;
298   header->ssrc         = SSRC;
299   header->headerLength = 4 + (len << 2);
300 
301   return true;
302 }
303 
Parse(RTPHeader & header,RtpHeaderExtensionMap * ptrExtensionMap) const304 bool RtpHeaderParser::Parse(RTPHeader& header,
305                             RtpHeaderExtensionMap* ptrExtensionMap) const {
306   const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
307   if (length < kRtpMinParseLength) {
308     return false;
309   }
310 
311   // Version
312   const uint8_t V  = _ptrRTPDataBegin[0] >> 6;
313   // Padding
314   const bool          P  = ((_ptrRTPDataBegin[0] & 0x20) == 0) ? false : true;
315   // eXtension
316   const bool          X  = ((_ptrRTPDataBegin[0] & 0x10) == 0) ? false : true;
317   const uint8_t CC = _ptrRTPDataBegin[0] & 0x0f;
318   const bool          M  = ((_ptrRTPDataBegin[1] & 0x80) == 0) ? false : true;
319 
320   const uint8_t PT = _ptrRTPDataBegin[1] & 0x7f;
321 
322   const uint16_t sequenceNumber = (_ptrRTPDataBegin[2] << 8) +
323       _ptrRTPDataBegin[3];
324 
325   const uint8_t* ptr = &_ptrRTPDataBegin[4];
326 
327   uint32_t RTPTimestamp = *ptr++ << 24;
328   RTPTimestamp += *ptr++ << 16;
329   RTPTimestamp += *ptr++ << 8;
330   RTPTimestamp += *ptr++;
331 
332   uint32_t SSRC = *ptr++ << 24;
333   SSRC += *ptr++ << 16;
334   SSRC += *ptr++ << 8;
335   SSRC += *ptr++;
336 
337   if (V != kRtpExpectedVersion) {
338     return false;
339   }
340 
341   const uint8_t CSRCocts = CC * 4;
342 
343   if ((ptr + CSRCocts) > _ptrRTPDataEnd) {
344     return false;
345   }
346 
347   header.markerBit      = M;
348   header.payloadType    = PT;
349   header.sequenceNumber = sequenceNumber;
350   header.timestamp      = RTPTimestamp;
351   header.ssrc           = SSRC;
352   header.numCSRCs       = CC;
353   header.paddingLength  = P ? *(_ptrRTPDataEnd - 1) : 0;
354 
355   for (unsigned int i = 0; i < CC; ++i) {
356     uint32_t CSRC = *ptr++ << 24;
357     CSRC += *ptr++ << 16;
358     CSRC += *ptr++ << 8;
359     CSRC += *ptr++;
360     header.arrOfCSRCs[i] = CSRC;
361   }
362 
363   header.headerLength   = 12 + CSRCocts;
364 
365   // If in effect, MAY be omitted for those packets for which the offset
366   // is zero.
367   header.extension.hasTransmissionTimeOffset = false;
368   header.extension.transmissionTimeOffset = 0;
369 
370   // May not be present in packet.
371   header.extension.hasAbsoluteSendTime = false;
372   header.extension.absoluteSendTime = 0;
373 
374   // May not be present in packet.
375   header.extension.hasAudioLevel = false;
376   header.extension.audioLevel = 0;
377 
378   if (X) {
379     /* RTP header extension, RFC 3550.
380      0                   1                   2                   3
381      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
382     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
383     |      defined by profile       |           length              |
384     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
385     |                        header extension                       |
386     |                             ....                              |
387     */
388     const ptrdiff_t remain = _ptrRTPDataEnd - ptr;
389     if (remain < 4) {
390       return false;
391     }
392 
393     header.headerLength += 4;
394 
395     uint16_t definedByProfile = *ptr++ << 8;
396     definedByProfile += *ptr++;
397 
398     uint16_t XLen = *ptr++ << 8;
399     XLen += *ptr++; // in 32 bit words
400     XLen *= 4; // in octs
401 
402     if (remain < (4 + XLen)) {
403       return false;
404     }
405     if (definedByProfile == kRtpOneByteHeaderExtensionId) {
406       const uint8_t* ptrRTPDataExtensionEnd = ptr + XLen;
407       ParseOneByteExtensionHeader(header,
408                                   ptrExtensionMap,
409                                   ptrRTPDataExtensionEnd,
410                                   ptr);
411     }
412     header.headerLength += XLen;
413   }
414   return true;
415 }
416 
ParseOneByteExtensionHeader(RTPHeader & header,const RtpHeaderExtensionMap * ptrExtensionMap,const uint8_t * ptrRTPDataExtensionEnd,const uint8_t * ptr) const417 void RtpHeaderParser::ParseOneByteExtensionHeader(
418     RTPHeader& header,
419     const RtpHeaderExtensionMap* ptrExtensionMap,
420     const uint8_t* ptrRTPDataExtensionEnd,
421     const uint8_t* ptr) const {
422   if (!ptrExtensionMap) {
423     return;
424   }
425 
426   while (ptrRTPDataExtensionEnd - ptr > 0) {
427     //  0
428     //  0 1 2 3 4 5 6 7
429     // +-+-+-+-+-+-+-+-+
430     // |  ID   |  len  |
431     // +-+-+-+-+-+-+-+-+
432 
433     // Note that 'len' is the header extension element length, which is the
434     // number of bytes - 1.
435     const uint8_t id = (*ptr & 0xf0) >> 4;
436     const uint8_t len = (*ptr & 0x0f);
437     ptr++;
438 
439     if (id == 15) {
440       LOG(LS_WARNING)
441           << "RTP extension header 15 encountered. Terminate parsing.";
442       return;
443     }
444 
445     RTPExtensionType type;
446     if (ptrExtensionMap->GetType(id, &type) != 0) {
447       // If we encounter an unknown extension, just skip over it.
448       LOG(LS_WARNING) << "Failed to find extension id: "
449                       << static_cast<int>(id);
450     } else {
451       switch (type) {
452         case kRtpExtensionTransmissionTimeOffset: {
453           if (len != 2) {
454             LOG(LS_WARNING) << "Incorrect transmission time offset len: "
455                             << len;
456             return;
457           }
458           //  0                   1                   2                   3
459           //  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
460           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
461           // |  ID   | len=2 |              transmission offset              |
462           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
463 
464           int32_t transmissionTimeOffset = ptr[0] << 16;
465           transmissionTimeOffset += ptr[1] << 8;
466           transmissionTimeOffset += ptr[2];
467           header.extension.transmissionTimeOffset =
468               transmissionTimeOffset;
469           if (transmissionTimeOffset & 0x800000) {
470             // Negative offset, correct sign for Word24 to Word32.
471             header.extension.transmissionTimeOffset |= 0xFF000000;
472           }
473           header.extension.hasTransmissionTimeOffset = true;
474           break;
475         }
476         case kRtpExtensionAudioLevel: {
477           if (len != 0) {
478             LOG(LS_WARNING) << "Incorrect audio level len: " << len;
479             return;
480           }
481           //  0                   1                   2                   3
482           //  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
483           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
484           // |  ID   | len=0 |V|   level     |      0x00     |      0x00     |
485           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
486           //
487 
488           // Parse out the fields but only use it for debugging for now.
489           // const uint8_t V = (*ptr & 0x80) >> 7;
490           // const uint8_t level = (*ptr & 0x7f);
491           // DEBUG_PRINT("RTP_AUDIO_LEVEL_UNIQUE_ID: ID=%u, len=%u, V=%u,
492           // level=%u", ID, len, V, level);
493 
494           header.extension.audioLevel = ptr[0];
495           header.extension.hasAudioLevel = true;
496           break;
497         }
498         case kRtpExtensionAbsoluteSendTime: {
499           if (len != 2) {
500             LOG(LS_WARNING) << "Incorrect absolute send time len: " << len;
501             return;
502           }
503           //  0                   1                   2                   3
504           //  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
505           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
506           // |  ID   | len=2 |              absolute send time               |
507           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
508 
509           uint32_t absoluteSendTime = ptr[0] << 16;
510           absoluteSendTime += ptr[1] << 8;
511           absoluteSendTime += ptr[2];
512           header.extension.absoluteSendTime = absoluteSendTime;
513           header.extension.hasAbsoluteSendTime = true;
514           break;
515         }
516         default: {
517           LOG(LS_WARNING) << "Extension type not implemented: " << type;
518           return;
519         }
520       }
521     }
522     ptr += (len + 1);
523     uint8_t num_bytes = ParsePaddingBytes(ptrRTPDataExtensionEnd, ptr);
524     ptr += num_bytes;
525   }
526 }
527 
ParsePaddingBytes(const uint8_t * ptrRTPDataExtensionEnd,const uint8_t * ptr) const528 uint8_t RtpHeaderParser::ParsePaddingBytes(
529     const uint8_t* ptrRTPDataExtensionEnd,
530     const uint8_t* ptr) const {
531   uint8_t num_zero_bytes = 0;
532   while (ptrRTPDataExtensionEnd - ptr > 0) {
533     if (*ptr != 0) {
534       return num_zero_bytes;
535     }
536     ptr++;
537     num_zero_bytes++;
538   }
539   return num_zero_bytes;
540 }
541 }  // namespace RtpUtility
542 
543 }  // namespace webrtc
544