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
47namespace webrtc {
48
49RtpData* NullObjectRtpData() {
50  static NullRtpData null_rtp_data;
51  return &null_rtp_data;
52}
53
54RtpFeedback* NullObjectRtpFeedback() {
55  static NullRtpFeedback null_rtp_feedback;
56  return &null_rtp_feedback;
57}
58
59RtpAudioFeedback* NullObjectRtpAudioFeedback() {
60  static NullRtpAudioFeedback null_rtp_audio_feedback;
61  return &null_rtp_audio_feedback;
62}
63
64ReceiveStatistics* NullObjectReceiveStatistics() {
65  static NullReceiveStatistics null_receive_statistics;
66  return &null_receive_statistics;
67}
68
69namespace RtpUtility {
70
71enum {
72  kRtcpExpectedVersion = 2,
73  kRtcpMinHeaderLength = 4,
74  kRtcpMinParseLength = 8,
75
76  kRtpExpectedVersion = 2,
77  kRtpMinParseLength = 12
78};
79
80/*
81 * Time routines.
82 */
83
84uint32_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
98uint32_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
104uint32_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)
117bool 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)
122bool 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*/
132void 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
144void 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
156void 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
166uint16_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
174uint32_t BufferToUWord24(const uint8_t* dataBuffer) {
175  return (dataBuffer[0] << 16) + (dataBuffer[1] << 8) + dataBuffer[2];
176}
177
178uint32_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
187uint32_t pow2(uint8_t exp) {
188  return 1 << exp;
189}
190
191RtpHeaderParser::RtpHeaderParser(const uint8_t* rtpData,
192                                 const size_t rtpDataLength)
193    : _ptrRTPDataBegin(rtpData),
194      _ptrRTPDataEnd(rtpData ? (rtpData + rtpDataLength) : NULL) {
195}
196
197RtpHeaderParser::~RtpHeaderParser() {
198}
199
200bool 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
275bool 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
304bool 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
417void 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
528uint8_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